├── .gitignore ├── 3.1池式组件 ├── 3.1.1手写线程池与性能分析 │ ├── .gitignore │ ├── 1.picture │ │ └── 线程池解析.png │ ├── 2.doc │ │ └── 手写线程池与性能分析.pdf │ ├── CMakeLists.txt │ ├── README.md │ └── src │ │ ├── example │ │ └── thread_pool.c │ │ └── practice │ │ └── thread_pool_hw.c ├── 3.1.2内存池的实现与场景分析 │ ├── .gitignore │ ├── 1.picture │ │ ├── 内存池.png │ │ ├── 内存池模型.png │ │ └── 内存池结构体.png │ ├── 2.doc │ │ ├── The Slab Allocator An Object-Caching Kernel Memory Allocator.pdf │ │ └── 内存池的实现与场景分析.pdf │ ├── CMakeLists.txt │ ├── README.md │ └── src │ │ ├── example │ │ └── mmpool.c │ │ └── practice │ │ └── mmpool_hw.c ├── 3.1.3异步请求池的实现 │ ├── .gitignore │ ├── 1.picture │ │ └── 异步请求池.jpg │ ├── 2.doc │ │ └── 异步请求池框架实现.pdf │ ├── CMakeLists.txt │ ├── README.md │ └── src │ │ ├── async │ │ ├── async_dns_client_noblock.c │ │ ├── sync_dns_client-课上手写.c │ │ └── sync_dns_client.c │ │ └── practice │ │ ├── async_dns_client_noblock_hw.c │ │ └── sync_dns_client_hw.c └── 3.1.4mysql连接池的实现 │ ├── .gitignore │ ├── 1.Picture │ └── 课上示图-20211211.png │ ├── 2.doc │ ├── mysql连接池和redis连接池的实现20211211.pdf │ └── 作业.txt │ ├── CMakeLists.txt │ ├── hiredis │ ├── .gitignore │ ├── .travis.yml │ ├── CHANGELOG.md │ ├── CMakeLists.txt │ ├── COPYING │ ├── Makefile │ ├── README.md │ ├── adapters │ │ ├── ae.h │ │ ├── glib.h │ │ ├── ivykis.h │ │ ├── libev.h │ │ ├── libevent.h │ │ ├── libuv.h │ │ ├── macosx.h │ │ └── qt.h │ ├── alloc.c │ ├── alloc.h │ ├── appveyor.yml │ ├── async.c │ ├── async.h │ ├── async_private.h │ ├── dict.c │ ├── dict.h │ ├── examples │ │ ├── CMakeLists.txt │ │ ├── example-ae.c │ │ ├── example-glib.c │ │ ├── example-ivykis.c │ │ ├── example-libev.c │ │ ├── example-libevent-ssl.c │ │ ├── example-libevent.c │ │ ├── example-libuv.c │ │ ├── example-macosx.c │ │ ├── example-push.c │ │ ├── example-qt.cpp │ │ ├── example-qt.h │ │ ├── example-ssl.c │ │ ├── example.c │ │ └── hi │ ├── fmacros.h │ ├── hiredis-config.cmake.in │ ├── hiredis.c │ ├── hiredis.h │ ├── hiredis.pc.in │ ├── hiredis_ssl-config.cmake.in │ ├── hiredis_ssl.h │ ├── hiredis_ssl.pc.in │ ├── net.c │ ├── net.h │ ├── read.c │ ├── read.h │ ├── sds.c │ ├── sds.h │ ├── sdsalloc.h │ ├── sdscompat.h │ ├── sockcompat.c │ ├── sockcompat.h │ ├── ssl.c │ ├── test.c │ ├── test.sh │ └── win32.h │ └── src │ ├── mysql_pool │ ├── .gitignore │ ├── CMakeLists.txt │ ├── DBPool.cpp │ ├── DBPool.h │ ├── IMUser.cpp │ ├── IMUser.h │ ├── README.md │ ├── ZeroThreadpool.cpp │ ├── ZeroThreadpool.h │ ├── test_curd.cpp │ ├── test_dbpool.cpp │ └── win32.h │ ├── mysql_pool_hw │ ├── .gitignore │ ├── CMakeLists.txt │ ├── DBPool.cpp │ ├── DBPool.h │ ├── IMUser.cpp │ ├── IMUser.h │ ├── README.md │ ├── ZeroThreadpool.cpp │ ├── ZeroThreadpool.h │ ├── test_curd_hw.cpp │ ├── test_dbpool_hw.cpp │ └── win32.h │ ├── redis-async-hw │ ├── README.md │ ├── adapter.h │ ├── async.c │ ├── reactor.h │ └── sync.c │ ├── redis-async │ ├── README.md │ ├── adapter.h │ ├── async.c │ ├── reactor.h │ └── sync.c │ ├── redis_pool │ ├── .gitignore │ ├── CMakeLists.txt │ ├── CachePool.cpp │ ├── CachePool.h │ ├── README.md │ ├── Thread.h │ ├── async.c │ ├── async.h │ ├── dict.c │ ├── dict.h │ ├── fmacros.h │ ├── hiredis.c │ ├── hiredis.h │ ├── net.c │ ├── net.h │ ├── read.c │ ├── read.h │ ├── sds.c │ ├── sds.h │ ├── sdsalloc.h │ ├── test_CachePool.cpp │ ├── test_ThreadPool.cpp │ ├── threadpool.h │ └── win32.h │ └── redis_pool_hw │ ├── .gitignore │ ├── CachePool.cpp │ ├── CachePool.h │ ├── Thread.h │ ├── fmacros.h │ ├── test_CachePool.cpp │ ├── test_ThreadPool.cpp │ ├── threadpool.h │ └── win32.h ├── 3.2高性能组件 ├── 3.2.1原子操作CAS与锁实现 │ ├── .gitignore │ ├── 2.doc │ │ └── 锁与原子操作CAS的底层实现.pdf │ ├── CMakeLists.txt │ └── src │ │ ├── example │ │ ├── lock.c │ │ └── trycatch_finally.c │ │ └── practice │ │ ├── lock_hw.c │ │ └── trycatch_finally_hw.c ├── 3.2.2定时器方案红黑树,时间轮,最小堆 │ ├── .gitignore │ ├── 2.doc │ │ └── 定时器方案 红黑树 时间轮 最小堆.pdf │ ├── CMakeLists.txt │ ├── readme.md │ └── timers_src │ │ ├── example │ │ ├── minheap │ │ │ ├── mh-timer.c │ │ │ ├── mh-timer.h │ │ │ ├── minheap.c │ │ │ └── minheap.h │ │ ├── rbtree │ │ │ ├── rbt-timer.c │ │ │ ├── rbt-timer.h │ │ │ ├── rbtree.c │ │ │ └── rbtree.h │ │ ├── skiplist │ │ │ ├── skiplist.c │ │ │ ├── skiplist.h │ │ │ └── skl-timer.c │ │ ├── timewheel │ │ │ ├── spinlock.h │ │ │ ├── timewheel.c │ │ │ ├── timewheel.h │ │ │ └── tw-timer.c │ │ └── timewheel_single │ │ │ └── single_tw.c │ │ └── practice │ │ ├── minheap │ │ ├── mh-timer_hw.c │ │ └── mh-timer_hw.h │ │ ├── rbtree │ │ ├── rbt-timer_hw.c │ │ └── rbt-timer_hw.h │ │ ├── skiplist │ │ └── skl-timer_hw.c │ │ ├── timewheel │ │ ├── timewheel.c │ │ ├── timewheel.h │ │ └── tw-timer_hw.c │ │ └── timewheel_single │ │ └── single_tw_hw.c ├── 3.2.3无锁消息队列实现 │ ├── .gitignore │ ├── 1.picture │ │ └── 上课演示20211218.png │ ├── 2.doc │ │ └── 无锁消息队列实现-课件.pdf │ ├── CMakeLists.txt │ └── src │ │ ├── cas_queue │ │ ├── 1_test_i++.c │ │ ├── 2_test_i++_threads.c │ │ ├── 3_test_mutex_spin_lock.cpp │ │ ├── 4_test_lock_free_queue.cpp │ │ ├── ArrayLockFreeQueue.h │ │ ├── ArrayLockFreeQueueImp.h │ │ ├── SimpleLockFreeQueue.h │ │ ├── atom_opt.h │ │ ├── atomic_ptr.hpp │ │ ├── ypipe.hpp │ │ └── yqueue.hpp │ │ └── cas_queue_hw │ │ ├── 1_test_i++.c │ │ ├── 2_test_i++_threads.c │ │ ├── 3_test_mutex_spin_lock.cpp │ │ └── 4_test_lock_free_queue.cpp ├── 3.2.4手写死锁检测组件 │ ├── .gitignore │ ├── 1.picture │ │ ├── Untitled.png │ │ └── 死锁检测.png │ ├── 2.doc │ │ ├── 使用锁分配图动态检测混合死锁.pdf │ │ └── 手写死锁检测组件.pdf │ ├── CMakeLists.txt │ └── src │ │ ├── example │ │ ├── deadlock_success.c │ │ └── deadlock课上手写.c │ │ └── practice │ │ └── deadlock_hw.c ├── 3.2.5手写内存泄漏检测组件 │ ├── .gitignore │ ├── 1.picture │ │ └── Untitled.png │ ├── 2.doc │ │ ├── atc20-wu-mingyu.pdf │ │ ├── 手写内存泄漏检测组件.pdf │ │ └── 有效的C 内存泄露检测方法.pdf │ ├── CMakeLists.txt │ ├── README.md │ └── src │ │ ├── example │ │ ├── mem │ │ │ └── 0x563d466c72a0.mem │ │ ├── memleak │ │ ├── memleak.c │ │ ├── shmem.c │ │ └── test.log │ │ └── practice │ │ └── memleak_hw.c └── 3.2.6手写分布式锁 │ ├── .gitignore │ ├── CMakeLists.txt │ └── README.md ├── 3.3开源组件 ├── 3.3.1 libeventlibev框架 │ ├── 1.picture │ │ └── libevent.jpg │ ├── 2.doc │ │ └── libevent_libev实战那些坑.pdf │ ├── README.md │ └── libevent-demo │ │ ├── epoll.c │ │ ├── evmain1.c │ │ └── evmain2.c ├── 3.3.2 异步日志方案log4cpp │ ├── 1.picture │ │ └── 20211230.png │ ├── 2.doc │ │ └── 开源框架log4cpp和日志模块实现-资料.pdf │ ├── README.md │ └── log-src-20211230 │ │ ├── muduo_log │ │ ├── AsyncLogging.cc │ │ ├── AsyncLogging.h │ │ ├── Atomic.h │ │ ├── BlockingQueue.h │ │ ├── CMakeLists.txt │ │ ├── Condition.cc │ │ ├── Condition.h │ │ ├── CountDownLatch.cc │ │ ├── CountDownLatch.h │ │ ├── CurrentThread.cc │ │ ├── CurrentThread.h │ │ ├── Date.cc │ │ ├── Date.h │ │ ├── Exception.cc │ │ ├── Exception.h │ │ ├── FileUtil.cc │ │ ├── FileUtil.h │ │ ├── LogFile.cc │ │ ├── LogFile.h │ │ ├── LogStream.cc │ │ ├── LogStream.h │ │ ├── Logging.cc │ │ ├── Logging.h │ │ ├── Mutex.h │ │ ├── ProcessInfo.cc │ │ ├── ProcessInfo.h │ │ ├── README.md │ │ ├── StringPiece.h │ │ ├── Thread.cc │ │ ├── Thread.h │ │ ├── TimeStamp.h │ │ ├── TimeZone.cc │ │ ├── TimeZone.h │ │ ├── Timestamp.cc │ │ ├── Types.h │ │ ├── copyable.h │ │ ├── main_log_test.cc │ │ ├── noncopyable.h │ │ ├── ptr_vector.h │ │ └── scoped_ptr.h │ │ └── src-log4cpp │ │ ├── 1-file_test.cpp │ │ ├── 2-test_log4cpp.cpp │ │ ├── 3-test_log4cpp copy.cpp │ │ ├── 3-test_log4cpp.conf │ │ ├── 3-test_log4cpp.cpp │ │ ├── 4-RollingFileAppender.cpp │ │ ├── 5-StringQueueAppender.cpp │ │ └── CMakeLists.txt ├── 3.3.3 应用层协议设计ProtoBufThrift │ ├── 2.doc │ │ └── Protobuf3语法详解-20220104.pdf │ └── README.md └── README.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.1手写线程池与性能分析/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.1手写线程池与性能分析/1.picture/线程池解析.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.1手写线程池与性能分析/1.picture/线程池解析.png -------------------------------------------------------------------------------- /3.1池式组件/3.1.1手写线程池与性能分析/2.doc/手写线程池与性能分析.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.1手写线程池与性能分析/2.doc/手写线程池与性能分析.pdf -------------------------------------------------------------------------------- /3.1池式组件/3.1.1手写线程池与性能分析/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(thread_pool_HW) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | include_directories(${CMAKE_SOURCE_DIR}/inc) 10 | 11 | add_executable(thread_pool_hw src/practice/thread_pool_hw.c) 12 | TARGET_LINK_LIBRARIES(thread_pool_hw pthread) 13 | 14 | add_executable(thread_pool src/example/thread_pool.c) 15 | TARGET_LINK_LIBRARIES(thread_pool pthread) -------------------------------------------------------------------------------- /3.1池式组件/3.1.1手写线程池与性能分析/src/practice/thread_pool_hw.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.1手写线程池与性能分析/src/practice/thread_pool_hw.c -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/1.picture/内存池.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.2内存池的实现与场景分析/1.picture/内存池.png -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/1.picture/内存池模型.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.2内存池的实现与场景分析/1.picture/内存池模型.png -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/1.picture/内存池结构体.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.2内存池的实现与场景分析/1.picture/内存池结构体.png -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/2.doc/The Slab Allocator An Object-Caching Kernel Memory Allocator.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.2内存池的实现与场景分析/2.doc/The Slab Allocator An Object-Caching Kernel Memory Allocator.pdf -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/2.doc/内存池的实现与场景分析.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.2内存池的实现与场景分析/2.doc/内存池的实现与场景分析.pdf -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(mmpool_HW) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | include_directories(${CMAKE_SOURCE_DIR}/inc) 10 | 11 | add_executable(mmpool_hw src/practice/mmpool_hw.c) 12 | 13 | add_executable(mmpool src/example/mmpool.c) 14 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.2内存池的实现与场景分析/src/practice/mmpool_hw.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.2内存池的实现与场景分析/src/practice/mmpool_hw.c -------------------------------------------------------------------------------- /3.1池式组件/3.1.3异步请求池的实现/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.3异步请求池的实现/1.picture/异步请求池.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.3异步请求池的实现/1.picture/异步请求池.jpg -------------------------------------------------------------------------------- /3.1池式组件/3.1.3异步请求池的实现/2.doc/异步请求池框架实现.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.3异步请求池的实现/2.doc/异步请求池框架实现.pdf -------------------------------------------------------------------------------- /3.1池式组件/3.1.3异步请求池的实现/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(async) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | include_directories(${CMAKE_SOURCE_DIR}/inc) 10 | 11 | add_executable(async_dns_client_noblock src/async/async_dns_client_noblock.c) 12 | TARGET_LINK_LIBRARIES(async_dns_client_noblock pthread) 13 | 14 | add_executable(sync_dns_client src/async/sync_dns_client.c) 15 | 16 | add_executable(async_dns_client_noblock_hw src/practice/async_dns_client_noblock_hw.c) 17 | TARGET_LINK_LIBRARIES(async_dns_client_noblock_hw pthread) 18 | 19 | add_executable(sync_dns_client_hw src/practice/sync_dns_client_hw.c) 20 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.3异步请求池的实现/README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计——异步请求池 3 | 通过开启一个线程使用epoll_wait接收返回的dns消息 4 | 5 | 6 | # 异步请求池实现 7 | ## 实现异步请求的四个步骤与伪代码 8 | 9 | 1. 初始化,创建epoll和线程池,通过一个独立的线程调用epoll_wait() 10 | ```bash 11 | 1. Init 实现异步 12 | a. epoll_create 13 | b. pthread_create 14 | ``` 15 | 2. 主函数通过socket连接服务器,并提交请求,将fd加入epoll中 16 | ```bash 17 | 2. commit 18 | a. socket 19 | b. connnect_server 20 | c. encode-->redis/mysql/dns 21 | d. send 22 | e. fd加入到epoll中-->epoll_ctl 23 | ``` 24 | 3. callback编写回调函数 25 | ```bash 26 | 3. callback 27 | while(1) 28 | epoll_wait() 29 | recv() 30 | parse() 31 | fd-->epoll_ delete 32 | ``` 33 | 4. 销毁资源 34 | ```bash 35 | 4. destroy 36 | close(epfd); 37 | pthread_cancel(thid) 38 | 39 | 40 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.3异步请求池的实现/src/practice/async_dns_client_noblock_hw.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.3异步请求池的实现/src/practice/async_dns_client_noblock_hw.c -------------------------------------------------------------------------------- /3.1池式组件/3.1.3异步请求池的实现/src/practice/sync_dns_client_hw.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.3异步请求池的实现/src/practice/sync_dns_client_hw.c -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/1.Picture/课上示图-20211211.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.4mysql连接池的实现/1.Picture/课上示图-20211211.png -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/2.doc/mysql连接池和redis连接池的实现20211211.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.4mysql连接池的实现/2.doc/mysql连接池和redis连接池的实现20211211.pdf -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/2.doc/作业.txt: -------------------------------------------------------------------------------- 1 | 1. 稍微思考:考虑连接池退出的资源如何释放问题,一般而言是需要线程池退出后才去释放连接池。 2 | 2. 重点思考(扩展功能): 3 | (1)超时获取连接统计; 4 | (2)连接被占用时间统计,即是被取走到归还的时间间隔统计; 5 | (3)长时间(比如2秒)没有归还如何检测。 -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.4mysql连接池的实现/CMakeLists.txt -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/.gitignore: -------------------------------------------------------------------------------- 1 | /hiredis-test 2 | /examples/hiredis-example* 3 | /*.o 4 | /*.so 5 | /*.dylib 6 | /*.a 7 | /*.pc 8 | *.dSYM 9 | tags 10 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2011, Salvatore Sanfilippo 2 | Copyright (c) 2010-2011, Pieter Noordhuis 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Redis nor the names of its contributors may be used 17 | to endorse or promote products derived from this software without specific 18 | prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 24 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/adapters/ivykis.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_IVYKIS_H__ 2 | #define __HIREDIS_IVYKIS_H__ 3 | #include 4 | #include "../hiredis.h" 5 | #include "../async.h" 6 | 7 | typedef struct redisIvykisEvents { 8 | redisAsyncContext *context; 9 | struct iv_fd fd; 10 | } redisIvykisEvents; 11 | 12 | static void redisIvykisReadEvent(void *arg) { 13 | redisAsyncContext *context = (redisAsyncContext *)arg; 14 | redisAsyncHandleRead(context); 15 | } 16 | 17 | static void redisIvykisWriteEvent(void *arg) { 18 | redisAsyncContext *context = (redisAsyncContext *)arg; 19 | redisAsyncHandleWrite(context); 20 | } 21 | 22 | static void redisIvykisAddRead(void *privdata) { 23 | redisIvykisEvents *e = (redisIvykisEvents*)privdata; 24 | iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent); 25 | } 26 | 27 | static void redisIvykisDelRead(void *privdata) { 28 | redisIvykisEvents *e = (redisIvykisEvents*)privdata; 29 | iv_fd_set_handler_in(&e->fd, NULL); 30 | } 31 | 32 | static void redisIvykisAddWrite(void *privdata) { 33 | redisIvykisEvents *e = (redisIvykisEvents*)privdata; 34 | iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent); 35 | } 36 | 37 | static void redisIvykisDelWrite(void *privdata) { 38 | redisIvykisEvents *e = (redisIvykisEvents*)privdata; 39 | iv_fd_set_handler_out(&e->fd, NULL); 40 | } 41 | 42 | static void redisIvykisCleanup(void *privdata) { 43 | redisIvykisEvents *e = (redisIvykisEvents*)privdata; 44 | 45 | iv_fd_unregister(&e->fd); 46 | hi_free(e); 47 | } 48 | 49 | static int redisIvykisAttach(redisAsyncContext *ac) { 50 | redisContext *c = &(ac->c); 51 | redisIvykisEvents *e; 52 | 53 | /* Nothing should be attached when something is already attached */ 54 | if (ac->ev.data != NULL) 55 | return REDIS_ERR; 56 | 57 | /* Create container for context and r/w events */ 58 | e = (redisIvykisEvents*)hi_malloc(sizeof(*e)); 59 | if (e == NULL) 60 | return REDIS_ERR; 61 | 62 | e->context = ac; 63 | 64 | /* Register functions to start/stop listening for events */ 65 | ac->ev.addRead = redisIvykisAddRead; 66 | ac->ev.delRead = redisIvykisDelRead; 67 | ac->ev.addWrite = redisIvykisAddWrite; 68 | ac->ev.delWrite = redisIvykisDelWrite; 69 | ac->ev.cleanup = redisIvykisCleanup; 70 | ac->ev.data = e; 71 | 72 | /* Initialize and install read/write events */ 73 | IV_FD_INIT(&e->fd); 74 | e->fd.fd = c->fd; 75 | e->fd.handler_in = redisIvykisReadEvent; 76 | e->fd.handler_out = redisIvykisWriteEvent; 77 | e->fd.handler_err = NULL; 78 | e->fd.cookie = e->context; 79 | 80 | iv_fd_register(&e->fd); 81 | 82 | return REDIS_OK; 83 | } 84 | #endif 85 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/adapters/libuv.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_LIBUV_H__ 2 | #define __HIREDIS_LIBUV_H__ 3 | #include 4 | #include 5 | #include "../hiredis.h" 6 | #include "../async.h" 7 | #include 8 | 9 | typedef struct redisLibuvEvents { 10 | redisAsyncContext* context; 11 | uv_poll_t handle; 12 | int events; 13 | } redisLibuvEvents; 14 | 15 | 16 | static void redisLibuvPoll(uv_poll_t* handle, int status, int events) { 17 | redisLibuvEvents* p = (redisLibuvEvents*)handle->data; 18 | int ev = (status ? p->events : events); 19 | 20 | if (p->context != NULL && (ev & UV_READABLE)) { 21 | redisAsyncHandleRead(p->context); 22 | } 23 | if (p->context != NULL && (ev & UV_WRITABLE)) { 24 | redisAsyncHandleWrite(p->context); 25 | } 26 | } 27 | 28 | 29 | static void redisLibuvAddRead(void *privdata) { 30 | redisLibuvEvents* p = (redisLibuvEvents*)privdata; 31 | 32 | p->events |= UV_READABLE; 33 | 34 | uv_poll_start(&p->handle, p->events, redisLibuvPoll); 35 | } 36 | 37 | 38 | static void redisLibuvDelRead(void *privdata) { 39 | redisLibuvEvents* p = (redisLibuvEvents*)privdata; 40 | 41 | p->events &= ~UV_READABLE; 42 | 43 | if (p->events) { 44 | uv_poll_start(&p->handle, p->events, redisLibuvPoll); 45 | } else { 46 | uv_poll_stop(&p->handle); 47 | } 48 | } 49 | 50 | 51 | static void redisLibuvAddWrite(void *privdata) { 52 | redisLibuvEvents* p = (redisLibuvEvents*)privdata; 53 | 54 | p->events |= UV_WRITABLE; 55 | 56 | uv_poll_start(&p->handle, p->events, redisLibuvPoll); 57 | } 58 | 59 | 60 | static void redisLibuvDelWrite(void *privdata) { 61 | redisLibuvEvents* p = (redisLibuvEvents*)privdata; 62 | 63 | p->events &= ~UV_WRITABLE; 64 | 65 | if (p->events) { 66 | uv_poll_start(&p->handle, p->events, redisLibuvPoll); 67 | } else { 68 | uv_poll_stop(&p->handle); 69 | } 70 | } 71 | 72 | 73 | static void on_close(uv_handle_t* handle) { 74 | redisLibuvEvents* p = (redisLibuvEvents*)handle->data; 75 | 76 | hi_free(p); 77 | } 78 | 79 | 80 | static void redisLibuvCleanup(void *privdata) { 81 | redisLibuvEvents* p = (redisLibuvEvents*)privdata; 82 | 83 | p->context = NULL; // indicate that context might no longer exist 84 | uv_close((uv_handle_t*)&p->handle, on_close); 85 | } 86 | 87 | 88 | static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { 89 | redisContext *c = &(ac->c); 90 | 91 | if (ac->ev.data != NULL) { 92 | return REDIS_ERR; 93 | } 94 | 95 | ac->ev.addRead = redisLibuvAddRead; 96 | ac->ev.delRead = redisLibuvDelRead; 97 | ac->ev.addWrite = redisLibuvAddWrite; 98 | ac->ev.delWrite = redisLibuvDelWrite; 99 | ac->ev.cleanup = redisLibuvCleanup; 100 | 101 | redisLibuvEvents* p = (redisLibuvEvents*)hi_malloc(sizeof(*p)); 102 | if (p == NULL) 103 | return REDIS_ERR; 104 | 105 | memset(p, 0, sizeof(*p)); 106 | 107 | if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) { 108 | return REDIS_ERR; 109 | } 110 | 111 | ac->ev.data = p; 112 | p->handle.data = p; 113 | p->context = ac; 114 | 115 | return REDIS_OK; 116 | } 117 | #endif 118 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/alloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Michael Grunder 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "fmacros.h" 32 | #include "alloc.h" 33 | #include 34 | #include 35 | 36 | hiredisAllocFuncs hiredisAllocFns = { 37 | .mallocFn = malloc, 38 | .callocFn = calloc, 39 | .reallocFn = realloc, 40 | .strdupFn = strdup, 41 | .freeFn = free, 42 | }; 43 | 44 | /* Override hiredis' allocators with ones supplied by the user */ 45 | hiredisAllocFuncs hiredisSetAllocators(hiredisAllocFuncs *override) { 46 | hiredisAllocFuncs orig = hiredisAllocFns; 47 | 48 | hiredisAllocFns = *override; 49 | 50 | return orig; 51 | } 52 | 53 | /* Reset allocators to use libc defaults */ 54 | void hiredisResetAllocators(void) { 55 | hiredisAllocFns = (hiredisAllocFuncs) { 56 | .mallocFn = malloc, 57 | .callocFn = calloc, 58 | .reallocFn = realloc, 59 | .strdupFn = strdup, 60 | .freeFn = free, 61 | }; 62 | } 63 | 64 | #ifdef _WIN32 65 | 66 | void *hi_malloc(size_t size) { 67 | return hiredisAllocFns.mallocFn(size); 68 | } 69 | 70 | void *hi_calloc(size_t nmemb, size_t size) { 71 | return hiredisAllocFns.callocFn(nmemb, size); 72 | } 73 | 74 | void *hi_realloc(void *ptr, size_t size) { 75 | return hiredisAllocFns.reallocFn(ptr, size); 76 | } 77 | 78 | char *hi_strdup(const char *str) { 79 | return hiredisAllocFns.strdupFn(str); 80 | } 81 | 82 | void hi_free(void *ptr) { 83 | hiredisAllocFns.freeFn(ptr); 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/alloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Michael Grunder 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef HIREDIS_ALLOC_H 32 | #define HIREDIS_ALLOC_H 33 | 34 | #include /* for size_t */ 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /* Structure pointing to our actually configured allocators */ 41 | typedef struct hiredisAllocFuncs { 42 | void *(*mallocFn)(size_t); 43 | void *(*callocFn)(size_t,size_t); 44 | void *(*reallocFn)(void*,size_t); 45 | char *(*strdupFn)(const char*); 46 | void (*freeFn)(void*); 47 | } hiredisAllocFuncs; 48 | 49 | hiredisAllocFuncs hiredisSetAllocators(hiredisAllocFuncs *ha); 50 | void hiredisResetAllocators(void); 51 | 52 | #ifndef _WIN32 53 | 54 | /* Hiredis' configured allocator function pointer struct */ 55 | extern hiredisAllocFuncs hiredisAllocFns; 56 | 57 | static inline void *hi_malloc(size_t size) { 58 | return hiredisAllocFns.mallocFn(size); 59 | } 60 | 61 | static inline void *hi_calloc(size_t nmemb, size_t size) { 62 | return hiredisAllocFns.callocFn(nmemb, size); 63 | } 64 | 65 | static inline void *hi_realloc(void *ptr, size_t size) { 66 | return hiredisAllocFns.reallocFn(ptr, size); 67 | } 68 | 69 | static inline char *hi_strdup(const char *str) { 70 | return hiredisAllocFns.strdupFn(str); 71 | } 72 | 73 | static inline void hi_free(void *ptr) { 74 | hiredisAllocFns.freeFn(ptr); 75 | } 76 | 77 | #else 78 | 79 | void *hi_malloc(size_t size); 80 | void *hi_calloc(size_t nmemb, size_t size); 81 | void *hi_realloc(void *ptr, size_t size); 82 | char *hi_strdup(const char *str); 83 | void hi_free(void *ptr); 84 | 85 | #endif 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | 91 | #endif /* HIREDIS_ALLOC_H */ 92 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/appveyor.yml: -------------------------------------------------------------------------------- 1 | # Appveyor configuration file for CI build of hiredis on Windows (under Cygwin) 2 | environment: 3 | matrix: 4 | - CYG_BASH: C:\cygwin64\bin\bash 5 | CC: gcc 6 | - CYG_BASH: C:\cygwin\bin\bash 7 | CC: gcc 8 | CFLAGS: -m32 9 | CXXFLAGS: -m32 10 | LDFLAGS: -m32 11 | 12 | clone_depth: 1 13 | 14 | # Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail 15 | init: 16 | - git config --global core.autocrlf input 17 | 18 | # Install needed build dependencies 19 | install: 20 | - '%CYG_BASH% -lc "cygcheck -dc cygwin"' 21 | 22 | build_script: 23 | - 'echo building...' 24 | - '%CYG_BASH% -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | /* Put event loop in the global scope, so it can be explicitly stopped */ 11 | static aeEventLoop *loop; 12 | 13 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 14 | redisReply *reply = r; 15 | if (reply == NULL) return; 16 | printf("argv[%s]: %s\n", (char*)privdata, reply->str); 17 | 18 | /* Disconnect after receiving the reply to GET */ 19 | redisAsyncDisconnect(c); 20 | } 21 | 22 | void connectCallback(const redisAsyncContext *c, int status) { 23 | if (status != REDIS_OK) { 24 | printf("Error: %s\n", c->errstr); 25 | aeStop(loop); 26 | return; 27 | } 28 | 29 | printf("Connected...\n"); 30 | } 31 | 32 | void disconnectCallback(const redisAsyncContext *c, int status) { 33 | if (status != REDIS_OK) { 34 | printf("Error: %s\n", c->errstr); 35 | aeStop(loop); 36 | return; 37 | } 38 | 39 | printf("Disconnected...\n"); 40 | aeStop(loop); 41 | } 42 | 43 | int main (int argc, char **argv) { 44 | signal(SIGPIPE, SIG_IGN); 45 | 46 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); 47 | if (c->err) { 48 | /* Let *c leak for now... */ 49 | printf("Error: %s\n", c->errstr); 50 | return 1; 51 | } 52 | 53 | loop = aeCreateEventLoop(64); 54 | redisAeAttach(loop, c); 55 | redisAsyncSetConnectCallback(c,connectCallback); 56 | redisAsyncSetDisconnectCallback(c,disconnectCallback); 57 | redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); 58 | redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); 59 | aeMain(loop); 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-glib.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | static GMainLoop *mainloop; 8 | 9 | static void 10 | connect_cb (const redisAsyncContext *ac G_GNUC_UNUSED, 11 | int status) 12 | { 13 | if (status != REDIS_OK) { 14 | g_printerr("Failed to connect: %s\n", ac->errstr); 15 | g_main_loop_quit(mainloop); 16 | } else { 17 | g_printerr("Connected...\n"); 18 | } 19 | } 20 | 21 | static void 22 | disconnect_cb (const redisAsyncContext *ac G_GNUC_UNUSED, 23 | int status) 24 | { 25 | if (status != REDIS_OK) { 26 | g_error("Failed to disconnect: %s", ac->errstr); 27 | } else { 28 | g_printerr("Disconnected...\n"); 29 | g_main_loop_quit(mainloop); 30 | } 31 | } 32 | 33 | static void 34 | command_cb(redisAsyncContext *ac, 35 | gpointer r, 36 | gpointer user_data G_GNUC_UNUSED) 37 | { 38 | redisReply *reply = r; 39 | 40 | if (reply) { 41 | g_print("REPLY: %s\n", reply->str); 42 | } 43 | 44 | redisAsyncDisconnect(ac); 45 | } 46 | 47 | gint 48 | main (gint argc G_GNUC_UNUSED, 49 | gchar *argv[] G_GNUC_UNUSED) 50 | { 51 | redisAsyncContext *ac; 52 | GMainContext *context = NULL; 53 | GSource *source; 54 | 55 | ac = redisAsyncConnect("127.0.0.1", 6379); 56 | if (ac->err) { 57 | g_printerr("%s\n", ac->errstr); 58 | exit(EXIT_FAILURE); 59 | } 60 | 61 | source = redis_source_new(ac); 62 | mainloop = g_main_loop_new(context, FALSE); 63 | g_source_attach(source, context); 64 | 65 | redisAsyncSetConnectCallback(ac, connect_cb); 66 | redisAsyncSetDisconnectCallback(ac, disconnect_cb); 67 | redisAsyncCommand(ac, command_cb, NULL, "SET key 1234"); 68 | redisAsyncCommand(ac, command_cb, NULL, "GET key"); 69 | 70 | g_main_loop_run(mainloop); 71 | 72 | return EXIT_SUCCESS; 73 | } 74 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-ivykis.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 11 | redisReply *reply = r; 12 | if (reply == NULL) return; 13 | printf("argv[%s]: %s\n", (char*)privdata, reply->str); 14 | 15 | /* Disconnect after receiving the reply to GET */ 16 | redisAsyncDisconnect(c); 17 | } 18 | 19 | void connectCallback(const redisAsyncContext *c, int status) { 20 | if (status != REDIS_OK) { 21 | printf("Error: %s\n", c->errstr); 22 | return; 23 | } 24 | printf("Connected...\n"); 25 | } 26 | 27 | void disconnectCallback(const redisAsyncContext *c, int status) { 28 | if (status != REDIS_OK) { 29 | printf("Error: %s\n", c->errstr); 30 | return; 31 | } 32 | printf("Disconnected...\n"); 33 | } 34 | 35 | int main (int argc, char **argv) { 36 | #ifndef _WIN32 37 | signal(SIGPIPE, SIG_IGN); 38 | #endif 39 | 40 | iv_init(); 41 | 42 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); 43 | if (c->err) { 44 | /* Let *c leak for now... */ 45 | printf("Error: %s\n", c->errstr); 46 | return 1; 47 | } 48 | 49 | redisIvykisAttach(c); 50 | redisAsyncSetConnectCallback(c,connectCallback); 51 | redisAsyncSetDisconnectCallback(c,disconnectCallback); 52 | redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); 53 | redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); 54 | 55 | iv_main(); 56 | 57 | iv_deinit(); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-libev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 11 | redisReply *reply = r; 12 | if (reply == NULL) return; 13 | printf("argv[%s]: %s\n", (char*)privdata, reply->str); 14 | 15 | /* Disconnect after receiving the reply to GET */ 16 | redisAsyncDisconnect(c); 17 | } 18 | 19 | void connectCallback(const redisAsyncContext *c, int status) { 20 | if (status != REDIS_OK) { 21 | printf("Error: %s\n", c->errstr); 22 | return; 23 | } 24 | printf("Connected...\n"); 25 | } 26 | 27 | void disconnectCallback(const redisAsyncContext *c, int status) { 28 | if (status != REDIS_OK) { 29 | printf("Error: %s\n", c->errstr); 30 | return; 31 | } 32 | printf("Disconnected...\n"); 33 | } 34 | 35 | int main (int argc, char **argv) { 36 | #ifndef _WIN32 37 | signal(SIGPIPE, SIG_IGN); 38 | #endif 39 | 40 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); 41 | if (c->err) { 42 | /* Let *c leak for now... */ 43 | printf("Error: %s\n", c->errstr); 44 | return 1; 45 | } 46 | 47 | redisLibevAttach(EV_DEFAULT_ c); 48 | redisAsyncSetConnectCallback(c,connectCallback); 49 | redisAsyncSetDisconnectCallback(c,disconnectCallback); 50 | redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); 51 | redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); 52 | ev_loop(EV_DEFAULT_ 0); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-libevent-ssl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 12 | redisReply *reply = r; 13 | if (reply == NULL) return; 14 | printf("argv[%s]: %s\n", (char*)privdata, reply->str); 15 | 16 | /* Disconnect after receiving the reply to GET */ 17 | redisAsyncDisconnect(c); 18 | } 19 | 20 | void connectCallback(const redisAsyncContext *c, int status) { 21 | if (status != REDIS_OK) { 22 | printf("Error: %s\n", c->errstr); 23 | return; 24 | } 25 | printf("Connected...\n"); 26 | } 27 | 28 | void disconnectCallback(const redisAsyncContext *c, int status) { 29 | if (status != REDIS_OK) { 30 | printf("Error: %s\n", c->errstr); 31 | return; 32 | } 33 | printf("Disconnected...\n"); 34 | } 35 | 36 | int main (int argc, char **argv) { 37 | #ifndef _WIN32 38 | signal(SIGPIPE, SIG_IGN); 39 | #endif 40 | 41 | struct event_base *base = event_base_new(); 42 | if (argc < 5) { 43 | fprintf(stderr, 44 | "Usage: %s [ca]\n", argv[0]); 45 | exit(1); 46 | } 47 | 48 | const char *value = argv[1]; 49 | size_t nvalue = strlen(value); 50 | 51 | const char *hostname = argv[2]; 52 | int port = atoi(argv[3]); 53 | 54 | const char *cert = argv[4]; 55 | const char *certKey = argv[5]; 56 | const char *caCert = argc > 5 ? argv[6] : NULL; 57 | 58 | redisSSLContext *ssl; 59 | redisSSLContextError ssl_error; 60 | 61 | redisInitOpenSSL(); 62 | 63 | ssl = redisCreateSSLContext(caCert, NULL, 64 | cert, certKey, NULL, &ssl_error); 65 | if (!ssl) { 66 | printf("Error: %s\n", redisSSLContextGetError(ssl_error)); 67 | return 1; 68 | } 69 | 70 | redisAsyncContext *c = redisAsyncConnect(hostname, port); 71 | if (c->err) { 72 | /* Let *c leak for now... */ 73 | printf("Error: %s\n", c->errstr); 74 | return 1; 75 | } 76 | if (redisInitiateSSLWithContext(&c->c, ssl) != REDIS_OK) { 77 | printf("SSL Error!\n"); 78 | exit(1); 79 | } 80 | 81 | redisLibeventAttach(c,base); 82 | redisAsyncSetConnectCallback(c,connectCallback); 83 | redisAsyncSetDisconnectCallback(c,disconnectCallback); 84 | redisAsyncCommand(c, NULL, NULL, "SET key %b", value, nvalue); 85 | redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); 86 | event_base_dispatch(base); 87 | 88 | redisFreeSSLContext(ssl); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-libevent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 11 | redisReply *reply = r; 12 | if (reply == NULL) { 13 | if (c->errstr) { 14 | printf("errstr: %s\n", c->errstr); 15 | } 16 | return; 17 | } 18 | printf("argv[%s]: %s\n", (char*)privdata, reply->str); 19 | 20 | /* Disconnect after receiving the reply to GET */ 21 | redisAsyncDisconnect(c); 22 | } 23 | 24 | void connectCallback(const redisAsyncContext *c, int status) { 25 | if (status != REDIS_OK) { 26 | printf("Error: %s\n", c->errstr); 27 | return; 28 | } 29 | printf("Connected...\n"); 30 | } 31 | 32 | void disconnectCallback(const redisAsyncContext *c, int status) { 33 | if (status != REDIS_OK) { 34 | printf("Error: %s\n", c->errstr); 35 | return; 36 | } 37 | printf("Disconnected...\n"); 38 | } 39 | 40 | int main (int argc, char **argv) { 41 | #ifndef _WIN32 42 | signal(SIGPIPE, SIG_IGN); 43 | #endif 44 | 45 | struct event_base *base = event_base_new(); 46 | redisOptions options = {0}; 47 | REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379); 48 | struct timeval tv = {0}; 49 | tv.tv_sec = 1; 50 | options.connect_timeout = &tv; 51 | 52 | 53 | redisAsyncContext *c = redisAsyncConnectWithOptions(&options); 54 | if (c->err) { 55 | /* Let *c leak for now... */ 56 | printf("Error: %s\n", c->errstr); 57 | return 1; 58 | } 59 | 60 | redisLibeventAttach(c,base); 61 | redisAsyncSetConnectCallback(c,connectCallback); 62 | redisAsyncSetDisconnectCallback(c,disconnectCallback); 63 | redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); 64 | redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); 65 | event_base_dispatch(base); 66 | return 0; 67 | } 68 | // gcc example-libevent.c -o hi -lhiredis -levent -I/usr/local/include/hiredis -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-libuv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 11 | redisReply *reply = r; 12 | if (reply == NULL) return; 13 | printf("argv[%s]: %s\n", (char*)privdata, reply->str); 14 | 15 | /* Disconnect after receiving the reply to GET */ 16 | redisAsyncDisconnect(c); 17 | } 18 | 19 | void connectCallback(const redisAsyncContext *c, int status) { 20 | if (status != REDIS_OK) { 21 | printf("Error: %s\n", c->errstr); 22 | return; 23 | } 24 | printf("Connected...\n"); 25 | } 26 | 27 | void disconnectCallback(const redisAsyncContext *c, int status) { 28 | if (status != REDIS_OK) { 29 | printf("Error: %s\n", c->errstr); 30 | return; 31 | } 32 | printf("Disconnected...\n"); 33 | } 34 | 35 | int main (int argc, char **argv) { 36 | #ifndef _WIN32 37 | signal(SIGPIPE, SIG_IGN); 38 | #endif 39 | 40 | uv_loop_t* loop = uv_default_loop(); 41 | 42 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); 43 | if (c->err) { 44 | /* Let *c leak for now... */ 45 | printf("Error: %s\n", c->errstr); 46 | return 1; 47 | } 48 | 49 | redisLibuvAttach(c,loop); 50 | redisAsyncSetConnectCallback(c,connectCallback); 51 | redisAsyncSetDisconnectCallback(c,disconnectCallback); 52 | redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); 53 | redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); 54 | uv_run(loop, UV_RUN_DEFAULT); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-macosx.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Дмитрий Бахвалов on 13.07.15. 3 | // Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. 4 | // 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 13 | redisReply *reply = r; 14 | if (reply == NULL) return; 15 | printf("argv[%s]: %s\n", (char*)privdata, reply->str); 16 | 17 | /* Disconnect after receiving the reply to GET */ 18 | redisAsyncDisconnect(c); 19 | } 20 | 21 | void connectCallback(const redisAsyncContext *c, int status) { 22 | if (status != REDIS_OK) { 23 | printf("Error: %s\n", c->errstr); 24 | return; 25 | } 26 | printf("Connected...\n"); 27 | } 28 | 29 | void disconnectCallback(const redisAsyncContext *c, int status) { 30 | if (status != REDIS_OK) { 31 | printf("Error: %s\n", c->errstr); 32 | return; 33 | } 34 | CFRunLoopStop(CFRunLoopGetCurrent()); 35 | printf("Disconnected...\n"); 36 | } 37 | 38 | int main (int argc, char **argv) { 39 | signal(SIGPIPE, SIG_IGN); 40 | 41 | CFRunLoopRef loop = CFRunLoopGetCurrent(); 42 | if( !loop ) { 43 | printf("Error: Cannot get current run loop\n"); 44 | return 1; 45 | } 46 | 47 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); 48 | if (c->err) { 49 | /* Let *c leak for now... */ 50 | printf("Error: %s\n", c->errstr); 51 | return 1; 52 | } 53 | 54 | redisMacOSAttach(c, loop); 55 | 56 | redisAsyncSetConnectCallback(c,connectCallback); 57 | redisAsyncSetDisconnectCallback(c,disconnectCallback); 58 | 59 | redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); 60 | redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); 61 | 62 | CFRunLoopRun(); 63 | 64 | return 0; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-qt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include 5 | #include 6 | 7 | #include "example-qt.h" 8 | 9 | void getCallback(redisAsyncContext *, void * r, void * privdata) { 10 | 11 | redisReply * reply = static_cast(r); 12 | ExampleQt * ex = static_cast(privdata); 13 | if (reply == nullptr || ex == nullptr) return; 14 | 15 | cout << "key: " << reply->str << endl; 16 | 17 | ex->finish(); 18 | } 19 | 20 | void ExampleQt::run() { 21 | 22 | m_ctx = redisAsyncConnect("localhost", 6379); 23 | 24 | if (m_ctx->err) { 25 | cerr << "Error: " << m_ctx->errstr << endl; 26 | redisAsyncFree(m_ctx); 27 | emit finished(); 28 | } 29 | 30 | m_adapter.setContext(m_ctx); 31 | 32 | redisAsyncCommand(m_ctx, NULL, NULL, "SET key %s", m_value); 33 | redisAsyncCommand(m_ctx, getCallback, this, "GET key"); 34 | } 35 | 36 | int main (int argc, char **argv) { 37 | 38 | QCoreApplication app(argc, argv); 39 | 40 | ExampleQt example(argv[argc-1]); 41 | 42 | QObject::connect(&example, SIGNAL(finished()), &app, SLOT(quit())); 43 | QTimer::singleShot(0, &example, SLOT(run())); 44 | 45 | return app.exec(); 46 | } 47 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example-qt.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_EXAMPLE_QT_H 2 | #define __HIREDIS_EXAMPLE_QT_H 3 | 4 | #include 5 | 6 | class ExampleQt : public QObject { 7 | 8 | Q_OBJECT 9 | 10 | public: 11 | ExampleQt(const char * value, QObject * parent = 0) 12 | : QObject(parent), m_value(value) {} 13 | 14 | signals: 15 | void finished(); 16 | 17 | public slots: 18 | void run(); 19 | 20 | private: 21 | void finish() { emit finished(); } 22 | 23 | private: 24 | const char * m_value; 25 | redisAsyncContext * m_ctx; 26 | RedisQtAdapter m_adapter; 27 | 28 | friend 29 | void getCallback(redisAsyncContext *, void *, void *); 30 | }; 31 | 32 | #endif /* !__HIREDIS_EXAMPLE_QT_H */ 33 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) { 8 | unsigned int j, isunix = 0; 9 | redisContext *c; 10 | redisReply *reply; 11 | const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; 12 | 13 | if (argc > 2) { 14 | if (*argv[2] == 'u' || *argv[2] == 'U') { 15 | isunix = 1; 16 | /* in this case, host is the path to the unix socket */ 17 | printf("Will connect to unix socket @%s\n", hostname); 18 | } 19 | } 20 | 21 | int port = (argc > 2) ? atoi(argv[2]) : 6379; 22 | 23 | struct timeval timeout = { 1, 500000 }; // 1.5 seconds 24 | if (isunix) { 25 | c = redisConnectUnixWithTimeout(hostname, timeout); 26 | } else { 27 | c = redisConnectWithTimeout(hostname, port, timeout); 28 | } 29 | if (c == NULL || c->err) { 30 | if (c) { 31 | printf("Connection error: %s\n", c->errstr); 32 | redisFree(c); 33 | } else { 34 | printf("Connection error: can't allocate redis context\n"); 35 | } 36 | exit(1); 37 | } 38 | 39 | /* PING server */ 40 | reply = redisCommand(c,"PING"); 41 | printf("PING: %s\n", reply->str); 42 | freeReplyObject(reply); 43 | 44 | /* Set a key */ 45 | reply = redisCommand(c,"SET %s %s", "foo", "hello world"); 46 | printf("SET: %s\n", reply->str); 47 | freeReplyObject(reply); 48 | 49 | /* Set a key using binary safe API */ 50 | reply = redisCommand(c,"SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5); 51 | printf("SET (binary API): %s\n", reply->str); 52 | freeReplyObject(reply); 53 | 54 | /* Try a GET and two INCR */ 55 | reply = redisCommand(c,"GET foo"); 56 | printf("GET foo: %s\n", reply->str); 57 | freeReplyObject(reply); 58 | 59 | reply = redisCommand(c,"INCR counter"); 60 | printf("INCR counter: %lld\n", reply->integer); 61 | freeReplyObject(reply); 62 | /* again ... */ 63 | reply = redisCommand(c,"INCR counter"); 64 | printf("INCR counter: %lld\n", reply->integer); 65 | freeReplyObject(reply); 66 | 67 | /* Create a list of numbers, from 0 to 9 */ 68 | reply = redisCommand(c,"DEL mylist"); 69 | freeReplyObject(reply); 70 | for (j = 0; j < 10; j++) { 71 | char buf[64]; 72 | 73 | snprintf(buf,64,"%u",j); 74 | reply = redisCommand(c,"LPUSH mylist element-%s", buf); 75 | freeReplyObject(reply); 76 | } 77 | 78 | /* Let's check what we have inside the list */ 79 | reply = redisCommand(c,"LRANGE mylist 0 -1"); 80 | if (reply->type == REDIS_REPLY_ARRAY) { 81 | for (j = 0; j < reply->elements; j++) { 82 | printf("%u) %s\n", j, reply->element[j]->str); 83 | } 84 | } 85 | freeReplyObject(reply); 86 | 87 | /* Disconnects and frees the context */ 88 | redisFree(c); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/hi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.1池式组件/3.1.4mysql连接池的实现/hiredis/examples/hi -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/fmacros.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_FMACRO_H 2 | #define __HIREDIS_FMACRO_H 3 | 4 | #define _XOPEN_SOURCE 600 5 | #define _POSIX_C_SOURCE 200112L 6 | 7 | #if defined(__APPLE__) && defined(__MACH__) 8 | /* Enable TCP_KEEPALIVE */ 9 | #define _DARWIN_C_SOURCE 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/hiredis-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | set_and_check(hiredis_INCLUDEDIR "@PACKAGE_INCLUDE_INSTALL_DIR@") 4 | 5 | IF (NOT TARGET hiredis::hiredis) 6 | INCLUDE(${CMAKE_CURRENT_LIST_DIR}/hiredis-targets.cmake) 7 | ENDIF() 8 | 9 | SET(hiredis_LIBRARIES hiredis::hiredis) 10 | SET(hiredis_INCLUDE_DIRS ${hiredis_INCLUDEDIR}) 11 | 12 | check_required_components(hiredis) 13 | 14 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/hiredis.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | install_libdir=@CMAKE_INSTALL_LIBDIR@ 3 | exec_prefix=${prefix} 4 | libdir=${exec_prefix}/${install_libdir} 5 | includedir=${prefix}/include 6 | pkgincludedir=${includedir}/hiredis 7 | 8 | Name: hiredis 9 | Description: Minimalistic C client library for Redis. 10 | Version: @PROJECT_VERSION@ 11 | Libs: -L${libdir} -lhiredis 12 | Cflags: -I${pkgincludedir} -D_FILE_OFFSET_BITS=64 13 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/hiredis_ssl-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | set_and_check(hiredis_ssl_INCLUDEDIR "@PACKAGE_INCLUDE_INSTALL_DIR@") 4 | 5 | IF (NOT TARGET hiredis::hiredis_ssl) 6 | INCLUDE(${CMAKE_CURRENT_LIST_DIR}/hiredis_ssl-targets.cmake) 7 | ENDIF() 8 | 9 | SET(hiredis_ssl_LIBRARIES hiredis::hiredis_ssl) 10 | SET(hiredis_ssl_INCLUDE_DIRS ${hiredis_ssl_INCLUDEDIR}) 11 | 12 | check_required_components(hiredis_ssl) 13 | 14 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/hiredis_ssl.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | pkgincludedir=${includedir}/hiredis 6 | 7 | Name: hiredis_ssl 8 | Description: SSL Support for hiredis. 9 | Version: @PROJECT_VERSION@ 10 | Requires: hiredis 11 | Libs: -L${libdir} -lhiredis_ssl 12 | Libs.private: -lssl -lcrypto 13 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/net.h: -------------------------------------------------------------------------------- 1 | /* Extracted from anet.c to work properly with Hiredis error reporting. 2 | * 3 | * Copyright (c) 2009-2011, Salvatore Sanfilippo 4 | * Copyright (c) 2010-2014, Pieter Noordhuis 5 | * Copyright (c) 2015, Matt Stancliff , 6 | * Jan-Erik Rediger 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * * Neither the name of Redis nor the names of its contributors may be used 19 | * to endorse or promote products derived from this software without 20 | * specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef __NET_H 36 | #define __NET_H 37 | 38 | #include "hiredis.h" 39 | 40 | void redisNetClose(redisContext *c); 41 | ssize_t redisNetRead(redisContext *c, char *buf, size_t bufcap); 42 | ssize_t redisNetWrite(redisContext *c); 43 | 44 | int redisCheckSocketError(redisContext *c); 45 | int redisContextSetTimeout(redisContext *c, const struct timeval tv); 46 | int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); 47 | int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, 48 | const struct timeval *timeout, 49 | const char *source_addr); 50 | int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); 51 | int redisKeepAlive(redisContext *c, int interval); 52 | int redisCheckConnectDone(redisContext *c, int *completed); 53 | 54 | int redisSetTcpNoDelay(redisContext *c); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/sdsalloc.h: -------------------------------------------------------------------------------- 1 | /* SDSLib 2.0 -- A C dynamic strings library 2 | * 3 | * Copyright (c) 2006-2015, Salvatore Sanfilippo 4 | * Copyright (c) 2015, Oran Agra 5 | * Copyright (c) 2015, Redis Labs, Inc 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Redis nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | /* SDS allocator selection. 34 | * 35 | * This file is used in order to change the SDS allocator at compile time. 36 | * Just define the following defines to what you want to use. Also add 37 | * the include of your alternate allocator if needed (not needed in order 38 | * to use the default libc allocator). */ 39 | 40 | #include "alloc.h" 41 | 42 | #define hi_s_malloc hi_malloc 43 | #define hi_s_realloc hi_realloc 44 | #define hi_s_free hi_free 45 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/hiredis/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ue 2 | 3 | REDIS_SERVER=${REDIS_SERVER:-redis-server} 4 | REDIS_PORT=${REDIS_PORT:-56379} 5 | REDIS_SSL_PORT=${REDIS_SSL_PORT:-56443} 6 | TEST_SSL=${TEST_SSL:-0} 7 | SKIPS_AS_FAILS=${SKIPS_AS_FAILS-:0} 8 | SSL_TEST_ARGS= 9 | SKIPS_ARG= 10 | 11 | tmpdir=$(mktemp -d) 12 | PID_FILE=${tmpdir}/hiredis-test-redis.pid 13 | SOCK_FILE=${tmpdir}/hiredis-test-redis.sock 14 | 15 | if [ "$TEST_SSL" = "1" ]; then 16 | SSL_CA_CERT=${tmpdir}/ca.crt 17 | SSL_CA_KEY=${tmpdir}/ca.key 18 | SSL_CERT=${tmpdir}/redis.crt 19 | SSL_KEY=${tmpdir}/redis.key 20 | 21 | openssl genrsa -out ${tmpdir}/ca.key 4096 22 | openssl req \ 23 | -x509 -new -nodes -sha256 \ 24 | -key ${SSL_CA_KEY} \ 25 | -days 3650 \ 26 | -subj '/CN=Hiredis Test CA' \ 27 | -out ${SSL_CA_CERT} 28 | openssl genrsa -out ${SSL_KEY} 2048 29 | openssl req \ 30 | -new -sha256 \ 31 | -key ${SSL_KEY} \ 32 | -subj '/CN=Hiredis Test Cert' | \ 33 | openssl x509 \ 34 | -req -sha256 \ 35 | -CA ${SSL_CA_CERT} \ 36 | -CAkey ${SSL_CA_KEY} \ 37 | -CAserial ${tmpdir}/ca.txt \ 38 | -CAcreateserial \ 39 | -days 365 \ 40 | -out ${SSL_CERT} 41 | 42 | SSL_TEST_ARGS="--ssl-host 127.0.0.1 --ssl-port ${REDIS_SSL_PORT} --ssl-ca-cert ${SSL_CA_CERT} --ssl-cert ${SSL_CERT} --ssl-key ${SSL_KEY}" 43 | fi 44 | 45 | cleanup() { 46 | set +e 47 | kill $(cat ${PID_FILE}) 48 | rm -rf ${tmpdir} 49 | } 50 | trap cleanup INT TERM EXIT 51 | 52 | cat > ${tmpdir}/redis.conf <> ${tmpdir}/redis.conf < /* for struct timeval */ 6 | 7 | #ifndef inline 8 | #define inline __inline 9 | #endif 10 | 11 | #ifndef strcasecmp 12 | #define strcasecmp stricmp 13 | #endif 14 | 15 | #ifndef strncasecmp 16 | #define strncasecmp strnicmp 17 | #endif 18 | 19 | #ifndef va_copy 20 | #define va_copy(d,s) ((d) = (s)) 21 | #endif 22 | 23 | #ifndef snprintf 24 | #define snprintf c99_snprintf 25 | 26 | __inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) 27 | { 28 | int count = -1; 29 | 30 | if (size != 0) 31 | count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); 32 | if (count == -1) 33 | count = _vscprintf(format, ap); 34 | 35 | return count; 36 | } 37 | 38 | __inline int c99_snprintf(char* str, size_t size, const char* format, ...) 39 | { 40 | int count; 41 | va_list ap; 42 | 43 | va_start(ap, format); 44 | count = c99_vsnprintf(str, size, format, ap); 45 | va_end(ap); 46 | 47 | return count; 48 | } 49 | #endif 50 | #endif /* _MSC_VER */ 51 | 52 | #ifdef _WIN32 53 | #define strerror_r(errno,buf,len) strerror_s(buf,len,errno) 54 | #endif /* _WIN32 */ 55 | 56 | #endif /* _WIN32_HELPER_INCLUDE */ 57 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .vscode/ 3 | /.vscode/ 4 | build 5 | build/ 6 | /build/ 7 | 8 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | PROJECT(test_curd) 3 | 4 | SET(SRC_LIST 5 | DBPool.cpp IMUser.cpp 6 | ) 7 | 8 | SET(EXECUTABLE_OUTPUT_PATH ./) 9 | 10 | 11 | ADD_DEFINITIONS( -g -W -Wall -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DAC_HAS_INFO 12 | -DAC_HAS_WARNING -DAC_HAS_ERROR -DAC_HAS_CRITICAL -DTIXML_USE_STL 13 | -DAC_HAS_DEBUG -DLINUX_DAEMON -std=c++11 -DENCRYPT) 14 | 15 | INCLUDE_DIRECTORIES(./) 16 | # 注意自己的库路径 17 | INCLUDE_DIRECTORIES(/usr/include/mysql) 18 | LINK_DIRECTORIES(/usr/lib/x86_64-linux-gnu/ /usr/lib64/mysql) 19 | 20 | ADD_EXECUTABLE(test_curd test_curd.cpp ${SRC_LIST}) 21 | ADD_EXECUTABLE(test_dbpool test_dbpool.cpp ZeroThreadpool.cpp ${SRC_LIST}) 22 | 23 | 24 | TARGET_LINK_LIBRARIES(test_curd mysqlclient pthread) 25 | TARGET_LINK_LIBRARIES(test_dbpool mysqlclient pthread) -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool/IMUser.cpp: -------------------------------------------------------------------------------- 1 | #include "IMUser.h" 2 | 3 | std::string int2string(uint32_t user_id) 4 | { 5 | std::stringstream ss; 6 | ss << user_id; 7 | return ss.str(); 8 | } 9 | 10 | bool insertUser(CDBConn *pDBConn, int id) 11 | { 12 | bool bRet = false; 13 | string strSql; 14 | strSql = "insert into IMUser(`sex`,`name`,`domain`,`nick`,`password`,`salt`,`phone`,`email`,`company`,`address`,`avatar`,`sign_info`,`departId`,`status`,`created`,`updated`) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 15 | int id_index = id; // 用来区别姓名 16 | 17 | CPrepareStatement *stmt = new CPrepareStatement(); 18 | if (stmt->Init(pDBConn->GetMysql(), strSql)) 19 | { 20 | uint32_t nNow = (uint32_t)time(NULL); 21 | uint32_t index = 0; 22 | 23 | int nSex = 1; // 用户性别 1.男;2.女 24 | 25 | uint32_t nDeptId = 0; // 所属部门 26 | string strName = "廖庆富" + int2string(id_index); // 真名 27 | string strDomain = "minghua" + int2string(id_index); // 花名拼音 28 | string strNick = "明华"; // 花名 29 | string strOutPass = "987654321"; // 密码 30 | string strSalt = "abcd"; // 31 | string strTel = "1857036"; // 手机号码 32 | string strEmail = "326873713@qq.com"; // Email 33 | string strAvatar = ""; // 头像 34 | string sign_info = "一切只为你"; //个性签名 35 | string strPass = "123456"; //密码 36 | int nStatus = 0; // 用户状态0 正常, 1 离职 37 | string strCompany = "零声学院"; //公司 38 | string strAddress = "长沙岳麓区雅阁国际"; //地址 39 | 40 | stmt->SetParam(index++, nSex); 41 | stmt->SetParam(index++, strName); 42 | stmt->SetParam(index++, strDomain); 43 | stmt->SetParam(index++, strNick); 44 | stmt->SetParam(index++, strOutPass); 45 | stmt->SetParam(index++, strSalt); 46 | stmt->SetParam(index++, (strTel + int2string(id_index))); 47 | stmt->SetParam(index++, strEmail); 48 | stmt->SetParam(index++, strCompany); 49 | stmt->SetParam(index++, strAddress); 50 | stmt->SetParam(index++, strAvatar); 51 | stmt->SetParam(index++, sign_info); 52 | stmt->SetParam(index++, nDeptId); 53 | stmt->SetParam(index++, nStatus); 54 | stmt->SetParam(index++, nNow); 55 | stmt->SetParam(index++, nNow); 56 | bRet = stmt->ExecuteUpdate(); 57 | 58 | if (!bRet) 59 | { 60 | printf("insert user failed: %s\n", strSql.c_str()); 61 | } 62 | else 63 | { 64 | uint32_t nId = (uint32_t)stmt->GetInsertId(); 65 | // printf("register then get user_id:%d\n", nId); 66 | } 67 | } 68 | delete stmt; 69 | 70 | return true; 71 | } -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool/IMUser.h: -------------------------------------------------------------------------------- 1 | #ifndef IMUSER_H_ 2 | #define IMUSER_H_ 3 | #include 4 | #include 5 | #include "DBPool.h" 6 | #define DROP_IMUSER_TABLE "DROP TABLE IF EXISTS IMUser" /* if EXISTS 好处 是如果表不存在,执行不会报错 */ 7 | 8 | #define CREATE_IMUSER_TABLE "CREATE TABLE IMUser ( \ 9 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id', \ 10 | `sex` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1男2女0未知', \ 11 | `name` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '用户名', \ 12 | `domain` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '拼音', \ 13 | `nick` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '花名,绰号等', \ 14 | `password` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '密码', \ 15 | `salt` varchar(4) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '混淆码', \ 16 | `phone` varchar(11) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '手机号码', \ 17 | `email` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT 'email', \ 18 | `company` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '公司名称', \ 19 | `address` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '所在地区', \ 20 | `avatar` varchar(255) COLLATE utf8mb4_bin DEFAULT '' COMMENT '自定义用户头像', \ 21 | `validateMethod` tinyint(2) unsigned DEFAULT '1' COMMENT '好友验证方式', \ 22 | `departId` int(11) unsigned NOT NULL DEFAULT '1' COMMENT '所属部门Id', \ 23 | `status` tinyint(2) unsigned DEFAULT '0' COMMENT '1. 试用期 2. 正式 3. 离职 4.实习', \ 24 | `created` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', \ 25 | `updated` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', \ 26 | `push_shield_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0关闭勿扰 1开启勿扰', \ 27 | `sign_info` varchar(128) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '个性签名', \ 28 | PRIMARY KEY (`id`), \ 29 | KEY `idx_domain` (`domain`), \ 30 | KEY `idx_name` (`name`), \ 31 | KEY `idx_phone` (`phone`) \ 32 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" 33 | 34 | #define INSERT_SAMPLE "INSERT INTO user(name,email,phone) VALUES(?,?,?)" 35 | #define SELECT_SAMPLE "SELECT name,email,phone FROM user" 36 | 37 | // 1.创建数据库mysql_pool_test: create database mysql_pool_test; 38 | // show databases; 查看数据库 39 | // show tables; 查看有哪些表 40 | // desc table_name; 查看表结构 41 | // 42 | 43 | std::string int2string(uint32_t user_id); // 只是一个工具函数 44 | bool insertUser(CDBConn *pDBConn, int id); 45 | #endif -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool/README.md: -------------------------------------------------------------------------------- 1 | mysql连接池 -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool/win32.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN32_HELPER_INCLUDE 2 | #define _WIN32_HELPER_INCLUDE 3 | #ifdef _MSC_VER 4 | 5 | #ifndef inline 6 | #define inline __inline 7 | #endif 8 | 9 | #ifndef va_copy 10 | #define va_copy(d,s) ((d) = (s)) 11 | #endif 12 | 13 | #ifndef snprintf 14 | #define snprintf c99_snprintf 15 | 16 | __inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) 17 | { 18 | int count = -1; 19 | 20 | if (size != 0) 21 | count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); 22 | if (count == -1) 23 | count = _vscprintf(format, ap); 24 | 25 | return count; 26 | } 27 | 28 | __inline int c99_snprintf(char* str, size_t size, const char* format, ...) 29 | { 30 | int count; 31 | va_list ap; 32 | 33 | va_start(ap, format); 34 | count = c99_vsnprintf(str, size, format, ap); 35 | va_end(ap); 36 | 37 | return count; 38 | } 39 | #endif 40 | 41 | #endif 42 | #endif -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool_hw/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .vscode/ 3 | /.vscode/ 4 | build 5 | build/ 6 | /build/ 7 | 8 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool_hw/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | PROJECT(test_curd) 3 | 4 | SET(SRC_LIST DBPool.cpp IMUser.cpp) 5 | 6 | SET(EXECUTABLE_OUTPUT_PATH ./) 7 | 8 | 9 | ADD_DEFINITIONS( -g -W -Wall -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DAC_HAS_INFO 10 | -DAC_HAS_WARNING -DAC_HAS_ERROR -DAC_HAS_CRITICAL -DTIXML_USE_STL 11 | -DAC_HAS_DEBUG -DLINUX_DAEMON -std=c++11 -DENCRYPT) 12 | 13 | INCLUDE_DIRECTORIES(./) 14 | # 注意自己的库路径 15 | INCLUDE_DIRECTORIES(/usr/include/mysql) 16 | LINK_DIRECTORIES(/usr/lib/x86_64-linux-gnu/ /usr/lib64/mysql) 17 | 18 | ADD_EXECUTABLE(test_curd test_curd.cpp ${SRC_LIST}) 19 | ADD_EXECUTABLE(test_dbpool test_dbpool.cpp ZeroThreadpool.cpp ${SRC_LIST}) 20 | 21 | TARGET_LINK_LIBRARIES(test_curd mysqlclient pthread) 22 | TARGET_LINK_LIBRARIES(test_dbpool mysqlclient pthread) -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool_hw/IMUser.cpp: -------------------------------------------------------------------------------- 1 | #include "IMUser.h" 2 | 3 | std::string int2string(uint32_t user_id) 4 | { 5 | std::stringstream ss; 6 | ss << user_id; 7 | return ss.str(); 8 | } 9 | 10 | bool insertUser(CDBConn *pDBConn, int id) 11 | { 12 | } -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool_hw/IMUser.h: -------------------------------------------------------------------------------- 1 | #ifndef IMUSER_H_ 2 | #define IMUSER_H_ 3 | #include 4 | #include 5 | #include "DBPool.h" 6 | #define DROP_IMUSER_TABLE "DROP TABLE IF EXISTS IMUser" /* if EXISTS 好处 是如果表不存在,执行不会报错 */ 7 | 8 | #define CREATE_IMUSER_TABLE "CREATE TABLE IMUser ( \ 9 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id', \ 10 | `sex` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1男2女0未知', \ 11 | `name` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '用户名', \ 12 | `domain` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '拼音', \ 13 | `nick` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '花名,绰号等', \ 14 | `password` varchar(32) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '密码', \ 15 | `salt` varchar(4) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '混淆码', \ 16 | `phone` varchar(11) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '手机号码', \ 17 | `email` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT 'email', \ 18 | `company` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '公司名称', \ 19 | `address` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '所在地区', \ 20 | `avatar` varchar(255) COLLATE utf8mb4_bin DEFAULT '' COMMENT '自定义用户头像', \ 21 | `validateMethod` tinyint(2) unsigned DEFAULT '1' COMMENT '好友验证方式', \ 22 | `departId` int(11) unsigned NOT NULL DEFAULT '1' COMMENT '所属部门Id', \ 23 | `status` tinyint(2) unsigned DEFAULT '0' COMMENT '1. 试用期 2. 正式 3. 离职 4.实习', \ 24 | `created` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间', \ 25 | `updated` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间', \ 26 | `push_shield_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0关闭勿扰 1开启勿扰', \ 27 | `sign_info` varchar(128) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '个性签名', \ 28 | PRIMARY KEY (`id`), \ 29 | KEY `idx_domain` (`domain`), \ 30 | KEY `idx_name` (`name`), \ 31 | KEY `idx_phone` (`phone`) \ 32 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" 33 | 34 | #define INSERT_SAMPLE "INSERT INTO user(name,email,phone) VALUES(?,?,?)" 35 | #define SELECT_SAMPLE "SELECT name,email,phone FROM user" 36 | 37 | // 1.创建数据库mysql_pool_test: create database mysql_pool_test; 38 | // show databases; 查看数据库 39 | // show tables; 查看有哪些表 40 | // desc table_name; 查看表结构 41 | // 42 | 43 | std::string int2string(uint32_t user_id); // 只是一个工具函数 44 | bool insertUser(CDBConn *pDBConn, int id); 45 | #endif -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool_hw/README.md: -------------------------------------------------------------------------------- 1 | mysql连接池 -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool_hw/test_curd_hw.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: test_curd.cpp 3 | * @Brief : In User Settings Edit 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-25 7 | * 8 | */ 9 | 10 | #include "DBPool.h" 11 | #include "IMUser.h" 12 | using namespace std; 13 | // 登录数据库: mysql -u root -p 14 | // 创建数据库: CREATE DATABASE 数据库名; 15 | // 删除数据库: DROP DATABASE 数据库名; 16 | // 显示所有的数据库: show DATABASE; 17 | // 进入某个数据库: USE 数据库名; 18 | // 查看所有表: SHOW tables 19 | // 查看某个表结构: 20 | 21 | #define DB_HOST_IP "127.0.0.1" // 数据库服务器ip 22 | #define DB_HOST_PORT 3306 23 | #define DB_DATABASE_NAME "mysql_pool_test" // 数据库对应的库名字, 这里需要自己提前用命令创建完毕 24 | #define DB_USERNAME "root" // 数据库用户名 25 | #define DB_PASSWORD "123456" // 数据库密码 26 | #define DB_POOL_NAME "mysql_pool" // 连接池的名字,便于将多个连接池集中管理 27 | #define DB_POOL_MAX_CON 4 // 连接池支持的最大连接数量 28 | 29 | static uint32_t IMUser_nId = 0; 30 | 31 | // 把连接传递进去 32 | bool insertUser(CDBConn *pDBConn) 33 | { 34 | } 35 | 36 | bool queryUser(CDBConn *pDBConn) 37 | { 38 | } 39 | 40 | bool updateUser(CDBConn *pDBConn) 41 | { 42 | } 43 | 44 | // 测试本地的数据库连接 45 | void testConnect() 46 | { 47 | } 48 | // 测试本地数据库的创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)操作。 49 | // 测试增删改查 50 | void testCurd() 51 | { 52 | } 53 | 54 | // 默认端口 3306 55 | // 测试一次连接和端口的情况: tcpdump -i any port 3306 56 | // 参考宏定义设置自己数据库的相关信息 57 | /* 58 | #define DB_HOST_IP "127.0.0.1" // 数据库服务器ip 59 | #define DB_HOST_PORT 3306 60 | #define DB_DATABASE_NAME "mysql_pool_test" // 数据库对应的库名字, 这里需要自己提前用命令创建完毕 61 | #define DB_USERNAME "root" // 数据库用户名 62 | #define DB_PASSWORD "123456" // 数据库密码 63 | #define DB_POOL_NAME "mysql_pool" // 连接池的名字,便于将多个连接池集中管理 64 | #define DB_POOL_MAX_CON 4 // 连接池支持的最大连接数量 65 | */ 66 | int main() 67 | { 68 | printf("test TestConnect begin\n"); 69 | testConnect(); 70 | printf("test TestConnect finish\n\n"); 71 | 72 | printf("test TestCurd begin\n"); 73 | testCurd(); 74 | printf("test TestCurd finish\n"); 75 | return 0; 76 | } -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/mysql_pool_hw/win32.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN32_HELPER_INCLUDE 2 | #define _WIN32_HELPER_INCLUDE 3 | #ifdef _MSC_VER 4 | 5 | #ifndef inline 6 | #define inline __inline 7 | #endif 8 | 9 | #ifndef va_copy 10 | #define va_copy(d, s) ((d) = (s)) 11 | #endif 12 | 13 | #ifndef snprintf 14 | #define snprintf c99_snprintf 15 | 16 | __inline int c99_vsnprintf(char *str, size_t size, const char *format, va_list ap) 17 | { 18 | int count = -1; 19 | 20 | if (size != 0) 21 | count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); 22 | if (count == -1) 23 | count = _vscprintf(format, ap); 24 | 25 | return count; 26 | } 27 | 28 | __inline int c99_snprintf(char *str, size_t size, const char *format, ...) 29 | { 30 | int count; 31 | va_list ap; 32 | 33 | va_start(ap, format); 34 | count = c99_vsnprintf(str, size, format, ap); 35 | va_end(ap); 36 | 37 | return count; 38 | } 39 | #endif 40 | 41 | #endif 42 | #endif -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async-hw/README.md: -------------------------------------------------------------------------------- 1 | gcc sync.c -o sync -I./ -L./hiredis -lhiredis 2 | gcc async.c -o async -I./ -L./hiredis -lhiredis 3 | 4 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async-hw/adapter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: adapter.h 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async-hw/async.c: -------------------------------------------------------------------------------- 1 | #include "hiredis/hiredis.h" 2 | #include "hiredis/async.h" 3 | #include "reactor.h" 4 | #include "adapter.h" 5 | #include 6 | 7 | static reactor_t *R; 8 | static int cnt, before, num; 9 | 10 | 11 | int current_tick() { 12 | int t = 0; 13 | struct timespec ti; 14 | clock_gettime(CLOCK_MONOTONIC, &ti); 15 | t = (int)ti.tv_sec * 1000; 16 | t += ti.tv_nsec / 1000000; 17 | return t; 18 | } 19 | 20 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 21 | redisReply *reply = r; 22 | if (reply == NULL) return; 23 | printf("argv[%s]: %lld\n", (char*)privdata, reply->integer); 24 | 25 | /* Disconnect after receiving the reply to GET */ 26 | cnt++; 27 | if (cnt == num) { 28 | int used = current_tick()-before; 29 | printf("after %d exec redis command, used %d ms\n", num, used); 30 | redisAsyncDisconnect(c); 31 | } 32 | } 33 | 34 | 35 | void connectCallback(const redisAsyncContext *c, int status) { 36 | if (status != REDIS_OK) { 37 | printf("Error: %s\n", c->errstr); 38 | stop_eventloop(R); 39 | return; 40 | } 41 | 42 | printf("Connected...\n"); 43 | } 44 | 45 | void disconnectCallback(const redisAsyncContext *c, int status) { 46 | if (status != REDIS_OK) { 47 | printf("Error: %s\n", c->errstr); 48 | stop_eventloop(R); 49 | return; 50 | } 51 | 52 | printf("Disconnected...\n"); 53 | stop_eventloop(R); 54 | } 55 | 56 | int main(int argc, char **argv) { 57 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); 58 | if (c->err) { 59 | /* Let *c leak for now... */ 60 | printf("Error: %s\n", c->errstr); 61 | return 1; 62 | } 63 | R = create_reactor(); 64 | 65 | redisAttach(R, c); 66 | 67 | redisAsyncSetConnectCallback(c, connectCallback); 68 | redisAsyncSetDisconnectCallback(c, disconnectCallback); 69 | 70 | before = current_tick(); 71 | num = (argc > 1) ? atoi(argv[1]) : 1000; 72 | 73 | for (int i = 0; i < num; i++) { 74 | redisAsyncCommand(c, getCallback, "count", "INCR counter"); 75 | } 76 | 77 | eventloop(R); 78 | 79 | release_reactor(R); 80 | return 0; 81 | } 82 | 83 | // gcc main.c -o main -L./hiredis -lhiredis 84 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async-hw/reactor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: reactor.h 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ 9 | #ifndef _MARK_REACTOR_ 10 | #define _MARK_REACTOR_ 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | #define MAX_EVENT_NUM 512 20 | 21 | typedef struct { 22 | int epfd; // epoll 23 | int listenfd; 24 | int stop; 25 | struct epoll_event evs[MAX_EVENT_NUM]; 26 | } reactor_t; 27 | 28 | reactor_t * create_reactor() { 29 | reactor_t *r = (reactor_t *)malloc(sizeof(*r)); 30 | r->epfd = epoll_create(1); 31 | r->listenfd = 0; 32 | r->stop = 0; 33 | memset(r->evs, 0, sizeof(struct epoll_event) * MAX_EVENT_NUM); 34 | return r; 35 | } 36 | 37 | void release_reactor(reactor_t * r) { 38 | close(r->epfd); 39 | free(r); 40 | } 41 | 42 | typedef void (*event_callback_fn)(int fd, int events, void *privdata); 43 | 44 | typedef struct { 45 | int fd; 46 | reactor_t *r; 47 | event_callback_fn read_fn; 48 | event_callback_fn write_fn; 49 | event_callback_fn accept_fn; 50 | } event_t; 51 | 52 | // int clientfd = accept(listenfd, addr, sz); 53 | int add_event(int epfd, int fd, int events, void *privdata) { 54 | struct epoll_event ev; 55 | ev.events = events; // 读 还是写事件 56 | ev.data.ptr = privdata; 57 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) { 58 | return 1; 59 | } 60 | return 0; 61 | } 62 | 63 | int del_event(int epfd, int fd) { 64 | epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); 65 | } 66 | 67 | int enable_event(int epfd, int fd, void *privdata, int readable, int writeable) { 68 | struct epoll_event ev; 69 | ev.events = (readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0); 70 | ev.data.ptr = privdata; 71 | if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) { 72 | return 1; 73 | } 74 | return 0; 75 | } 76 | 77 | // 测试io 78 | // 1. 增删改 事件处理 79 | // 2. 事件循环 取出事件 80 | void eventloop_once(reactor_t * r) { 81 | int n = epoll_wait(r->epfd, r->evs, MAX_EVENT_NUM, -1); 82 | for (int i = 0; i < n; i++) { 83 | int mask = 0; 84 | struct epoll_event *e = &r->evs[i]; 85 | if (e->events & EPOLLIN) mask |= EPOLLIN; 86 | if (e->events & EPOLLOUT) mask |= EPOLLOUT; 87 | if (e->events & EPOLLERR) mask |= EPOLLIN|EPOLLOUT; 88 | if (e->events & EPOLLHUP) mask |= EPOLLIN|EPOLLOUT; 89 | if (mask & EPOLLIN) { 90 | event_t *et = (event_t*) e->data.ptr; 91 | if (et->fd == r->listenfd) { 92 | if (et->accept_fn) 93 | et->accept_fn(et->fd, mask, et); 94 | } else { 95 | if (et->read_fn) 96 | et->read_fn(et->fd, mask, et); 97 | } 98 | } 99 | if (mask & EPOLLOUT) { 100 | event_t *et = (event_t*) e->data.ptr; 101 | if (et->write_fn) 102 | et->write_fn(et->fd, mask, et); 103 | } 104 | } 105 | } 106 | 107 | void stop_eventloop(reactor_t * r) { 108 | r->stop = 1; 109 | } 110 | 111 | void eventloop(reactor_t * r) { 112 | while (!r->stop) { 113 | eventloop_once(r); 114 | } 115 | } 116 | 117 | #endif -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async-hw/sync.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: sync.c 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async/README.md: -------------------------------------------------------------------------------- 1 | gcc sync.c -o sync -I./inc -L./hiredis -lhiredis 2 | gcc async.c -o async -I./inc -L./hiredis -lhiredis 3 | 4 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async/async.c: -------------------------------------------------------------------------------- 1 | #include "hiredis/hiredis.h" 2 | #include "hiredis/async.h" 3 | #include "reactor.h" 4 | #include "adapter.h" 5 | #include 6 | 7 | static reactor_t *R; 8 | static int cnt, before, num; 9 | 10 | 11 | int current_tick() { 12 | int t = 0; 13 | struct timespec ti; 14 | clock_gettime(CLOCK_MONOTONIC, &ti); 15 | t = (int)ti.tv_sec * 1000; 16 | t += ti.tv_nsec / 1000000; 17 | return t; 18 | } 19 | 20 | void getCallback(redisAsyncContext *c, void *r, void *privdata) { 21 | redisReply *reply = r; 22 | if (reply == NULL) return; 23 | printf("argv[%s]: %lld\n", (char*)privdata, reply->integer); 24 | 25 | /* Disconnect after receiving the reply to GET */ 26 | cnt++; 27 | if (cnt == num) { 28 | int used = current_tick()-before; 29 | printf("after %d exec redis command, used %d ms\n", num, used); 30 | redisAsyncDisconnect(c); 31 | } 32 | } 33 | 34 | 35 | void connectCallback(const redisAsyncContext *c, int status) { 36 | if (status != REDIS_OK) { 37 | printf("Error: %s\n", c->errstr); 38 | stop_eventloop(R); 39 | return; 40 | } 41 | 42 | printf("Connected...\n"); 43 | } 44 | 45 | void disconnectCallback(const redisAsyncContext *c, int status) { 46 | if (status != REDIS_OK) { 47 | printf("Error: %s\n", c->errstr); 48 | stop_eventloop(R); 49 | return; 50 | } 51 | 52 | printf("Disconnected...\n"); 53 | stop_eventloop(R); 54 | } 55 | 56 | int main(int argc, char **argv) { 57 | redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); 58 | if (c->err) { 59 | /* Let *c leak for now... */ 60 | printf("Error: %s\n", c->errstr); 61 | return 1; 62 | } 63 | R = create_reactor(); 64 | 65 | redisAttach(R, c); 66 | 67 | redisAsyncSetConnectCallback(c, connectCallback); 68 | redisAsyncSetDisconnectCallback(c, disconnectCallback); 69 | 70 | before = current_tick(); 71 | num = (argc > 1) ? atoi(argv[1]) : 1000; 72 | 73 | for (int i = 0; i < num; i++) { 74 | redisAsyncCommand(c, getCallback, "count", "INCR counter"); 75 | } 76 | 77 | eventloop(R); 78 | 79 | release_reactor(R); 80 | return 0; 81 | } 82 | 83 | // gcc main.c -o main -L./hiredis -lhiredis 84 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async/reactor.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MARK_REACTOR_ 3 | #define _MARK_REACTOR_ 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #define MAX_EVENT_NUM 512 13 | 14 | typedef struct { 15 | int epfd; // epoll 16 | int listenfd; 17 | int stop; 18 | struct epoll_event evs[MAX_EVENT_NUM]; 19 | } reactor_t; 20 | 21 | reactor_t * create_reactor() { 22 | reactor_t *r = (reactor_t *)malloc(sizeof(*r)); 23 | r->epfd = epoll_create(1); 24 | r->listenfd = 0; 25 | r->stop = 0; 26 | memset(r->evs, 0, sizeof(struct epoll_event) * MAX_EVENT_NUM); 27 | return r; 28 | } 29 | 30 | void release_reactor(reactor_t * r) { 31 | close(r->epfd); 32 | free(r); 33 | } 34 | 35 | typedef void (*event_callback_fn)(int fd, int events, void *privdata); 36 | 37 | typedef struct { 38 | int fd; 39 | reactor_t *r; 40 | event_callback_fn read_fn; 41 | event_callback_fn write_fn; 42 | event_callback_fn accept_fn; 43 | } event_t; 44 | 45 | // int clientfd = accept(listenfd, addr, sz); 46 | int add_event(int epfd, int fd, int events, void *privdata) { 47 | struct epoll_event ev; 48 | ev.events = events; // 读 还是写事件 49 | ev.data.ptr = privdata; 50 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) { 51 | return 1; 52 | } 53 | return 0; 54 | } 55 | 56 | int del_event(int epfd, int fd) { 57 | epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); 58 | } 59 | 60 | int enable_event(int epfd, int fd, void *privdata, int readable, int writeable) { 61 | struct epoll_event ev; 62 | ev.events = (readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0); 63 | ev.data.ptr = privdata; 64 | if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) { 65 | return 1; 66 | } 67 | return 0; 68 | } 69 | 70 | // 测试io 71 | // 1. 增删改 事件处理 72 | // 2. 事件循环 取出事件 73 | void eventloop_once(reactor_t * r) { 74 | int n = epoll_wait(r->epfd, r->evs, MAX_EVENT_NUM, -1); 75 | for (int i = 0; i < n; i++) { 76 | int mask = 0; 77 | struct epoll_event *e = &r->evs[i]; 78 | if (e->events & EPOLLIN) mask |= EPOLLIN; 79 | if (e->events & EPOLLOUT) mask |= EPOLLOUT; 80 | if (e->events & EPOLLERR) mask |= EPOLLIN|EPOLLOUT; 81 | if (e->events & EPOLLHUP) mask |= EPOLLIN|EPOLLOUT; 82 | if (mask & EPOLLIN) { 83 | event_t *et = (event_t*) e->data.ptr; 84 | if (et->fd == r->listenfd) { 85 | if (et->accept_fn) 86 | et->accept_fn(et->fd, mask, et); 87 | } else { 88 | if (et->read_fn) 89 | et->read_fn(et->fd, mask, et); 90 | } 91 | } 92 | if (mask & EPOLLOUT) { 93 | event_t *et = (event_t*) e->data.ptr; 94 | if (et->write_fn) 95 | et->write_fn(et->fd, mask, et); 96 | } 97 | } 98 | } 99 | 100 | void stop_eventloop(reactor_t * r) { 101 | r->stop = 1; 102 | } 103 | 104 | void eventloop(reactor_t * r) { 105 | while (!r->stop) { 106 | eventloop_once(r); 107 | } 108 | } 109 | 110 | #endif -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis-async/sync.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int current_tick() { 8 | int t = 0; 9 | struct timespec ti; 10 | clock_gettime(CLOCK_MONOTONIC, &ti); 11 | t = (int)ti.tv_sec * 1000; 12 | t += ti.tv_nsec / 1000000; 13 | return t; 14 | } 15 | 16 | int main(int argc, char **argv) { 17 | unsigned int j, isunix = 0; 18 | redisContext *c; 19 | redisReply *reply; 20 | const char *hostname = "127.0.0.1"; 21 | 22 | int port = 6379; 23 | 24 | struct timeval timeout = { 1, 500000 }; // 1.5 seconds 25 | 26 | c = redisConnectWithTimeout(hostname, port, timeout); 27 | 28 | if (c == NULL || c->err) { 29 | if (c) { 30 | printf("Connection error: %s\n", c->errstr); 31 | redisFree(c); 32 | } else { 33 | printf("Connection error: can't allocate redis context\n"); 34 | } 35 | exit(1); 36 | } 37 | 38 | int num = (argc > 1) ? atoi(argv[1]) : 1000; 39 | 40 | int before = current_tick(); 41 | 42 | for (int i=0; iinteger); 45 | freeReplyObject(reply); 46 | } 47 | 48 | int used = current_tick()-before; 49 | 50 | printf("after %d exec redis command, used %d ms\n", num, used); 51 | 52 | /* Disconnects and frees the context */ 53 | redisFree(c); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .vscode/ 3 | /.vscode/ 4 | build 5 | build/ 6 | /build/ 7 | 8 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | PROJECT(test_CachePool) 3 | 4 | SET(SRC_LIST 5 | async.c 6 | dict.c 7 | hiredis.c 8 | net.c 9 | read.c 10 | sds.c 11 | CachePool.cpp 12 | ) 13 | 14 | SET(EXECUTABLE_OUTPUT_PATH ./) 15 | INCLUDE_DIRECTORIES(./) 16 | 17 | ADD_EXECUTABLE(test_CachePool test_CachePool.cpp ${SRC_LIST}) 18 | ADD_EXECUTABLE(test_ThreadPool test_ThreadPool.cpp ${SRC_LIST}) 19 | 20 | TARGET_LINK_LIBRARIES(test_CachePool pthread) 21 | TARGET_LINK_LIBRARIES(test_ThreadPool pthread) -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/README.md: -------------------------------------------------------------------------------- 1 | redis连接池测试 2 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/Thread.h: -------------------------------------------------------------------------------- 1 | #ifndef __THREAD_H__ 2 | #define __THREAD_H__ 3 | #include 4 | #include 5 | 6 | class CThreadNotify 7 | { 8 | public: 9 | CThreadNotify() 10 | { 11 | pthread_mutexattr_init(&m_mutexattr); 12 | pthread_mutexattr_settype(&m_mutexattr, PTHREAD_MUTEX_RECURSIVE); 13 | pthread_mutex_init(&m_mutex, &m_mutexattr); 14 | 15 | pthread_cond_init(&m_cond, NULL); 16 | } 17 | ~CThreadNotify() 18 | { 19 | pthread_mutexattr_destroy(&m_mutexattr); 20 | pthread_mutex_destroy(&m_mutex); 21 | pthread_cond_destroy(&m_cond); 22 | } 23 | void Lock() 24 | { 25 | pthread_mutex_lock(&m_mutex); 26 | } 27 | void Unlock() 28 | { 29 | pthread_mutex_unlock(&m_mutex); 30 | } 31 | void Wait() 32 | { 33 | pthread_cond_wait(&m_cond, &m_mutex); 34 | } 35 | // 返回0则正常,其他值为异常 36 | int WaitTime(int ms) 37 | { 38 | //获取时间 39 | struct timespec outtime; 40 | clock_gettime(CLOCK_MONOTONIC, &outtime); 41 | //ms为毫秒,换算成秒 42 | outtime.tv_sec += ms / 1000; 43 | 44 | //在outtime的基础上,增加ms毫秒 45 | //outtime.tv_nsec为纳秒,1微秒=1000纳秒 46 | //tv_nsec此值再加上剩余的毫秒数 ms%1000,有可能超过1秒。需要特殊处理 47 | uint64_t us = outtime.tv_nsec / 1000 + 1000 * (ms % 1000); //微秒 48 | //us的值有可能超过1秒, 49 | outtime.tv_sec += us / 1000000; 50 | 51 | us = us % 1000000; 52 | outtime.tv_nsec = us * 1000; //换算成纳秒 53 | return pthread_cond_timedwait(&m_cond, &m_mutex, &outtime); 54 | } 55 | void Signal() 56 | { 57 | pthread_cond_signal(&m_cond); 58 | } 59 | 60 | private: 61 | pthread_mutex_t m_mutex; 62 | pthread_mutexattr_t m_mutexattr; 63 | 64 | pthread_cond_t m_cond; 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/fmacros.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_FMACRO_H 2 | #define __HIREDIS_FMACRO_H 3 | 4 | #define _XOPEN_SOURCE 600 5 | #define _POSIX_C_SOURCE 200112L 6 | 7 | #if defined(__APPLE__) && defined(__MACH__) 8 | /* Enable TCP_KEEPALIVE */ 9 | #define _DARWIN_C_SOURCE 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/net.h: -------------------------------------------------------------------------------- 1 | /* Extracted from anet.c to work properly with Hiredis error reporting. 2 | * 3 | * Copyright (c) 2009-2011, Salvatore Sanfilippo 4 | * Copyright (c) 2010-2014, Pieter Noordhuis 5 | * Copyright (c) 2015, Matt Stancliff , 6 | * Jan-Erik Rediger 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * * Neither the name of Redis nor the names of its contributors may be used 19 | * to endorse or promote products derived from this software without 20 | * specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef __NET_H 36 | #define __NET_H 37 | 38 | #include "hiredis.h" 39 | 40 | int redisCheckSocketError(redisContext *c); 41 | int redisContextSetTimeout(redisContext *c, const struct timeval tv); 42 | int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); 43 | int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, 44 | const struct timeval *timeout, 45 | const char *source_addr); 46 | int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); 47 | int redisKeepAlive(redisContext *c, int interval); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/sdsalloc.h: -------------------------------------------------------------------------------- 1 | /* SDSLib 2.0 -- A C dynamic strings library 2 | * 3 | * Copyright (c) 2006-2015, Salvatore Sanfilippo 4 | * Copyright (c) 2015, Oran Agra 5 | * Copyright (c) 2015, Redis Labs, Inc 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Redis nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | /* SDS allocator selection. 34 | * 35 | * This file is used in order to change the SDS allocator at compile time. 36 | * Just define the following defines to what you want to use. Also add 37 | * the include of your alternate allocator if needed (not needed in order 38 | * to use the default libc allocator). */ 39 | 40 | #define s_malloc malloc 41 | #define s_realloc realloc 42 | #define s_free free 43 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/threadpool.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct job 4 | { 5 | void* (*callback_function)(void *arg); //线程回调函数 6 | void *arg; //回调函数参数 7 | struct job *next; 8 | }; 9 | 10 | struct threadpool 11 | { 12 | int thread_num; //线程池中开启线程的个数 13 | int queue_max_num; //队列中最大job的个数 14 | struct job *head; //指向job的头指针 15 | struct job *tail; //指向job的尾指针 16 | pthread_t *pthreads; //线程池中所有线程的pthread_t 17 | pthread_mutex_t mutex; //互斥信号量 18 | pthread_cond_t queue_empty; //队列为空的条件变量 19 | pthread_cond_t queue_not_empty; //队列不为空的条件变量 20 | pthread_cond_t queue_not_full; //队列不为满的条件变量 21 | int queue_cur_num; //队列当前的job个数 22 | int queue_close; //队列是否已经关闭 23 | int pool_close; //线程池是否已经关闭 24 | }; 25 | 26 | //================================================================================================ 27 | //函数名: threadpool_init 28 | //函数描述: 初始化线程池 29 | //输入: [in] thread_num 线程池开启的线程个数 30 | // [in] queue_max_num 队列的最大job个数 31 | //输出: 无 32 | //返回: 成功:线程池地址 失败:NULL 33 | //================================================================================================ 34 | struct threadpool* threadpool_init(int thread_num, int queue_max_num); 35 | 36 | //================================================================================================ 37 | //函数名: threadpool_add_job 38 | //函数描述: 向线程池中添加任务 39 | //输入: [in] pool 线程池地址 40 | // [in] callback_function 回调函数 41 | // [in] arg 回调函数参数 42 | //输出: 无 43 | //返回: 成功:0 失败:-1 44 | //================================================================================================ 45 | int threadpool_add_job(struct threadpool *pool, void* (*callback_function)(void *arg), void *arg); 46 | 47 | //================================================================================================ 48 | //函数名: threadpool_destroy 49 | //函数描述: 销毁线程池 50 | //输入: [in] pool 线程池地址 51 | //输出: 无 52 | //返回: 成功:0 失败:-1 53 | //================================================================================================ 54 | int threadpool_destroy(struct threadpool *pool); 55 | 56 | //================================================================================================ 57 | //函数名: threadpool_function 58 | //函数描述: 线程池中线程函数 59 | //输入: [in] arg 线程池地址 60 | //输出: 无 61 | //返回: 无 62 | //================================================================================================ 63 | void* threadpool_function(void* arg); -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool/win32.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN32_HELPER_INCLUDE 2 | #define _WIN32_HELPER_INCLUDE 3 | #ifdef _MSC_VER 4 | 5 | #ifndef inline 6 | #define inline __inline 7 | #endif 8 | 9 | #ifndef va_copy 10 | #define va_copy(d,s) ((d) = (s)) 11 | #endif 12 | 13 | #ifndef snprintf 14 | #define snprintf c99_snprintf 15 | 16 | __inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) 17 | { 18 | int count = -1; 19 | 20 | if (size != 0) 21 | count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); 22 | if (count == -1) 23 | count = _vscprintf(format, ap); 24 | 25 | return count; 26 | } 27 | 28 | __inline int c99_snprintf(char* str, size_t size, const char* format, ...) 29 | { 30 | int count; 31 | va_list ap; 32 | 33 | va_start(ap, format); 34 | count = c99_vsnprintf(str, size, format, ap); 35 | va_end(ap); 36 | 37 | return count; 38 | } 39 | #endif 40 | 41 | #endif 42 | #endif -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .vscode/ 3 | /.vscode/ 4 | build 5 | build/ 6 | /build/ 7 | 8 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/CachePool.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: CachePool.cpp 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/CachePool.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: CachePool.h 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/Thread.h: -------------------------------------------------------------------------------- 1 | #ifndef __THREAD_H__ 2 | #define __THREAD_H__ 3 | #include 4 | #include 5 | 6 | class CThreadNotify 7 | { 8 | public: 9 | CThreadNotify() 10 | { 11 | pthread_mutexattr_init(&m_mutexattr); 12 | pthread_mutexattr_settype(&m_mutexattr, PTHREAD_MUTEX_RECURSIVE); 13 | pthread_mutex_init(&m_mutex, &m_mutexattr); 14 | 15 | pthread_cond_init(&m_cond, NULL); 16 | } 17 | ~CThreadNotify() 18 | { 19 | pthread_mutexattr_destroy(&m_mutexattr); 20 | pthread_mutex_destroy(&m_mutex); 21 | pthread_cond_destroy(&m_cond); 22 | } 23 | void Lock() 24 | { 25 | pthread_mutex_lock(&m_mutex); 26 | } 27 | void Unlock() 28 | { 29 | pthread_mutex_unlock(&m_mutex); 30 | } 31 | void Wait() 32 | { 33 | pthread_cond_wait(&m_cond, &m_mutex); 34 | } 35 | // 返回0则正常,其他值为异常 36 | int WaitTime(int ms) 37 | { 38 | //获取时间 39 | struct timespec outtime; 40 | clock_gettime(CLOCK_MONOTONIC, &outtime); 41 | //ms为毫秒,换算成秒 42 | outtime.tv_sec += ms / 1000; 43 | 44 | //在outtime的基础上,增加ms毫秒 45 | //outtime.tv_nsec为纳秒,1微秒=1000纳秒 46 | //tv_nsec此值再加上剩余的毫秒数 ms%1000,有可能超过1秒。需要特殊处理 47 | uint64_t us = outtime.tv_nsec / 1000 + 1000 * (ms % 1000); //微秒 48 | //us的值有可能超过1秒, 49 | outtime.tv_sec += us / 1000000; 50 | 51 | us = us % 1000000; 52 | outtime.tv_nsec = us * 1000; //换算成纳秒 53 | return pthread_cond_timedwait(&m_cond, &m_mutex, &outtime); 54 | } 55 | void Signal() 56 | { 57 | pthread_cond_signal(&m_cond); 58 | } 59 | 60 | private: 61 | pthread_mutex_t m_mutex; 62 | pthread_mutexattr_t m_mutexattr; 63 | 64 | pthread_cond_t m_cond; 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/fmacros.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIREDIS_FMACRO_H 2 | #define __HIREDIS_FMACRO_H 3 | 4 | #define _XOPEN_SOURCE 600 5 | #define _POSIX_C_SOURCE 200112L 6 | 7 | #if defined(__APPLE__) && defined(__MACH__) 8 | /* Enable TCP_KEEPALIVE */ 9 | #define _DARWIN_C_SOURCE 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/test_CachePool.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: test_CachePool.cpp 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/test_ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: test_ThreadPool.cpp 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/threadpool.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct job 4 | { 5 | void* (*callback_function)(void *arg); //线程回调函数 6 | void *arg; //回调函数参数 7 | struct job *next; 8 | }; 9 | 10 | struct threadpool 11 | { 12 | int thread_num; //线程池中开启线程的个数 13 | int queue_max_num; //队列中最大job的个数 14 | struct job *head; //指向job的头指针 15 | struct job *tail; //指向job的尾指针 16 | pthread_t *pthreads; //线程池中所有线程的pthread_t 17 | pthread_mutex_t mutex; //互斥信号量 18 | pthread_cond_t queue_empty; //队列为空的条件变量 19 | pthread_cond_t queue_not_empty; //队列不为空的条件变量 20 | pthread_cond_t queue_not_full; //队列不为满的条件变量 21 | int queue_cur_num; //队列当前的job个数 22 | int queue_close; //队列是否已经关闭 23 | int pool_close; //线程池是否已经关闭 24 | }; 25 | 26 | //================================================================================================ 27 | //函数名: threadpool_init 28 | //函数描述: 初始化线程池 29 | //输入: [in] thread_num 线程池开启的线程个数 30 | // [in] queue_max_num 队列的最大job个数 31 | //输出: 无 32 | //返回: 成功:线程池地址 失败:NULL 33 | //================================================================================================ 34 | struct threadpool* threadpool_init(int thread_num, int queue_max_num); 35 | 36 | //================================================================================================ 37 | //函数名: threadpool_add_job 38 | //函数描述: 向线程池中添加任务 39 | //输入: [in] pool 线程池地址 40 | // [in] callback_function 回调函数 41 | // [in] arg 回调函数参数 42 | //输出: 无 43 | //返回: 成功:0 失败:-1 44 | //================================================================================================ 45 | int threadpool_add_job(struct threadpool *pool, void* (*callback_function)(void *arg), void *arg); 46 | 47 | //================================================================================================ 48 | //函数名: threadpool_destroy 49 | //函数描述: 销毁线程池 50 | //输入: [in] pool 线程池地址 51 | //输出: 无 52 | //返回: 成功:0 失败:-1 53 | //================================================================================================ 54 | int threadpool_destroy(struct threadpool *pool); 55 | 56 | //================================================================================================ 57 | //函数名: threadpool_function 58 | //函数描述: 线程池中线程函数 59 | //输入: [in] arg 线程池地址 60 | //输出: 无 61 | //返回: 无 62 | //================================================================================================ 63 | void* threadpool_function(void* arg); -------------------------------------------------------------------------------- /3.1池式组件/3.1.4mysql连接池的实现/src/redis_pool_hw/win32.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN32_HELPER_INCLUDE 2 | #define _WIN32_HELPER_INCLUDE 3 | #ifdef _MSC_VER 4 | 5 | #ifndef inline 6 | #define inline __inline 7 | #endif 8 | 9 | #ifndef va_copy 10 | #define va_copy(d,s) ((d) = (s)) 11 | #endif 12 | 13 | #ifndef snprintf 14 | #define snprintf c99_snprintf 15 | 16 | __inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) 17 | { 18 | int count = -1; 19 | 20 | if (size != 0) 21 | count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); 22 | if (count == -1) 23 | count = _vscprintf(format, ap); 24 | 25 | return count; 26 | } 27 | 28 | __inline int c99_snprintf(char* str, size_t size, const char* format, ...) 29 | { 30 | int count; 31 | va_list ap; 32 | 33 | va_start(ap, format); 34 | count = c99_vsnprintf(str, size, format, ap); 35 | va_end(ap); 36 | 37 | return count; 38 | } 39 | #endif 40 | 41 | #endif 42 | #endif -------------------------------------------------------------------------------- /3.2高性能组件/3.2.1原子操作CAS与锁实现/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.1原子操作CAS与锁实现/2.doc/锁与原子操作CAS的底层实现.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.1原子操作CAS与锁实现/2.doc/锁与原子操作CAS的底层实现.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.1原子操作CAS与锁实现/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(lock_HW) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | add_executable(lock_hw src/practice/lock_hw.c) 10 | TARGET_LINK_LIBRARIES(lock_hw pthread) 11 | 12 | add_executable(lock src/example/lock.c) 13 | TARGET_LINK_LIBRARIES(lock pthread) -------------------------------------------------------------------------------- /3.2高性能组件/3.2.1原子操作CAS与锁实现/src/practice/trycatch_finally_hw.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: trycatch_finally_hw.c 3 | * @Brief : 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-22 7 | * 8 | */ -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/2.doc/定时器方案 红黑树 时间轮 最小堆.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/2.doc/定时器方案 红黑树 时间轮 最小堆.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(timers_HW) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | set(timers_example_minheap "timers_src/example/minheap") 10 | set(timers_example_rbtree "timers_src/example/rbtree") 11 | set(timers_example_skiplist "timers_src/example/skiplist") 12 | set(timers_example_timewheel "timers_src/example/timewheel") 13 | set(timers_example_timewheel_single "timers_src/example/timewheel_single") 14 | 15 | include_directories(${CMAKE_SOURCE_DIR}/${timers_example_minheap}) 16 | include_directories(${CMAKE_SOURCE_DIR}/${timers_example_rbtree}) 17 | include_directories(${CMAKE_SOURCE_DIR}/${timers_example_skiplist}) 18 | include_directories(${CMAKE_SOURCE_DIR}/${timers_example_timewheel}) 19 | include_directories(${CMAKE_SOURCE_DIR}/${timers_example_timewheel_single}) 20 | 21 | 22 | add_executable(mh ${timers_example_minheap}/minheap.c ${timers_example_minheap}/mh-timer.c) 23 | 24 | add_executable(rbt ${timers_example_rbtree}/rbtree.c ${timers_example_rbtree}/rbt-timer.c) 25 | 26 | add_executable(skl ${timers_example_skiplist}/skiplist.c ${timers_example_skiplist}/skl-timer.c) 27 | 28 | add_executable(stw ${timers_example_timewheel_single}/single_tw.c) 29 | 30 | add_executable(tw ${timers_example_timewheel}/timewheel.c ${timers_example_timewheel}/tw-timer.c) 31 | TARGET_LINK_LIBRARIES(tw pthread) -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/readme.md: -------------------------------------------------------------------------------- 1 | ### 零声教育出品 Mark 老师 QQ:2548898954 2 | 3 | ### 编译 4 | 5 | #### 最小堆 6 | 7 | ```shell 8 | # 关联文件 mh-timer.c mh-timer.h minheap.h minheap.c 9 | gcc mh-timer.c minheap.c -o mh -I./ 10 | ``` 11 | 12 | #### 红黑树 13 | 14 | ```shell 15 | # 关联文件 rbt-timer.c rbt-timer.h rbtree.c rbtree.h 16 | gcc rbt-timer.c rbtree.c -o rbt -I./ 17 | ``` 18 | 19 | #### 跳表 20 | 21 | ```shell 22 | # 关联文件 skiplist.h skiplist.c skl-timer.c 23 | gcc skiplist.c skl-timer.c -o skl -I./ 24 | ``` 25 | 26 | #### 单层级时间轮 27 | 28 | ```shell 29 | gcc single_tw.c -o stw 30 | ``` 31 | 32 | #### 多层级时间轮 33 | 34 | ```shell 35 | # 关联文件 timewheel.h timewheel.c tw-timer.c spinlock.h 36 | gcc timewheel.c tw-timer.c -o tw -I./ -lpthread 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/minheap/mh-timer.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "mh-timer.h" 5 | 6 | void hello_world(timer_entry_t *te) 7 | { 8 | printf("hello world time = %u\n", te->time); 9 | } 10 | 11 | int main() 12 | { 13 | init_timer(); 14 | 15 | add_timer(3000, hello_world); 16 | 17 | int epfd = epoll_create(1); 18 | struct epoll_event events[512]; 19 | 20 | for (;;) 21 | { 22 | int nearest = find_nearest_expire_timer(); 23 | int n = epoll_wait(epfd, events, 512, nearest); 24 | for (int i = 0; i < n; i++) 25 | { 26 | // 27 | } 28 | expire_timer(); 29 | } 30 | return 0; 31 | } 32 | 33 | // gcc mh-timer.c minheap.c -o mh -I./ -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/minheap/mh-timer.h: -------------------------------------------------------------------------------- 1 | #ifndef MARK_MINHEAP_TIMER_H 2 | #define MARK_MINHEAP_TIMER_H 3 | 4 | #if defined(__APPLE__) 5 | #include 6 | #include 7 | #include 8 | #include 9 | #else 10 | #include 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "minheap.h" 20 | 21 | static min_heap_t min_heap; 22 | 23 | static uint32_t 24 | current_time() 25 | { 26 | uint32_t t; 27 | #if !defined(__APPLE__) || defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER) 28 | struct timespec ti; 29 | clock_gettime(CLOCK_MONOTONIC, &ti); 30 | t = (uint32_t)ti.tv_sec * 1000; 31 | t += ti.tv_nsec / 1000000; 32 | #else 33 | struct timeval tv; 34 | gettimeofday(&tv, NULL); 35 | t = (uint32_t)tv.tv_sec * 1000; 36 | t += tv.tv_usec / 1000; 37 | #endif 38 | return t; 39 | } 40 | 41 | void init_timer() 42 | { 43 | min_heap_ctor_(&min_heap); 44 | } 45 | 46 | timer_entry_t *add_timer(uint32_t msec, timer_handler_pt callback) 47 | { 48 | timer_entry_t *te = (timer_entry_t *)malloc(sizeof(*te)); 49 | if (!te) 50 | { 51 | return NULL; 52 | } 53 | memset(te, 0, sizeof(timer_entry_t)); 54 | 55 | te->handler = callback; 56 | te->time = current_time() + msec; 57 | 58 | if (0 != min_heap_push_(&min_heap, te)) 59 | { 60 | free(te); 61 | return NULL; 62 | } 63 | printf("add timer time = %u now = %u\n", te->time, current_time()); 64 | return te; 65 | } 66 | 67 | bool del_timer(timer_entry_t *e) 68 | { 69 | return 0 == min_heap_erase_(&min_heap, e); 70 | } 71 | 72 | int find_nearest_expire_timer() 73 | { 74 | timer_entry_t *te = min_heap_top_(&min_heap); 75 | if (!te) 76 | return -1; 77 | int diff = (int)te->time - (int)current_time(); 78 | return diff > 0 ? diff : 0; 79 | } 80 | 81 | void expire_timer() 82 | { 83 | uint32_t cur = current_time(); 84 | for (;;) 85 | { 86 | timer_entry_t *te = min_heap_top_(&min_heap); 87 | if (!te) 88 | break; 89 | if (te->time > cur) 90 | break; 91 | te->handler(te); 92 | min_heap_pop_(&min_heap); 93 | free(te); 94 | } 95 | } 96 | 97 | #endif // MARK_MINHEAP_TIMER_H 98 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/minheap/minheap.h: -------------------------------------------------------------------------------- 1 | #ifndef MARK_MINHEAP_H 2 | #define MARK_MINHEAP_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct timer_entry_s timer_entry_t; 8 | typedef void (*timer_handler_pt)(timer_entry_t *ev); 9 | 10 | struct timer_entry_s 11 | { 12 | uint32_t time; 13 | uint32_t min_heap_idx; 14 | timer_handler_pt handler; 15 | void *privdata; 16 | }; 17 | 18 | typedef struct min_heap 19 | { 20 | timer_entry_t **p; 21 | uint32_t n, a; // n 为实际元素个数 a 为容量 22 | } min_heap_t; 23 | 24 | void min_heap_ctor_(min_heap_t *s); 25 | void min_heap_dtor_(min_heap_t *s); 26 | void min_heap_elem_init_(timer_entry_t *e); 27 | int min_heap_elt_is_top_(const timer_entry_t *e); 28 | int min_heap_empty_(min_heap_t *s); 29 | unsigned min_heap_size_(min_heap_t *s); 30 | timer_entry_t *min_heap_top_(min_heap_t *s); 31 | int min_heap_reserve_(min_heap_t *s, unsigned n); 32 | int min_heap_push_(min_heap_t *s, timer_entry_t *e); 33 | timer_entry_t *min_heap_pop_(min_heap_t *s); 34 | int min_heap_adjust_(min_heap_t *s, timer_entry_t *e); 35 | int min_heap_erase_(min_heap_t *s, timer_entry_t *e); 36 | void min_heap_shift_up_(min_heap_t *s, unsigned hole_index, timer_entry_t *e); 37 | void min_heap_shift_up_unconditional_(min_heap_t *s, unsigned hole_index, timer_entry_t *e); 38 | void min_heap_shift_down_(min_heap_t *s, unsigned hole_index, timer_entry_t *e); 39 | 40 | #endif // MARK_MINHEAP_H -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/rbtree/rbt-timer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "rbt-timer.h" 5 | 6 | void hello_world(timer_entry_t *te) 7 | { 8 | printf("hello world time = %u\n", te->rbnode.key); 9 | } 10 | 11 | int main() 12 | { 13 | init_timer(); 14 | 15 | add_timer(3000, hello_world); 16 | 17 | int epfd = epoll_create(1); 18 | struct epoll_event events[512]; 19 | 20 | for (;;) 21 | { 22 | int nearest = find_nearest_expire_timer(); 23 | int n = epoll_wait(epfd, events, 512, nearest); 24 | for (int i = 0; i < n; i++) 25 | { 26 | // 27 | } 28 | expire_timer(); 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/rbtree/rbt-timer.h: -------------------------------------------------------------------------------- 1 | #ifndef _MARK_RBT_ 2 | #define _MARK_RBT_ 3 | 4 | #include 5 | #include // 整数 6 | #include // usleep 7 | #include // malloc 注意需要强转 8 | #include //offsetof 9 | 10 | #if defined(__APPLE__) 11 | #include 12 | #include 13 | #include 14 | #include 15 | #else 16 | #include 17 | #endif 18 | 19 | #include "rbtree.h" 20 | 21 | ngx_rbtree_t timer; 22 | static ngx_rbtree_node_t sentinel; 23 | 24 | typedef struct timer_entry_s timer_entry_t; 25 | typedef void (*timer_handler_pt)(timer_entry_t *ev); 26 | 27 | struct timer_entry_s 28 | { 29 | ngx_rbtree_node_t rbnode; 30 | timer_handler_pt handler; 31 | }; 32 | 33 | static uint32_t 34 | current_time() 35 | { 36 | uint32_t t; 37 | #if 0 38 | #!defined(__APPLE__) || defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER) 39 | struct timespec ti; 40 | clock_gettime(CLOCK_MONOTONIC, &ti); 41 | t = (uint32_t)ti.tv_sec * 1000; 42 | t += ti.tv_nsec / 1000000; 43 | #else 44 | struct timeval tv; 45 | gettimeofday(&tv, NULL); 46 | t = (uint32_t)tv.tv_sec * 1000; 47 | t += tv.tv_usec / 1000; 48 | #endif 49 | return t; 50 | } 51 | 52 | ngx_rbtree_t *init_timer() 53 | { 54 | ngx_rbtree_init(&timer, &sentinel, ngx_rbtree_insert_timer_value); 55 | return &timer; 56 | } 57 | 58 | void add_timer(uint32_t msec, timer_handler_pt func) 59 | { 60 | timer_entry_t *te = malloc(sizeof(timer_entry_t)); 61 | memset(te, 0, sizeof(timer_entry_t)); 62 | te->handler = func; 63 | msec += current_time(); 64 | printf("add_timer expire at msec = %u\n", msec); 65 | te->rbnode.key = msec; 66 | ngx_rbtree_insert(&timer, &te->rbnode); 67 | } 68 | 69 | void del_timer(timer_entry_t *te) 70 | { 71 | ngx_rbtree_delete(&timer, &te->rbnode); 72 | free(te); 73 | } 74 | 75 | int find_nearest_expire_timer() 76 | { 77 | ngx_rbtree_node_t *node; 78 | if (timer.root == &sentinel) 79 | { 80 | return -1; 81 | } 82 | node = ngx_rbtree_min(timer.root, timer.sentinel); 83 | int diff = (int)node->key - (int)current_time(); 84 | return diff > 0 ? diff : 0; 85 | } 86 | 87 | void expire_timer() 88 | { 89 | timer_entry_t *te; 90 | ngx_rbtree_node_t *sentinel, *root, *node; 91 | sentinel = timer.sentinel; 92 | uint32_t now = current_time(); 93 | for (;;) 94 | { 95 | root = timer.root; 96 | if (root == sentinel) 97 | break; 98 | node = ngx_rbtree_min(root, sentinel); 99 | if (node->key > now) 100 | break; 101 | printf("touch timer expire time=%u, now = %u\n", node->key, now); 102 | te = (timer_entry_t *)((char *)node - offsetof(timer_entry_t, rbnode)); 103 | te->handler(te); 104 | ngx_rbtree_delete(&timer, &te->rbnode); 105 | free(te); 106 | } 107 | } 108 | 109 | #endif -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/rbtree/rbtree.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Igor Sysoev 4 | * Copyright (C) Nginx, Inc. 5 | */ 6 | 7 | #ifndef _NGX_RBTREE_H_INCLUDED_ 8 | #define _NGX_RBTREE_H_INCLUDED_ 9 | 10 | typedef unsigned int ngx_rbtree_key_t; 11 | typedef unsigned int ngx_uint_t; 12 | typedef int ngx_rbtree_key_int_t; 13 | typedef unsigned char u_char; 14 | #ifndef NULL 15 | #define NULL ((void *)0) 16 | #endif 17 | 18 | typedef struct ngx_rbtree_node_s ngx_rbtree_node_t; 19 | 20 | struct ngx_rbtree_node_s 21 | { 22 | ngx_rbtree_key_t key; 23 | ngx_rbtree_node_t *left; 24 | ngx_rbtree_node_t *right; 25 | ngx_rbtree_node_t *parent; 26 | u_char color; 27 | u_char data; 28 | }; 29 | 30 | typedef struct ngx_rbtree_s ngx_rbtree_t; 31 | 32 | typedef void (*ngx_rbtree_insert_pt)(ngx_rbtree_node_t *root, 33 | ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 34 | 35 | struct ngx_rbtree_s 36 | { 37 | ngx_rbtree_node_t *root; 38 | ngx_rbtree_node_t *sentinel; 39 | ngx_rbtree_insert_pt insert; 40 | }; 41 | 42 | #define ngx_rbtree_init(tree, s, i) \ 43 | ngx_rbtree_sentinel_init(s); \ 44 | (tree)->root = s; \ 45 | (tree)->sentinel = s; \ 46 | (tree)->insert = i 47 | 48 | void ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node); 49 | 50 | void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node); 51 | 52 | void ngx_rbtree_insert_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node, 53 | ngx_rbtree_node_t *sentinel); 54 | 55 | void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root, 56 | ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 57 | 58 | ngx_rbtree_node_t * 59 | ngx_rbtree_next(ngx_rbtree_t *tree, 60 | ngx_rbtree_node_t *node); 61 | 62 | #define ngx_rbt_red(node) ((node)->color = 1) 63 | #define ngx_rbt_black(node) ((node)->color = 0) 64 | #define ngx_rbt_is_red(node) ((node)->color) 65 | #define ngx_rbt_is_black(node) (!ngx_rbt_is_red(node)) 66 | #define ngx_rbt_copy_color(n1, n2) (n1->color = n2->color) 67 | 68 | /* a sentinel must be black */ 69 | 70 | #define ngx_rbtree_sentinel_init(node) ngx_rbt_black(node) 71 | 72 | static ngx_rbtree_node_t * 73 | ngx_rbtree_min(ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) 74 | { 75 | while (node->left != sentinel) 76 | { 77 | node = node->left; 78 | } 79 | 80 | return node; 81 | } 82 | 83 | #endif /* _NGX_RBTREE_H_INCLUDED_ */ 84 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/skiplist/skiplist.h: -------------------------------------------------------------------------------- 1 | #ifndef _MARK_SKIPLIST_ 2 | #define _MARK_SKIPLIST_ 3 | 4 | /* ZSETs use a specialized version of Skiplists */ 5 | #define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^64 elements */ 6 | #define ZSKIPLIST_P 0.25 /* Skiplist P = 1/2 */ 7 | 8 | typedef struct zskiplistNode zskiplistNode; 9 | typedef void (*handler_pt)(zskiplistNode *node); 10 | struct zskiplistNode 11 | { 12 | // sds ele; 13 | // double score; 14 | unsigned long score; // 时间戳 15 | handler_pt handler; 16 | /*struct zskiplistNode *backward; 从后向前遍历时使用*/ 17 | struct zskiplistLevel 18 | { 19 | struct zskiplistNode *forward; 20 | /* unsigned long span; 这个存储的level间节点的个数,在定时器中并不需要*/ 21 | } level[]; 22 | }; 23 | 24 | typedef struct zskiplist 25 | { 26 | // 添加一个free的函数 27 | struct zskiplistNode *header /*, *tail 并不需要知道最后一个节点*/; 28 | int length; 29 | int level; 30 | } zskiplist; 31 | 32 | zskiplist *zslCreate(void); 33 | void zslFree(zskiplist *zsl); 34 | zskiplistNode *zslInsert(zskiplist *zsl, unsigned long score, handler_pt func); 35 | zskiplistNode *zslMin(zskiplist *zsl); 36 | void zslDeleteHead(zskiplist *zsl); 37 | void zslDelete(zskiplist *zsl, zskiplistNode *zn); 38 | 39 | void zslPrint(zskiplist *zsl); 40 | #endif 41 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/skiplist/skl-timer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #if defined(__APPLE__) 7 | #include 8 | #include 9 | #include 10 | #include 11 | #else 12 | #include 13 | #endif 14 | #include "skiplist.h" 15 | 16 | static uint32_t 17 | current_time() 18 | { 19 | uint32_t t; 20 | #if !defined(__APPLE__) || defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER) 21 | struct timespec ti; 22 | clock_gettime(CLOCK_MONOTONIC, &ti); 23 | t = (uint32_t)ti.tv_sec * 1000; 24 | t += ti.tv_nsec / 1000000; 25 | #else 26 | struct timeval tv; 27 | gettimeofday(&tv, NULL); 28 | t = (uint32_t)tv.tv_sec * 1000; 29 | t += tv.tv_usec / 1000; 30 | #endif 31 | return t; 32 | } 33 | 34 | zskiplist *init_timer() 35 | { 36 | return zslCreate(); 37 | } 38 | 39 | zskiplistNode *add_timer(zskiplist *zsl, uint32_t msec, handler_pt func) 40 | { 41 | msec += current_time(); 42 | printf("add_timer expire at msec = %u\n", msec); 43 | return zslInsert(zsl, msec, func); 44 | } 45 | 46 | void del_timer(zskiplist *zsl, zskiplistNode *zn) 47 | { 48 | zslDelete(zsl, zn); 49 | } 50 | 51 | void expire_timer(zskiplist *zsl) 52 | { 53 | zskiplistNode *x; 54 | uint32_t now = current_time(); 55 | for (;;) 56 | { 57 | x = zslMin(zsl); 58 | if (!x) 59 | break; 60 | if (x->score > now) 61 | break; 62 | printf("touch timer expire time=%lu, now = %u\n", x->score, now); 63 | x->handler(x); 64 | zslDeleteHead(zsl); 65 | } 66 | } 67 | 68 | void print_hello(zskiplistNode *zn) 69 | { 70 | printf("hello world time = %lu\n", zn->score); 71 | } 72 | 73 | int main() 74 | { 75 | zskiplist *zsl = init_timer(); 76 | add_timer(zsl, 3010, print_hello); 77 | add_timer(zsl, 4004, print_hello); 78 | zskiplistNode *zn = add_timer(zsl, 3005, print_hello); 79 | del_timer(zsl, zn); 80 | add_timer(zsl, 5008, print_hello); 81 | add_timer(zsl, 7003, print_hello); 82 | // zslPrint(zsl); 83 | for (;;) 84 | { 85 | expire_timer(zsl); 86 | usleep(10000); 87 | } 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/timewheel/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SPINLOCK_H 2 | #define SPINLOCK_H 3 | 4 | struct spinlock 5 | { 6 | int lock; 7 | }; 8 | 9 | void spinlock_init(struct spinlock *lock) 10 | { 11 | lock->lock = 0; 12 | } 13 | 14 | void spinlock_lock(struct spinlock *lock) 15 | { 16 | while (__sync_lock_test_and_set(&lock->lock, 1)) 17 | { 18 | } 19 | } 20 | 21 | int spinlock_trylock(struct spinlock *lock) 22 | { 23 | return __sync_lock_test_and_set(&lock->lock, 1) == 0; 24 | } 25 | 26 | void spinlock_unlock(struct spinlock *lock) 27 | { 28 | __sync_lock_release(&lock->lock); 29 | } 30 | 31 | void spinlock_destroy(struct spinlock *lock) 32 | { 33 | (void)lock; 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/timewheel/timewheel.h: -------------------------------------------------------------------------------- 1 | #ifndef _MARK_TIMEWHEEL_ 2 | #define _MARK_TIMEWHEEL_ 3 | 4 | #include 5 | 6 | #define TIME_NEAR_SHIFT 8 7 | #define TIME_NEAR (1 << TIME_NEAR_SHIFT) 8 | #define TIME_LEVEL_SHIFT 6 9 | #define TIME_LEVEL (1 << TIME_LEVEL_SHIFT) 10 | #define TIME_NEAR_MASK (TIME_NEAR - 1) 11 | #define TIME_LEVEL_MASK (TIME_LEVEL - 1) 12 | 13 | typedef struct timer_node timer_node_t; 14 | typedef void (*handler_pt)(struct timer_node *node); 15 | 16 | struct timer_node 17 | { 18 | struct timer_node *next; 19 | uint32_t expire; 20 | handler_pt callback; 21 | uint8_t cancel; 22 | int id; // 此时携带参数 23 | }; 24 | 25 | timer_node_t *add_timer(int time, handler_pt func, int threadid); 26 | 27 | void expire_timer(void); 28 | 29 | void del_timer(timer_node_t *node); 30 | 31 | void init_timer(void); 32 | 33 | void clear_timer(); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/example/timewheel/tw-timer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include "timewheel.h" 8 | 9 | struct context 10 | { 11 | int quit; 12 | int thread; 13 | }; 14 | 15 | struct thread_param 16 | { 17 | struct context *ctx; 18 | int id; 19 | }; 20 | 21 | static struct context ctx = {0}; 22 | 23 | void do_timer(timer_node_t *node) 24 | { 25 | printf("timer expired:%d - thread-id:%d\n", node->expire, node->id); 26 | } 27 | 28 | void *thread_worker(void *p) 29 | { 30 | struct thread_param *tp = p; 31 | int id = tp->id; 32 | struct context *ctx = tp->ctx; 33 | while (!ctx->quit) 34 | { 35 | int expire = rand() % 200; 36 | add_timer(expire, do_timer, id); 37 | usleep(expire * (10 - 1) * 1000); 38 | } 39 | printf("thread_worker:%d exit!\n", id); 40 | return NULL; 41 | } 42 | 43 | void do_quit(timer_node_t *node) 44 | { 45 | ctx.quit = 1; 46 | } 47 | 48 | int main() 49 | { 50 | srand(time(NULL)); 51 | ctx.thread = 8; 52 | pthread_t pid[ctx.thread]; 53 | 54 | init_timer(); 55 | add_timer(6000, do_quit, 100); 56 | struct thread_param task_thread_p[ctx.thread]; 57 | int i; 58 | for (i = 0; i < ctx.thread; i++) 59 | { 60 | task_thread_p[i].id = i; 61 | task_thread_p[i].ctx = &ctx; 62 | if (pthread_create(&pid[i], NULL, thread_worker, &task_thread_p[i])) 63 | { 64 | fprintf(stderr, "create thread failed\n"); 65 | exit(1); 66 | } 67 | } 68 | 69 | while (!ctx.quit) 70 | { 71 | expire_timer(); 72 | usleep(2500); 73 | } 74 | clear_timer(); 75 | for (i = 0; i < ctx.thread; i++) 76 | { 77 | pthread_join(pid[i], NULL); 78 | } 79 | printf("all thread is closed\n"); 80 | return 0; 81 | } 82 | 83 | // gcc tw-timer.c timewheel.c -o tw -I./ -lpthread -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/minheap/mh-timer_hw.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "mh-timer.h" 5 | 6 | void hello_world(timer_entry_t *te) 7 | { 8 | } 9 | 10 | int main() 11 | { 12 | } 13 | 14 | // gcc mh-timer.c minheap.c -o mh -I./ -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/minheap/mh-timer_hw.h: -------------------------------------------------------------------------------- 1 | #ifndef MARK_MINHEAP_TIMER_H 2 | #define MARK_MINHEAP_TIMER_H 3 | 4 | #if defined(__APPLE__) 5 | #include 6 | #include 7 | #include 8 | #include 9 | #else 10 | #include 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "minheap.h" 20 | 21 | static min_heap_t min_heap; 22 | 23 | static uint32_t 24 | current_time() 25 | { 26 | uint32_t t; 27 | struct timespec ti; 28 | clock_gettime(CLOCK_MONOTONIC, &ti); 29 | t = (uint32_t)ti.tv_sec * 1000; 30 | t += ti.tv_nsec / 1000000; 31 | return t; 32 | } 33 | 34 | void init_timer() 35 | { 36 | min_heap_ctor_(&min_heap); 37 | } 38 | 39 | timer_entry_t *add_timer(uint32_t msec, timer_handler_pt callback) 40 | { 41 | } 42 | 43 | bool del_timer(timer_entry_t *e) 44 | { 45 | } 46 | 47 | int find_nearest_expire_timer() 48 | { 49 | } 50 | 51 | void expire_timer() 52 | { 53 | } 54 | 55 | #endif // MARK_MINHEAP_TIMER_H 56 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/rbtree/rbt-timer_hw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "rbt-timer.h" 5 | 6 | void hello_world(timer_entry_t *te) 7 | { 8 | printf("hello world time = %u\n", te->rbnode.key); 9 | } 10 | 11 | int main() 12 | { 13 | init_timer(); 14 | 15 | add_timer(3000, hello_world); 16 | 17 | int epfd = epoll_create(1); 18 | struct epoll_event events[512]; 19 | 20 | for (;;) 21 | { 22 | int nearest = find_nearest_expire_timer(); 23 | int n = epoll_wait(epfd, events, 512, nearest); 24 | for (int i = 0; i < n; i++) 25 | { 26 | // 27 | } 28 | expire_timer(); 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/rbtree/rbt-timer_hw.h: -------------------------------------------------------------------------------- 1 | #ifndef _MARK_RBT_ 2 | #define _MARK_RBT_ 3 | 4 | #include 5 | #include // 整数 6 | #include // usleep 7 | #include // malloc 注意需要强转 8 | #include //offsetof 9 | 10 | #if defined(__APPLE__) 11 | #include 12 | #include 13 | #include 14 | #include 15 | #else 16 | #include 17 | #endif 18 | 19 | #include "rbtree.h" 20 | 21 | ngx_rbtree_t timer; 22 | static ngx_rbtree_node_t sentinel; 23 | 24 | typedef struct timer_entry_s timer_entry_t; 25 | typedef void (*timer_handler_pt)(timer_entry_t *ev); 26 | 27 | struct timer_entry_s 28 | { 29 | ngx_rbtree_node_t rbnode; 30 | timer_handler_pt handler; 31 | }; 32 | 33 | static uint32_t 34 | current_time() 35 | { 36 | uint32_t t; 37 | #if !defined(__APPLE__) || defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER) 38 | struct timespec ti; 39 | clock_gettime(CLOCK_MONOTONIC, &ti); 40 | t = (uint32_t)ti.tv_sec * 1000; 41 | t += ti.tv_nsec / 1000000; 42 | #else 43 | struct timeval tv; 44 | gettimeofday(&tv, NULL); 45 | t = (uint32_t)tv.tv_sec * 1000; 46 | t += tv.tv_usec / 1000; 47 | #endif 48 | return t; 49 | } 50 | 51 | ngx_rbtree_t *init_timer() 52 | { 53 | ngx_rbtree_init(&timer, &sentinel, ngx_rbtree_insert_timer_value); 54 | return &timer; 55 | } 56 | 57 | void add_timer(uint32_t msec, timer_handler_pt func) 58 | { 59 | timer_entry_t *te = malloc(sizeof(timer_entry_t)); 60 | memset(te, 0, sizeof(timer_entry_t)); 61 | te->handler = func; 62 | msec += current_time(); 63 | printf("add_timer expire at msec = %u\n", msec); 64 | te->rbnode.key = msec; 65 | ngx_rbtree_insert(&timer, &te->rbnode); 66 | } 67 | 68 | void del_timer(timer_entry_t *te) 69 | { 70 | ngx_rbtree_delete(&timer, &te->rbnode); 71 | free(te); 72 | } 73 | 74 | int find_nearest_expire_timer() 75 | { 76 | ngx_rbtree_node_t *node; 77 | if (timer.root == &sentinel) 78 | { 79 | return -1; 80 | } 81 | node = ngx_rbtree_min(timer.root, timer.sentinel); 82 | int diff = (int)node->key - (int)current_time(); 83 | return diff > 0 ? diff : 0; 84 | } 85 | 86 | void expire_timer() 87 | { 88 | timer_entry_t *te; 89 | ngx_rbtree_node_t *sentinel, *root, *node; 90 | sentinel = timer.sentinel; 91 | uint32_t now = current_time(); 92 | for (;;) 93 | { 94 | root = timer.root; 95 | if (root == sentinel) 96 | break; 97 | node = ngx_rbtree_min(root, sentinel); 98 | if (node->key > now) 99 | break; 100 | printf("touch timer expire time=%u, now = %u\n", node->key, now); 101 | te = (timer_entry_t *)((char *)node - offsetof(timer_entry_t, rbnode)); 102 | te->handler(te); 103 | ngx_rbtree_delete(&timer, &te->rbnode); 104 | free(te); 105 | } 106 | } 107 | 108 | #endif -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/skiplist/skl-timer_hw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #if defined(__APPLE__) 7 | #include 8 | #include 9 | #include 10 | #include 11 | #else 12 | #include 13 | #endif 14 | #include "skiplist.h" 15 | 16 | static uint32_t 17 | current_time() 18 | { 19 | uint32_t t; 20 | #if !defined(__APPLE__) || defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER) 21 | struct timespec ti; 22 | clock_gettime(CLOCK_MONOTONIC, &ti); 23 | t = (uint32_t)ti.tv_sec * 1000; 24 | t += ti.tv_nsec / 1000000; 25 | #else 26 | struct timeval tv; 27 | gettimeofday(&tv, NULL); 28 | t = (uint32_t)tv.tv_sec * 1000; 29 | t += tv.tv_usec / 1000; 30 | #endif 31 | return t; 32 | } 33 | 34 | zskiplist *init_timer() 35 | { 36 | return zslCreate(); 37 | } 38 | 39 | zskiplistNode *add_timer(zskiplist *zsl, uint32_t msec, handler_pt func) 40 | { 41 | msec += current_time(); 42 | printf("add_timer expire at msec = %u\n", msec); 43 | return zslInsert(zsl, msec, func); 44 | } 45 | 46 | void del_timer(zskiplist *zsl, zskiplistNode *zn) 47 | { 48 | zslDelete(zsl, zn); 49 | } 50 | 51 | void expire_timer(zskiplist *zsl) 52 | { 53 | zskiplistNode *x; 54 | uint32_t now = current_time(); 55 | for (;;) 56 | { 57 | x = zslMin(zsl); 58 | if (!x) 59 | break; 60 | if (x->score > now) 61 | break; 62 | printf("touch timer expire time=%lu, now = %u\n", x->score, now); 63 | x->handler(x); 64 | zslDeleteHead(zsl); 65 | } 66 | } 67 | 68 | void print_hello(zskiplistNode *zn) 69 | { 70 | printf("hello world time = %lu\n", zn->score); 71 | } 72 | 73 | int main() 74 | { 75 | zskiplist *zsl = init_timer(); 76 | add_timer(zsl, 3010, print_hello); 77 | add_timer(zsl, 4004, print_hello); 78 | zskiplistNode *zn = add_timer(zsl, 3005, print_hello); 79 | del_timer(zsl, zn); 80 | add_timer(zsl, 5008, print_hello); 81 | add_timer(zsl, 7003, print_hello); 82 | // zslPrint(zsl); 83 | for (;;) 84 | { 85 | expire_timer(zsl); 86 | usleep(10000); 87 | } 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/timewheel/timewheel.h: -------------------------------------------------------------------------------- 1 | #ifndef _MARK_TIMEWHEEL_ 2 | #define _MARK_TIMEWHEEL_ 3 | 4 | #include 5 | 6 | #define TIME_NEAR_SHIFT 8 7 | #define TIME_NEAR (1 << TIME_NEAR_SHIFT) 8 | #define TIME_LEVEL_SHIFT 6 9 | #define TIME_LEVEL (1 << TIME_LEVEL_SHIFT) 10 | #define TIME_NEAR_MASK (TIME_NEAR - 1) 11 | #define TIME_LEVEL_MASK (TIME_LEVEL - 1) 12 | 13 | typedef struct timer_node timer_node_t; 14 | typedef void (*handler_pt)(struct timer_node *node); 15 | 16 | struct timer_node 17 | { 18 | struct timer_node *next; 19 | uint32_t expire; 20 | handler_pt callback; 21 | uint8_t cancel; 22 | int id; // 此时携带参数 23 | }; 24 | 25 | timer_node_t *add_timer(int time, handler_pt func, int threadid); 26 | 27 | void expire_timer(void); 28 | 29 | void del_timer(timer_node_t *node); 30 | 31 | void init_timer(void); 32 | 33 | void clear_timer(); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/timewheel/tw-timer_hw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include "timewheel.h" 8 | 9 | struct context 10 | { 11 | int quit; 12 | int thread; 13 | }; 14 | 15 | struct thread_param 16 | { 17 | struct context *ctx; 18 | int id; 19 | }; 20 | 21 | static struct context ctx = {0}; 22 | 23 | void do_timer(timer_node_t *node) 24 | { 25 | printf("timer expired:%d - thread-id:%d\n", node->expire, node->id); 26 | } 27 | 28 | void *thread_worker(void *p) 29 | { 30 | struct thread_param *tp = p; 31 | int id = tp->id; 32 | struct context *ctx = tp->ctx; 33 | while (!ctx->quit) 34 | { 35 | int expire = rand() % 200; 36 | add_timer(expire, do_timer, id); 37 | usleep(expire * (10 - 1) * 1000); 38 | } 39 | printf("thread_worker:%d exit!\n", id); 40 | return NULL; 41 | } 42 | 43 | void do_quit(timer_node_t *node) 44 | { 45 | ctx.quit = 1; 46 | } 47 | 48 | int main() 49 | { 50 | srand(time(NULL)); 51 | ctx.thread = 8; 52 | pthread_t pid[ctx.thread]; 53 | 54 | init_timer(); 55 | add_timer(6000, do_quit, 100); 56 | struct thread_param task_thread_p[ctx.thread]; 57 | int i; 58 | for (i = 0; i < ctx.thread; i++) 59 | { 60 | task_thread_p[i].id = i; 61 | task_thread_p[i].ctx = &ctx; 62 | if (pthread_create(&pid[i], NULL, thread_worker, &task_thread_p[i])) 63 | { 64 | fprintf(stderr, "create thread failed\n"); 65 | exit(1); 66 | } 67 | } 68 | 69 | while (!ctx.quit) 70 | { 71 | expire_timer(); 72 | usleep(2500); 73 | } 74 | clear_timer(); 75 | for (i = 0; i < ctx.thread; i++) 76 | { 77 | pthread_join(pid[i], NULL); 78 | } 79 | printf("all thread is closed\n"); 80 | return 0; 81 | } 82 | 83 | // gcc tw-timer.c timewheel.c -o tw -I./ -lpthread -------------------------------------------------------------------------------- /3.2高性能组件/3.2.2定时器方案红黑树,时间轮,最小堆/timers_src/practice/timewheel_single/single_tw_hw.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @File Name: single_tw_hw.c 3 | * @Brief : 单层级时间轮 4 | * @Author : hewei (hewei_1996@qq.com) 5 | * @Version : 1.0 6 | * @Creat Date : 2022-03-31 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #define MAX_TIMER ((1 << 17) - 1) 17 | #define MAX_CONN ((1 << 16) - 1) 18 | 19 | typedef struct conn_node 20 | { 21 | uint8_t used; // 引用 就是这段时间发送的心跳包的个数 22 | int id; // fd 23 | } conn_node_t; 24 | 25 | typedef struct timer_node 26 | { 27 | struct timer_node *next; // 下一个 28 | struct conn_node *node; // 本身 29 | uint32_t idx; 30 | } timer_node_t; 31 | 32 | static timer_node_t timer_nodes[MAX_TIMER] = {0}; 33 | static conn_node_t conn_nodes[MAX_CONN] = {0}; 34 | static uint32_t t_iter = 0; 35 | static uint32_t c_iter = 0; 36 | 37 | timer_node_t *get_timer_node() 38 | { // 注意:没有检测定时任务数超过 MAX_TIMER 的情况 39 | } 40 | 41 | conn_node_t *get_conn_node() 42 | { // 注意:没有检测连接数超过 MAX_CONN 的情况 43 | } 44 | 45 | #define TW_SIZE 16 46 | #define EXPIRE 10 47 | #define TW_MASK (TW_SIZE - 1) 48 | static uint32_t tick = 0; 49 | 50 | typedef struct link_list 51 | { 52 | timer_node_t head; // 方便遍历 53 | timer_node_t *tail; // 方便添加 54 | } link_list_t; 55 | 56 | void add_conn(link_list_t *tw, conn_node_t *cnode, int delay) 57 | { 58 | } 59 | 60 | void link_clear(link_list_t *list) 61 | { 62 | } 63 | 64 | void check_conn(link_list_t *tw) 65 | { 66 | } 67 | 68 | static time_t 69 | current_time() 70 | { 71 | } 72 | 73 | int main() 74 | { 75 | } 76 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/1.picture/上课演示20211218.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.3无锁消息队列实现/1.picture/上课演示20211218.png -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/2.doc/无锁消息队列实现-课件.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.3无锁消息队列实现/2.doc/无锁消息队列实现-课件.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.3无锁消息队列实现/CMakeLists.txt -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/src/cas_queue/1_test_i++.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2020-05-31 18:33:36 4 | * @LastEditTime: 2020-05-31 18:34:15 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \cas\1_test_i++.c 8 | */ 9 | #include 10 | 11 | int i = 0; 12 | // gcc -S 1_test_i++.c 13 | int main(int argc, char **argv) 14 | { 15 | ++i; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/src/cas_queue/2_test_i++_threads.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2020-05-31 18:34:32 4 | * @LastEditTime: 2020-05-31 20:33:16 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \cas\2_test_i++_threads.c 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | #define THREAD_NUMBER 2 14 | #define THREAD_INCR_COUNT 100000 15 | static int s_i = 0; 16 | 17 | static int lxx_atomic_add(int *ptr, int increment) 18 | { 19 | int old_value = *ptr; 20 | __asm__ volatile("lock; xadd %0, %1 \n\t" 21 | : "=r"(old_value), "=m"(*ptr) 22 | : "0"(increment), "m"(*ptr) 23 | : "cc", "memory"); 24 | return *ptr; 25 | } 26 | 27 | void *thread_increase(void *arg) 28 | { 29 | for (int i = 0; i < THREAD_INCR_COUNT; ++i) 30 | { 31 | // ++s_i; // ++s_i 会怎么样? 32 | lxx_atomic_add(&s_i, 1); 33 | } 34 | printf("finish\n"); 35 | pthread_exit(NULL); 36 | } 37 | 38 | // 多运行几次 39 | // gcc -o 2_test_i++_threads 2_test_i++_threads.c -lpthread 40 | int main(int argc, char **argv) 41 | { 42 | pthread_t threadArr[THREAD_NUMBER]; 43 | for (int i = 0; i < THREAD_NUMBER; ++i) 44 | { 45 | pthread_create(&threadArr[i], NULL, thread_increase, NULL); 46 | } 47 | 48 | for (int i = 0; i < THREAD_NUMBER; ++i) 49 | { 50 | pthread_join(threadArr[i], NULL); 51 | } 52 | printf("s_i actual:%d, expected:%d\n", s_i, THREAD_NUMBER * THREAD_INCR_COUNT); 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/src/cas_queue/ArrayLockFreeQueue.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARRAYLOCKFREEQUEUE_H___ 2 | #define _ARRAYLOCKFREEQUEUE_H___ 3 | 4 | #include 5 | 6 | #ifdef _WIN64 7 | #define QUEUE_INT int64_t 8 | #else 9 | #define QUEUE_INT unsigned long 10 | #endif 11 | 12 | #define ARRAY_LOCK_FREE_Q_DEFAULT_SIZE 65535 // 2^16 13 | 14 | template 15 | class ArrayLockFreeQueue 16 | { 17 | public: 18 | ArrayLockFreeQueue(); 19 | virtual ~ArrayLockFreeQueue(); 20 | 21 | QUEUE_INT size(); 22 | 23 | bool enqueue(const ELEM_T &a_data); 24 | 25 | bool dequeue(ELEM_T &a_data); 26 | 27 | bool try_dequeue(ELEM_T &a_data); 28 | 29 | private: 30 | ELEM_T m_thequeue[Q_SIZE]; 31 | 32 | volatile QUEUE_INT m_count; 33 | volatile QUEUE_INT m_writeIndex; 34 | 35 | volatile QUEUE_INT m_readIndex; 36 | 37 | volatile QUEUE_INT m_maximumReadIndex; 38 | 39 | inline QUEUE_INT countToIndex(QUEUE_INT a_count); 40 | }; 41 | 42 | #include "ArrayLockFreeQueueImp.h" 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/src/cas_queue/atom_opt.h: -------------------------------------------------------------------------------- 1 | #ifndef _ATOM_OPT_H___ 2 | #define _ATOM_OPT_H___ 3 | 4 | #ifdef __GNUC__ 5 | #define CAS(a_ptr, a_oldVal, a_newVal) __sync_bool_compare_and_swap(a_ptr, a_oldVal, a_newVal) 6 | #define AtomicAdd(a_ptr, a_count) __sync_fetch_and_add(a_ptr, a_count) 7 | #define AtomicSub(a_ptr, a_count) __sync_fetch_and_sub(a_ptr, a_count) 8 | #include // sched_yield() 9 | #else 10 | 11 | #include 12 | #ifdef _WIN64 13 | #define CAS(a_ptr, a_oldVal, a_newVal) (a_oldVal == InterlockedCompareExchange64(a_ptr, a_newVal, a_oldVal)) 14 | #define sched_yield() SwitchToThread() 15 | #define AtomicAdd(a_ptr, num) InterlockedIncrement64(a_ptr) 16 | #define AtomicSub(a_ptr, num) InterlockedDecrement64(a_ptr) 17 | #else 18 | #define CAS(a_ptr, a_oldVal, a_newVal) (a_oldVal == InterlockedCompareExchange(a_ptr, a_newVal, a_oldVal)) 19 | #define sched_yield() SwitchToThread() 20 | #define AtomicAdd(a_ptr, num) InterlockedIncrement(a_ptr) 21 | #define AtomicSub(a_ptr, num) InterlockedDecrement(a_ptr) 22 | #endif 23 | 24 | #endif 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/src/cas_queue_hw/1_test_i++.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2020-05-31 18:33:36 4 | * @LastEditTime: 2020-05-31 18:34:15 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \cas\1_test_i++.c 8 | */ 9 | #include 10 | 11 | int i = 0; 12 | // gcc -S 1_test_i++.c 13 | int main(int argc, char **argv) 14 | { 15 | ++i; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /3.2高性能组件/3.2.3无锁消息队列实现/src/cas_queue_hw/2_test_i++_threads.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2020-05-31 18:34:32 4 | * @LastEditTime: 2020-05-31 20:33:16 5 | * @LastEditors: Please set LastEditors 6 | * @Description: In User Settings Edit 7 | * @FilePath: \cas\2_test_i++_threads.c 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | #define THREAD_NUMBER 2 14 | #define THREAD_INCR_COUNT 100000 15 | static int s_i = 0; 16 | 17 | static int lxx_atomic_add(int *ptr, int increment) 18 | { 19 | int old_value = *ptr; 20 | __asm__ volatile("lock; xadd %0, %1 \n\t" 21 | : "=r"(old_value), "=m"(*ptr) 22 | : "0"(increment), "m"(*ptr) 23 | : "cc", "memory"); 24 | return *ptr; 25 | } 26 | 27 | void *thread_increase(void *arg) 28 | { 29 | for (int i = 0; i < THREAD_INCR_COUNT; ++i) 30 | { 31 | // ++s_i; // ++s_i 会怎么样? 32 | lxx_atomic_add(&s_i, 1); 33 | } 34 | printf("finish\n"); 35 | pthread_exit(NULL); 36 | } 37 | 38 | // 多运行几次 39 | // gcc -o 2_test_i++_threads 2_test_i++_threads.c -lpthread 40 | int main(int argc, char **argv) 41 | { 42 | pthread_t threadArr[THREAD_NUMBER]; 43 | for (int i = 0; i < THREAD_NUMBER; ++i) 44 | { 45 | pthread_create(&threadArr[i], NULL, thread_increase, NULL); 46 | } 47 | 48 | for (int i = 0; i < THREAD_NUMBER; ++i) 49 | { 50 | pthread_join(threadArr[i], NULL); 51 | } 52 | printf("s_i actual:%d, expected:%d\n", s_i, THREAD_NUMBER * THREAD_INCR_COUNT); 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.4手写死锁检测组件/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.4手写死锁检测组件/1.picture/Untitled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.4手写死锁检测组件/1.picture/Untitled.png -------------------------------------------------------------------------------- /3.2高性能组件/3.2.4手写死锁检测组件/1.picture/死锁检测.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.4手写死锁检测组件/1.picture/死锁检测.png -------------------------------------------------------------------------------- /3.2高性能组件/3.2.4手写死锁检测组件/2.doc/使用锁分配图动态检测混合死锁.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.4手写死锁检测组件/2.doc/使用锁分配图动态检测混合死锁.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.4手写死锁检测组件/2.doc/手写死锁检测组件.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.4手写死锁检测组件/2.doc/手写死锁检测组件.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.4手写死锁检测组件/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(DEADLOCK_HW) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | include_directories(${CMAKE_SOURCE_DIR}/inc) 10 | 11 | add_executable(deadlock_success src/example/deadlock_success.c) 12 | TARGET_LINK_LIBRARIES(deadlock_success pthread dl) 13 | 14 | add_executable(deadlock_hw src/practice/deadlock_hw.c) 15 | TARGET_LINK_LIBRARIES(deadlock_hw pthread dl) -------------------------------------------------------------------------------- /3.2高性能组件/3.2.4手写死锁检测组件/src/practice/deadlock_hw.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.4手写死锁检测组件/src/practice/deadlock_hw.c -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/1.picture/Untitled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.5手写内存泄漏检测组件/1.picture/Untitled.png -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/2.doc/atc20-wu-mingyu.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.5手写内存泄漏检测组件/2.doc/atc20-wu-mingyu.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/2.doc/手写内存泄漏检测组件.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.5手写内存泄漏检测组件/2.doc/手写内存泄漏检测组件.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/2.doc/有效的C 内存泄露检测方法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.5手写内存泄漏检测组件/2.doc/有效的C 内存泄露检测方法.pdf -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(DEADLOCK_HW) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | include_directories(${CMAKE_SOURCE_DIR}/inc) 10 | 11 | add_executable(deadlock_success src/example/deadlock_success.c) 12 | TARGET_LINK_LIBRARIES(deadlock_success pthread dl) 13 | 14 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计——高性能组件(内存泄漏检测) 3 | 4 | addr2line -f -e ./mem -a 打印的地址 5 | 6 | 7 | export MALLOC_TRACE=./test.log -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/src/example/mem/0x563d466c72a0.mem: -------------------------------------------------------------------------------- 1 | [+0x563d44ad05dc] --> addr:0x563d466c72a0, size:20 2 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/src/example/memleak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.5手写内存泄漏检测组件/src/example/memleak -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/src/example/memleak.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.5手写内存泄漏检测组件/src/example/memleak.c -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/src/example/shmem.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | // shmget 4 | 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // mmap 14 | #if 0 15 | void *shm_mmap_alloc(int size) { 16 | 17 | void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, 18 | MAP_ANON | MAP_SHARED, -1, 0); 19 | if (addr == MAP_FAILED) { 20 | return NULL; 21 | } 22 | return addr; 23 | 24 | } 25 | 26 | int shm_mmap_free(void *addr, int size) { 27 | 28 | return munmap(addr, size); 29 | 30 | } 31 | #else 32 | 33 | 34 | void *shm_mmap_alloc(int size) { 35 | 36 | int fd = open("/dev/zero", O_RDWR); 37 | 38 | void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, 39 | MAP_SHARED, fd, 0); 40 | close(fd); 41 | 42 | if (addr == MAP_FAILED) { 43 | return NULL; 44 | } 45 | 46 | return addr; 47 | 48 | } 49 | 50 | int shm_mmap_free(void *addr, int size) { 51 | 52 | return munmap(addr, size); 53 | 54 | } 55 | 56 | #endif 57 | 58 | // 59 | 60 | // a.jpg 61 | 62 | // fd = open("a.jpg", "r"); 63 | 64 | // int length = read(fd, buffer, 1024) 65 | 66 | int main() { 67 | 68 | char *addr= (char *)shm_mmap_alloc(1024 * 1024); 69 | 70 | pid_t pid = fork(); 71 | if (pid == 0) { 72 | 73 | int i = 0; 74 | 75 | while (i < 26) { 76 | addr[i] = 'a' + i ++; 77 | addr[i] = '\0'; 78 | sleep(1); 79 | } 80 | 81 | 82 | } else if (pid > 0) { 83 | 84 | int i = 0; 85 | while (i ++ < 26) { 86 | 87 | printf("client : %s\n", addr); 88 | sleep(1); 89 | 90 | } 91 | 92 | } 93 | 94 | shm_mmap_free(addr, 1024); 95 | 96 | } 97 | 98 | 99 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/src/example/test.log: -------------------------------------------------------------------------------- 1 | = Start 2 | @ ./memleak:[0x55beeb03f5f4] + 0x55beeb405690 0xa 3 | @ ./memleak:[0x55beeb03f602] + 0x55beeb4056b0 0x14 4 | @ ./memleak:[0x55beeb03f612] - 0x55beeb405690 5 | @ ./memleak:[0x55beeb03f61c] + 0x55beeb405690 0x14 6 | @ ./memleak:[0x55beeb03f62a] + 0x55beeb4056d0 0x14 7 | @ ./memleak:[0x55beeb03f63a] - 0x55beeb4056b0 8 | @ ./memleak:[0x55beeb03f646] - 0x55beeb4056d0 9 | = End 10 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.5手写内存泄漏检测组件/src/practice/memleak_hw.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.2高性能组件/3.2.5手写内存泄漏检测组件/src/practice/memleak_hw.c -------------------------------------------------------------------------------- /3.2高性能组件/3.2.6手写分布式锁/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /3.2高性能组件/3.2.6手写分布式锁/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(mmpool_HW) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 6 | 7 | set(CMAKE_BUILD_TYPE Debug) 8 | 9 | include_directories(${CMAKE_SOURCE_DIR}/inc) 10 | 11 | add_executable(mmpool_hw src/practice/mmpool_hw.c) 12 | TARGET_LINK_LIBRARIES(mmpool_hw pthread) 13 | 14 | add_executable(mmpool src/example/mmpool.c) 15 | TARGET_LINK_LIBRARIES(mmpool pthread) -------------------------------------------------------------------------------- /3.2高性能组件/3.2.6手写分布式锁/README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计 3 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.1 libeventlibev框架/1.picture/libevent.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.3开源组件/3.3.1 libeventlibev框架/1.picture/libevent.jpg -------------------------------------------------------------------------------- /3.3开源组件/3.3.1 libeventlibev框架/2.doc/libevent_libev实战那些坑.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.3开源组件/3.3.1 libeventlibev框架/2.doc/libevent_libev实战那些坑.pdf -------------------------------------------------------------------------------- /3.3开源组件/3.3.1 libeventlibev框架/README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计——池式组件(线程池、内存池、异步请求池)、高性能组件(原子操作CAS与锁、无锁消息队列、定时器、死锁检测、内存泄漏检测)及开源组件(libevent/libev、异步日志log4cpp、应用层协议设计ProtoBuf/Thrift) 3 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.1 libeventlibev框架/libevent-demo/evmain1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "event2/event.h" 6 | 7 | void socket_read_cb(int fd, short events, void *arg); 8 | 9 | void socket_accept_cb(int fd, short events, void* arg) 10 | { 11 | struct sockaddr_in addr; 12 | socklen_t len = sizeof(addr); 13 | evutil_socket_t clientfd = accept(fd, (struct sockaddr*)&addr, &len); 14 | evutil_make_socket_nonblocking(clientfd); 15 | printf("accept a client %d\n", clientfd); 16 | struct event_base* base = (struct event_base*)arg; 17 | struct event *ev = event_new(NULL, -1, 0, NULL, NULL); 18 | event_assign(ev, base, clientfd, EV_READ | EV_PERSIST, 19 | socket_read_cb, (void*)ev); 20 | event_add(ev, NULL); 21 | } 22 | 23 | void socket_read_cb(int fd, short events, void *arg) 24 | { 25 | char msg[4096]; 26 | struct event *ev = (struct event*)arg; 27 | int len = read(fd, msg, sizeof(msg) - 1); 28 | if( len <= 0 ) 29 | { 30 | printf("client fd:%d disconnect\n", fd); 31 | event_free(ev); 32 | close(fd); 33 | return; 34 | } 35 | 36 | msg[len] = '\0'; 37 | printf("recv the client msg: %s", msg); 38 | 39 | char reply_msg[4096] = "recvieced msg: "; 40 | strcat(reply_msg + strlen(reply_msg), msg); 41 | write(fd, reply_msg, strlen(reply_msg)); 42 | } 43 | 44 | int socket_listen(int port) 45 | { 46 | int errno_save; 47 | 48 | evutil_socket_t listenfd = socket(AF_INET, SOCK_STREAM, 0); 49 | if (listenfd == -1) 50 | return -1; 51 | 52 | evutil_make_listen_socket_reuseable(listenfd); 53 | 54 | struct sockaddr_in sin; 55 | sin.sin_family = AF_INET; 56 | sin.sin_addr.s_addr = 0; 57 | sin.sin_port = htons(port); 58 | 59 | if (bind(listenfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 60 | evutil_closesocket(listenfd); 61 | return -1; 62 | } 63 | 64 | if (listen(listenfd, 5) < 0) { 65 | evutil_closesocket(listenfd); 66 | return -1; 67 | } 68 | 69 | evutil_make_socket_nonblocking(listenfd); 70 | 71 | return listenfd; 72 | } 73 | 74 | int main(int argc, char** argv) 75 | { 76 | int listenfd = socket_listen(8080); 77 | if (listenfd == -1) 78 | { 79 | printf("socket_listen error\n"); 80 | return -1; 81 | } 82 | 83 | struct event_base* base = event_base_new(); 84 | 85 | struct event* ev_listen = event_new(base, listenfd, EV_READ | EV_PERSIST, 86 | socket_accept_cb, base); 87 | /* 88 | event_new 等价于 89 | struct event ev_listen; 90 | event_set(&ev_listen, listenfd, EV_READ | EV_PERSIST, socket_accept_cb, base); 91 | event_base_set(base, &ev_listen); 92 | */ 93 | 94 | event_add(ev_listen, NULL); 95 | 96 | event_base_dispatch(base); 97 | 98 | return 0; 99 | } 100 | 101 | /* 102 | gcc evmain1.c -o ev1 -levent 103 | client: 104 | telnet 127.0.0.1 8080 105 | */ 106 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/1.picture/20211230.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.3开源组件/3.3.2 异步日志方案log4cpp/1.picture/20211230.png -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/2.doc/开源框架log4cpp和日志模块实现-资料.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.3开源组件/3.3.2 异步日志方案log4cpp/2.doc/开源框架log4cpp和日志模块实现-资料.pdf -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计——池式组件(线程池、内存池、异步请求池)、高性能组件(原子操作CAS与锁、无锁消息队列、定时器、死锁检测、内存泄漏检测)及开源组件(libevent/libev、异步日志log4cpp、应用层协议设计ProtoBuf/Thrift) 3 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/AsyncLogging.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef ASYNCLOGGING_H 7 | #define ASYNCLOGGING_H 8 | 9 | #include "BlockingQueue.h" 10 | #include "CountDownLatch.h" 11 | #include "Mutex.h" 12 | #include "Thread.h" 13 | #include "LogStream.h" 14 | 15 | #include 16 | #include 17 | 18 | 19 | 20 | class AsyncLogging : noncopyable 21 | { 22 | public: 23 | 24 | AsyncLogging(const string& basename, 25 | off_t rollSize, 26 | int flushInterval = 3); 27 | 28 | ~AsyncLogging() 29 | { 30 | if (running_) 31 | { 32 | stop(); 33 | } 34 | } 35 | 36 | void append(const char* logline, int len); 37 | 38 | void start() 39 | { 40 | running_ = true; 41 | thread_.start(); 42 | latch_.wait(); 43 | } 44 | 45 | void stop() NO_THREAD_SAFETY_ANALYSIS 46 | { 47 | running_ = false; 48 | cond_.notify(); 49 | thread_.join(); 50 | } 51 | 52 | private: 53 | 54 | void threadFunc(); 55 | 56 | typedef detail::FixedBuffer Buffer; 57 | typedef std::vector> BufferVector; 58 | typedef BufferVector::value_type BufferPtr; 59 | 60 | const int flushInterval_; 61 | std::atomic running_; 62 | const string basename_; 63 | const off_t rollSize_; 64 | Thread thread_; 65 | CountDownLatch latch_; 66 | MutexLock mutex_; 67 | Condition cond_ GUARDED_BY(mutex_); 68 | BufferPtr currentBuffer_ GUARDED_BY(mutex_); 69 | BufferPtr nextBuffer_ GUARDED_BY(mutex_); 70 | BufferVector buffers_ GUARDED_BY(mutex_); 71 | }; 72 | 73 | 74 | #endif // ASYNCLOGGING_H 75 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Atomic.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef ATOMIC_H 7 | #define ATOMIC_H 8 | 9 | #include "noncopyable.h" 10 | 11 | #include 12 | 13 | 14 | namespace detail 15 | { 16 | template 17 | class AtomicIntegerT : noncopyable 18 | { 19 | public: 20 | AtomicIntegerT() 21 | : value_(0) 22 | { 23 | } 24 | 25 | // uncomment if you need copying and assignment 26 | // 27 | // AtomicIntegerT(const AtomicIntegerT& that) 28 | // : value_(that.get()) 29 | // {} 30 | // 31 | // AtomicIntegerT& operator=(const AtomicIntegerT& that) 32 | // { 33 | // getAndSet(that.get()); 34 | // return *this; 35 | // } 36 | 37 | T get() 38 | { 39 | // in gcc >= 4.7: __atomic_load_n(&value_, __ATOMIC_SEQ_CST) 40 | return __sync_val_compare_and_swap(&value_, 0, 0); 41 | } 42 | 43 | T getAndAdd(T x) 44 | { 45 | // in gcc >= 4.7: __atomic_fetch_add(&value_, x, __ATOMIC_SEQ_CST) 46 | return __sync_fetch_and_add(&value_, x); 47 | } 48 | 49 | T addAndGet(T x) 50 | { 51 | return getAndAdd(x) + x; 52 | } 53 | 54 | T incrementAndGet() 55 | { 56 | return addAndGet(1); 57 | } 58 | 59 | T decrementAndGet() 60 | { 61 | return addAndGet(-1); 62 | } 63 | 64 | void add(T x) 65 | { 66 | getAndAdd(x); 67 | } 68 | 69 | void increment() 70 | { 71 | incrementAndGet(); 72 | } 73 | 74 | void decrement() 75 | { 76 | decrementAndGet(); 77 | } 78 | 79 | T getAndSet(T newValue) 80 | { 81 | // in gcc >= 4.7: __atomic_exchange_n(&value_, newValue, __ATOMIC_SEQ_CST) 82 | return __sync_lock_test_and_set(&value_, newValue); 83 | } 84 | 85 | private: 86 | volatile T value_; 87 | }; 88 | } // namespace detail 89 | 90 | typedef detail::AtomicIntegerT AtomicInt32; 91 | typedef detail::AtomicIntegerT AtomicInt64; 92 | 93 | #endif // ATOMIC_H 94 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/BlockingQueue.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef BLOCKINGQUEUE_H 7 | #define BLOCKINGQUEUE_H 8 | 9 | #include "Condition.h" 10 | #include "Mutex.h" 11 | 12 | #include 13 | #include 14 | 15 | 16 | template 17 | class BlockingQueue : noncopyable 18 | { 19 | public: 20 | BlockingQueue() 21 | : mutex_(), 22 | notEmpty_(mutex_), 23 | queue_() 24 | { 25 | } 26 | 27 | void put(const T& x) 28 | { 29 | MutexLockGuard lock(mutex_); 30 | queue_.push_back(x); 31 | notEmpty_.notify(); // wait morphing saves us 32 | // http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/ 33 | } 34 | 35 | void put(T&& x) 36 | { 37 | MutexLockGuard lock(mutex_); 38 | queue_.push_back(std::move(x)); 39 | notEmpty_.notify(); 40 | } 41 | 42 | T take() 43 | { 44 | MutexLockGuard lock(mutex_); 45 | // always use a while-loop, due to spurious wakeup 46 | while (queue_.empty()) 47 | { 48 | notEmpty_.wait(); 49 | } 50 | assert(!queue_.empty()); 51 | T front(std::move(queue_.front())); 52 | queue_.pop_front(); 53 | return front; 54 | } 55 | 56 | size_t size() const 57 | { 58 | MutexLockGuard lock(mutex_); 59 | return queue_.size(); 60 | } 61 | 62 | private: 63 | mutable MutexLock mutex_; 64 | Condition notEmpty_ GUARDED_BY(mutex_); 65 | std::deque queue_ GUARDED_BY(mutex_); 66 | }; 67 | 68 | 69 | #endif // BLOCKINGQUEUE_H 70 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.7) 2 | project (log_test) 3 | 4 | ### 5 | # compilation options 6 | ### 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -W -Wall -Wextra -g") 8 | 9 | 10 | ### 11 | # variables 12 | ### 13 | set(PROJECT_ROOT_DIR ${PROJECT_SOURCE_DIR}) 14 | 15 | 16 | ### 17 | # includes 18 | ### 19 | include_directories(. 20 | ${INCLUDES_DIRECTORY}) 21 | aux_source_directory(. LOG_TEST_SOURCES_DIRECTORY) 22 | 23 | 24 | #set(EXECUTABLE_OUTPUT_PATH ${PROJECT_ROOT_DIR}/bin) 25 | 26 | 27 | ### 28 | # executable 29 | ### 30 | add_executable(main_log_test ${LOG_TEST_SOURCES_DIRECTORY}) 31 | 32 | 33 | ### 34 | # link librarys 35 | ### 36 | target_link_libraries(main_log_test pthread) -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Condition.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "Condition.h" 7 | 8 | #include 9 | 10 | // returns true if time out, false otherwise. 11 | bool Condition::waitForSeconds(double seconds) 12 | { 13 | struct timespec abstime; 14 | // FIXME: use CLOCK_MONOTONIC or CLOCK_MONOTONIC_RAW to prevent time rewind. 15 | clock_gettime(CLOCK_REALTIME, &abstime); 16 | 17 | const int64_t kNanoSecondsPerSecond = 1000000000; 18 | int64_t nanoseconds = static_cast(seconds * kNanoSecondsPerSecond); 19 | 20 | abstime.tv_sec += static_cast((abstime.tv_nsec + nanoseconds) / kNanoSecondsPerSecond); 21 | abstime.tv_nsec = static_cast((abstime.tv_nsec + nanoseconds) % kNanoSecondsPerSecond); 22 | 23 | MutexLock::UnassignGuard ug(mutex_); 24 | return ETIMEDOUT == pthread_cond_timedwait(&pcond_, mutex_.getPthreadMutex(), &abstime); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Condition.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONDITION_HH 2 | #define _CONDITION_HH 3 | 4 | #include "Mutex.h" 5 | 6 | #include 7 | 8 | class Condition : noncopyable 9 | { 10 | public: 11 | explicit Condition(MutexLock& mutex) 12 | : mutex_(mutex) 13 | { 14 | MCHECK(pthread_cond_init(&pcond_, NULL)); 15 | } 16 | 17 | ~Condition() 18 | { 19 | MCHECK(pthread_cond_destroy(&pcond_)); 20 | } 21 | 22 | void wait() 23 | { 24 | MutexLock::UnassignGuard ug(mutex_); 25 | MCHECK(pthread_cond_wait(&pcond_, mutex_.getPthreadMutex())); 26 | } 27 | 28 | // returns true if time out, false otherwise. 29 | bool waitForSeconds(double seconds); 30 | 31 | void notify() 32 | { 33 | MCHECK(pthread_cond_signal(&pcond_)); 34 | } 35 | 36 | void notifyAll() 37 | { 38 | MCHECK(pthread_cond_broadcast(&pcond_)); 39 | } 40 | 41 | private: 42 | MutexLock& mutex_; 43 | pthread_cond_t pcond_; 44 | }; 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/CountDownLatch.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "CountDownLatch.h" 7 | 8 | 9 | CountDownLatch::CountDownLatch(int count) 10 | : mutex_(), 11 | condition_(mutex_), 12 | count_(count) 13 | { 14 | } 15 | 16 | void CountDownLatch::wait() 17 | { 18 | MutexLockGuard lock(mutex_); 19 | while (count_ > 0) 20 | { 21 | condition_.wait(); 22 | } 23 | } 24 | 25 | void CountDownLatch::countDown() 26 | { 27 | MutexLockGuard lock(mutex_); 28 | --count_; 29 | if (count_ == 0) 30 | { 31 | condition_.notifyAll(); 32 | } 33 | } 34 | 35 | int CountDownLatch::getCount() const 36 | { 37 | MutexLockGuard lock(mutex_); 38 | return count_; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/CountDownLatch.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef COUNTDOWNLATCH_H 7 | #define COUNTDOWNLATCH_H 8 | 9 | #include "Condition.h" 10 | #include "Mutex.h" 11 | 12 | class CountDownLatch : noncopyable 13 | { 14 | public: 15 | 16 | explicit CountDownLatch(int count); 17 | 18 | void wait(); 19 | 20 | void countDown(); 21 | 22 | int getCount() const; 23 | 24 | private: 25 | mutable MutexLock mutex_; 26 | Condition condition_ GUARDED_BY(mutex_); 27 | int count_ GUARDED_BY(mutex_); 28 | }; 29 | #endif // COUNTDOWNLATCH_H 30 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/CurrentThread.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "CurrentThread.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace CurrentThread 13 | { 14 | __thread int t_cachedTid = 0; 15 | __thread char t_tidString[32]; 16 | __thread int t_tidStringLength = 6; 17 | __thread const char* t_threadName = "unknown"; 18 | static_assert(std::is_same::value, "pid_t should be int"); 19 | 20 | string stackTrace(bool demangle) 21 | { 22 | string stack; 23 | const int max_frames = 200; 24 | void* frame[max_frames]; 25 | int nptrs = ::backtrace(frame, max_frames); 26 | char** strings = ::backtrace_symbols(frame, nptrs); 27 | if (strings) 28 | { 29 | size_t len = 256; 30 | char* demangled = demangle ? static_cast(::malloc(len)) : nullptr; 31 | for (int i = 1; i < nptrs; ++i) // skipping the 0-th, which is this function 32 | { 33 | if (demangle) 34 | { 35 | // https://panthema.net/2008/0901-stacktrace-demangled/ 36 | // bin/exception_test(_ZN3Bar4testEv+0x79) [0x401909] 37 | char* left_par = nullptr; 38 | char* plus = nullptr; 39 | for (char* p = strings[i]; *p; ++p) 40 | { 41 | if (*p == '(') 42 | left_par = p; 43 | else if (*p == '+') 44 | plus = p; 45 | } 46 | 47 | if (left_par && plus) 48 | { 49 | *plus = '\0'; 50 | int status = 0; 51 | char* ret = abi::__cxa_demangle(left_par+1, demangled, &len, &status); 52 | *plus = '+'; 53 | if (status == 0) 54 | { 55 | demangled = ret; // ret could be realloc() 56 | stack.append(strings[i], left_par+1); 57 | stack.append(demangled); 58 | stack.append(plus); 59 | stack.push_back('\n'); 60 | continue; 61 | } 62 | } 63 | } 64 | // Fallback to mangled names 65 | stack.append(strings[i]); 66 | stack.push_back('\n'); 67 | } 68 | free(demangled); 69 | free(strings); 70 | } 71 | return stack; 72 | } 73 | 74 | } // namespace CurrentThread 75 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/CurrentThread.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef CURRENTTHREAD_H 7 | #define CURRENTTHREAD_H 8 | 9 | #include "Types.h" 10 | 11 | 12 | namespace CurrentThread 13 | { 14 | // internal 15 | extern __thread int t_cachedTid; 16 | extern __thread char t_tidString[32]; 17 | extern __thread int t_tidStringLength; 18 | extern __thread const char* t_threadName; 19 | void cacheTid(); 20 | 21 | inline int tid() 22 | { 23 | if (__builtin_expect(t_cachedTid == 0, 0)) 24 | { 25 | cacheTid(); 26 | } 27 | return t_cachedTid; 28 | } 29 | 30 | inline const char* tidString() // for logging 31 | { 32 | return t_tidString; 33 | } 34 | 35 | inline int tidStringLength() // for logging 36 | { 37 | return t_tidStringLength; 38 | } 39 | 40 | inline const char* name() 41 | { 42 | return t_threadName; 43 | } 44 | 45 | bool isMainThread(); 46 | 47 | void sleepUsec(int64_t usec); // for testing 48 | 49 | string stackTrace(bool demangle); 50 | } // namespace CurrentThread 51 | 52 | #endif // CURRENTTHREAD_H 53 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Date.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "Date.h" 7 | #include // snprintf 8 | #include // struct tm 9 | 10 | 11 | namespace detail 12 | { 13 | 14 | char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1]; 15 | 16 | // algorithm and explanation see: 17 | // http://www.faqs.org/faqs/calendars/faq/part2/ 18 | // http://blog.csdn.net/Solstice 19 | 20 | int getJulianDayNumber(int year, int month, int day) 21 | { 22 | (void) require_32_bit_integer_at_least; // no warning please 23 | int a = (14 - month) / 12; 24 | int y = year + 4800 - a; 25 | int m = month + 12 * a - 3; 26 | return day + (153*m + 2) / 5 + y*365 + y/4 - y/100 + y/400 - 32045; 27 | } 28 | 29 | struct Date::YearMonthDay getYearMonthDay(int julianDayNumber) 30 | { 31 | int a = julianDayNumber + 32044; 32 | int b = (4 * a + 3) / 146097; 33 | int c = a - ((b * 146097) / 4); 34 | int d = (4 * c + 3) / 1461; 35 | int e = c - ((1461 * d) / 4); 36 | int m = (5 * e + 2) / 153; 37 | Date::YearMonthDay ymd; 38 | ymd.day = e - ((153 * m + 2) / 5) + 1; 39 | ymd.month = m + 3 - 12 * (m / 10); 40 | ymd.year = b * 100 + d - 4800 + (m / 10); 41 | return ymd; 42 | } 43 | } // namespace detail 44 | const int Date::kJulianDayOf1970_01_01 = detail::getJulianDayNumber(1970, 1, 1); 45 | 46 | 47 | 48 | using namespace detail; 49 | 50 | Date::Date(int y, int m, int d) 51 | : julianDayNumber_(getJulianDayNumber(y, m, d)) 52 | { 53 | } 54 | 55 | Date::Date(const struct tm& t) 56 | : julianDayNumber_(getJulianDayNumber( 57 | t.tm_year+1900, 58 | t.tm_mon+1, 59 | t.tm_mday)) 60 | { 61 | } 62 | 63 | string Date::toIsoString() const 64 | { 65 | char buf[32]; 66 | YearMonthDay ymd(yearMonthDay()); 67 | snprintf(buf, sizeof buf, "%4d-%02d-%02d", ymd.year, ymd.month, ymd.day); 68 | return buf; 69 | } 70 | 71 | Date::YearMonthDay Date::yearMonthDay() const 72 | { 73 | return getYearMonthDay(julianDayNumber_); 74 | } 75 | 76 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Date.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef DATE_H 7 | #define DATE_H 8 | 9 | #include "copyable.h" 10 | #include "Types.h" 11 | 12 | struct tm; 13 | 14 | /// 15 | /// Date in Gregorian calendar. 16 | /// 17 | /// This class is immutable. 18 | /// It's recommended to pass it by value, since it's passed in register on x64. 19 | /// 20 | class Date : public copyable 21 | // public boost::less_than_comparable, 22 | // public boost::equality_comparable 23 | { 24 | public: 25 | 26 | struct YearMonthDay 27 | { 28 | int year; // [1900..2500] 29 | int month; // [1..12] 30 | int day; // [1..31] 31 | }; 32 | 33 | static const int kDaysPerWeek = 7; 34 | static const int kJulianDayOf1970_01_01; 35 | 36 | /// 37 | /// Constucts an invalid Date. 38 | /// 39 | Date() 40 | : julianDayNumber_(0) 41 | {} 42 | 43 | /// 44 | /// Constucts a yyyy-mm-dd Date. 45 | /// 46 | /// 1 <= month <= 12 47 | Date(int year, int month, int day); 48 | 49 | /// 50 | /// Constucts a Date from Julian Day Number. 51 | /// 52 | explicit Date(int julianDayNum) 53 | : julianDayNumber_(julianDayNum) 54 | {} 55 | 56 | /// 57 | /// Constucts a Date from struct tm 58 | /// 59 | explicit Date(const struct tm&); 60 | 61 | // default copy/assignment/dtor are Okay 62 | 63 | void swap(Date& that) 64 | { 65 | std::swap(julianDayNumber_, that.julianDayNumber_); 66 | } 67 | 68 | bool valid() const { return julianDayNumber_ > 0; } 69 | 70 | /// 71 | /// Converts to yyyy-mm-dd format. 72 | /// 73 | string toIsoString() const; 74 | 75 | struct YearMonthDay yearMonthDay() const; 76 | 77 | int year() const 78 | { 79 | return yearMonthDay().year; 80 | } 81 | 82 | int month() const 83 | { 84 | return yearMonthDay().month; 85 | } 86 | 87 | int day() const 88 | { 89 | return yearMonthDay().day; 90 | } 91 | 92 | // [0, 1, ..., 6] => [Sunday, Monday, ..., Saturday ] 93 | int weekDay() const 94 | { 95 | return (julianDayNumber_+1) % kDaysPerWeek; 96 | } 97 | 98 | int julianDayNumber() const { return julianDayNumber_; } 99 | 100 | private: 101 | int julianDayNumber_; 102 | }; 103 | 104 | inline bool operator<(Date x, Date y) 105 | { 106 | return x.julianDayNumber() < y.julianDayNumber(); 107 | } 108 | 109 | inline bool operator==(Date x, Date y) 110 | { 111 | return x.julianDayNumber() == y.julianDayNumber(); 112 | } 113 | 114 | 115 | #endif // DATE_H 116 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Exception.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "Exception.h" 7 | #include "CurrentThread.h" 8 | 9 | 10 | 11 | Exception::Exception(string msg) 12 | : message_(std::move(msg)), 13 | stack_(CurrentThread::stackTrace(/*demangle=*/false)) 14 | { 15 | } 16 | 17 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Exception.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef EXCEPTION_H 7 | #define EXCEPTION_H 8 | 9 | #include "Types.h" 10 | #include 11 | 12 | 13 | class Exception : public std::exception 14 | { 15 | public: 16 | Exception(string what); 17 | ~Exception() noexcept override = default; 18 | 19 | // default copy-ctor and operator= are okay. 20 | 21 | const char* what() const noexcept override 22 | { 23 | return message_.c_str(); 24 | } 25 | 26 | const char* stackTrace() const noexcept 27 | { 28 | return stack_.c_str(); 29 | } 30 | 31 | private: 32 | string message_; 33 | string stack_; 34 | }; 35 | 36 | #endif // EXCEPTION_H 37 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/FileUtil.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | // 6 | // This is a public header file, it must only include public header files. 7 | 8 | #ifndef FILEUTIL_H 9 | #define FILEUTIL_H 10 | 11 | #include "noncopyable.h" 12 | #include "StringPiece.h" 13 | #include // for off_t 14 | 15 | 16 | namespace FileUtil 17 | { 18 | 19 | // read small file < 64KB 20 | class ReadSmallFile : noncopyable 21 | { 22 | public: 23 | ReadSmallFile(StringArg filename); 24 | ~ReadSmallFile(); 25 | 26 | // return errno 27 | template 28 | int readToString(int maxSize, 29 | String* content, 30 | int64_t* fileSize, 31 | int64_t* modifyTime, 32 | int64_t* createTime); 33 | 34 | /// Read at maxium kBufferSize into buf_ 35 | // return errno 36 | int readToBuffer(int* size); 37 | 38 | const char* buffer() const { return buf_; } 39 | 40 | static const int kBufferSize = 64*1024; 41 | 42 | private: 43 | int fd_; 44 | int err_; 45 | char buf_[kBufferSize]; 46 | }; 47 | 48 | // read the file content, returns errno if error happens. 49 | template 50 | int readFile(StringArg filename, 51 | int maxSize, 52 | String* content, 53 | int64_t* fileSize = NULL, 54 | int64_t* modifyTime = NULL, 55 | int64_t* createTime = NULL) 56 | { 57 | ReadSmallFile file(filename); 58 | return file.readToString(maxSize, content, fileSize, modifyTime, createTime); 59 | } 60 | 61 | // not thread safe 62 | class AppendFile : noncopyable 63 | { 64 | public: 65 | explicit AppendFile(StringArg filename); 66 | 67 | ~AppendFile(); 68 | 69 | void append(const char* logline, size_t len); 70 | 71 | void flush(); 72 | 73 | off_t writtenBytes() const { return writtenBytes_; } 74 | 75 | private: 76 | 77 | size_t write(const char* logline, size_t len); 78 | 79 | FILE* fp_; 80 | char buffer_[64*1024]; 81 | off_t writtenBytes_; 82 | }; 83 | 84 | } // namespace FileUtil 85 | 86 | 87 | #endif // FILEUTIL_H 88 | 89 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/LogFile.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "LogFile.h" 7 | 8 | #include "FileUtil.h" 9 | #include "ProcessInfo.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | 17 | LogFile::LogFile(const string& basename, 18 | off_t rollSize, 19 | bool threadSafe, 20 | int flushInterval, 21 | int checkEveryN) 22 | : basename_(basename), 23 | rollSize_(rollSize), 24 | flushInterval_(flushInterval), 25 | checkEveryN_(checkEveryN), 26 | count_(0), 27 | mutex_(threadSafe ? new MutexLock : NULL), 28 | startOfPeriod_(0), 29 | lastRoll_(0), 30 | lastFlush_(0) 31 | { 32 | assert(basename.find('/') == string::npos); 33 | rollFile(); 34 | } 35 | 36 | LogFile::~LogFile() = default; 37 | 38 | void LogFile::append(const char* logline, int len) 39 | { 40 | if (mutex_) 41 | { 42 | MutexLockGuard lock(*mutex_); 43 | append_unlocked(logline, len); 44 | } 45 | else 46 | { 47 | append_unlocked(logline, len); 48 | } 49 | } 50 | 51 | void LogFile::flush() 52 | { 53 | if (mutex_) 54 | { 55 | MutexLockGuard lock(*mutex_); 56 | file_->flush(); 57 | } 58 | else 59 | { 60 | file_->flush(); 61 | } 62 | } 63 | 64 | void LogFile::append_unlocked(const char* logline, int len) 65 | { 66 | file_->append(logline, len); 67 | 68 | if (file_->writtenBytes() > rollSize_) 69 | { 70 | rollFile(); 71 | } 72 | else 73 | { 74 | ++count_; 75 | if (count_ >= checkEveryN_) 76 | { 77 | count_ = 0; 78 | time_t now = ::time(NULL); 79 | time_t thisPeriod_ = now / kRollPerSeconds_ * kRollPerSeconds_; 80 | if (thisPeriod_ != startOfPeriod_) 81 | { 82 | rollFile(); 83 | } 84 | else if (now - lastFlush_ > flushInterval_) 85 | { 86 | lastFlush_ = now; 87 | file_->flush(); 88 | } 89 | } 90 | } 91 | } 92 | 93 | bool LogFile::rollFile() 94 | { 95 | time_t now = 0; 96 | string filename = getLogFileName(basename_, &now); 97 | time_t start = now / kRollPerSeconds_ * kRollPerSeconds_; 98 | 99 | if (now > lastRoll_) 100 | { 101 | lastRoll_ = now; 102 | lastFlush_ = now; 103 | startOfPeriod_ = start; 104 | file_.reset(new FileUtil::AppendFile(filename)); 105 | return true; 106 | } 107 | return false; 108 | } 109 | 110 | string LogFile::getLogFileName(const string& basename, time_t* now) 111 | { 112 | string filename; 113 | filename.reserve(basename.size() + 64); 114 | filename = basename; 115 | 116 | char timebuf[32]; 117 | struct tm tm; 118 | *now = time(NULL); 119 | gmtime_r(now, &tm); // FIXME: localtime_r ? 120 | strftime(timebuf, sizeof timebuf, ".%Y%m%d-%H%M%S.", &tm); 121 | filename += timebuf; 122 | 123 | filename += ProcessInfo::hostname(); 124 | 125 | char pidbuf[32]; 126 | snprintf(pidbuf, sizeof pidbuf, ".%d", ProcessInfo::pid()); 127 | filename += pidbuf; 128 | 129 | filename += ".log"; 130 | 131 | return filename; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/LogFile.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef LOGFILE_H 7 | #define LOGFILE_H 8 | 9 | #include "Mutex.h" 10 | #include "Types.h" 11 | 12 | #include 13 | 14 | 15 | 16 | namespace FileUtil 17 | { 18 | class AppendFile; 19 | } 20 | 21 | class LogFile : noncopyable 22 | { 23 | public: 24 | LogFile(const string& basename, 25 | off_t rollSize, 26 | bool threadSafe = true, 27 | int flushInterval = 3, 28 | int checkEveryN = 1024); 29 | ~LogFile(); 30 | 31 | void append(const char* logline, int len); 32 | void flush(); 33 | bool rollFile(); 34 | 35 | private: 36 | void append_unlocked(const char* logline, int len); 37 | 38 | static string getLogFileName(const string& basename, time_t* now); 39 | 40 | const string basename_; 41 | const off_t rollSize_; 42 | const int flushInterval_; 43 | const int checkEveryN_; 44 | 45 | int count_; 46 | 47 | std::unique_ptr mutex_; 48 | time_t startOfPeriod_; 49 | time_t lastRoll_; 50 | time_t lastFlush_; 51 | std::unique_ptr file_; 52 | 53 | const static int kRollPerSeconds_ = 60*60*24; 54 | }; 55 | 56 | 57 | #endif // LOGFILE_H 58 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/ProcessInfo.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | // 6 | // This is a public header file, it must only include public header files. 7 | 8 | #ifndef PROCESSINFO_H 9 | #define PROCESSINFO_H 10 | 11 | #include "StringPiece.h" 12 | #include "Types.h" 13 | #include "Timestamp.h" 14 | #include 15 | #include 16 | 17 | namespace ProcessInfo 18 | { 19 | pid_t pid(); 20 | string pidString(); 21 | uid_t uid(); 22 | string username(); 23 | uid_t euid(); 24 | Timestamp startTime(); 25 | int clockTicksPerSecond(); 26 | int pageSize(); 27 | bool isDebugBuild(); // constexpr 28 | 29 | string hostname(); 30 | string procname(); 31 | StringPiece procname(const string& stat); 32 | 33 | /// read /proc/self/status 34 | string procStatus(); 35 | 36 | /// read /proc/self/stat 37 | string procStat(); 38 | 39 | /// read /proc/self/task/tid/stat 40 | string threadStat(); 41 | 42 | /// readlink /proc/self/exe 43 | string exePath(); 44 | 45 | int openedFiles(); 46 | int maxOpenFiles(); 47 | 48 | struct CpuTime 49 | { 50 | double userSeconds; 51 | double systemSeconds; 52 | 53 | CpuTime() : userSeconds(0.0), systemSeconds(0.0) { } 54 | 55 | double total() const { return userSeconds + systemSeconds; } 56 | }; 57 | CpuTime cpuTime(); 58 | 59 | int numThreads(); 60 | std::vector threads(); 61 | } // namespace ProcessInfo 62 | 63 | 64 | #endif // PROCESSINFO_H 65 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/README.md: -------------------------------------------------------------------------------- 1 | 编译说明 2 | mkdir build 3 | cd build 4 | cmake .. 5 | make 6 | 得到执行文件 7 | main_log_test -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Thread.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef THREAD_H 7 | #define THREAD_H 8 | 9 | #include "Atomic.h" 10 | #include "CountDownLatch.h" 11 | #include "Types.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | 19 | class Thread : noncopyable 20 | { 21 | public: 22 | typedef std::function ThreadFunc; 23 | 24 | explicit Thread(ThreadFunc, const string& name = string()); 25 | // FIXME: make it movable in C++11 26 | ~Thread(); 27 | 28 | void start(); 29 | int join(); // return pthread_join() 30 | 31 | bool started() const { return started_; } 32 | // pthread_t pthreadId() const { return pthreadId_; } 33 | pid_t tid() const { return tid_; } 34 | const string& name() const { return name_; } 35 | 36 | static int numCreated() { return numCreated_.get(); } 37 | 38 | private: 39 | void setDefaultName(); 40 | 41 | bool started_; 42 | bool joined_; 43 | pthread_t pthreadId_; 44 | pid_t tid_; 45 | ThreadFunc func_; 46 | string name_; 47 | CountDownLatch latch_; 48 | 49 | static AtomicInt32 numCreated_; 50 | }; 51 | 52 | 53 | #endif // THREAD_H 54 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/TimeZone.h: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #ifndef TIMEZONE_H 7 | #define TIMEZONE_H 8 | 9 | #include "copyable.h" 10 | #include 11 | #include 12 | 13 | 14 | 15 | // TimeZone for 1970~2030 16 | class TimeZone : public copyable 17 | { 18 | public: 19 | explicit TimeZone(const char* zonefile); 20 | TimeZone(int eastOfUtc, const char* tzname); // a fixed timezone 21 | TimeZone() = default; // an invalid timezone 22 | 23 | // default copy ctor/assignment/dtor are Okay. 24 | 25 | bool valid() const 26 | { 27 | // 'explicit operator bool() const' in C++11 28 | return static_cast(data_); 29 | } 30 | 31 | struct tm toLocalTime(time_t secondsSinceEpoch) const; 32 | time_t fromLocalTime(const struct tm&) const; 33 | 34 | // gmtime(3) 35 | static struct tm toUtcTime(time_t secondsSinceEpoch, bool yday = false); 36 | // timegm(3) 37 | static time_t fromUtcTime(const struct tm&); 38 | // year in [1900..2500], month in [1..12], day in [1..31] 39 | static time_t fromUtcTime(int year, int month, int day, 40 | int hour, int minute, int seconds); 41 | 42 | struct Data; 43 | 44 | private: 45 | 46 | std::shared_ptr data_; 47 | }; 48 | 49 | 50 | 51 | #endif // TIMEZONE_H 52 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/Timestamp.cc: -------------------------------------------------------------------------------- 1 | // Use of this source code is governed by a BSD-style license 2 | // that can be found in the License file. 3 | // 4 | // Author: Shuo Chen (chenshuo at chenshuo dot com) 5 | 6 | #include "Timestamp.h" 7 | 8 | #include 9 | #include 10 | 11 | #ifndef __STDC_FORMAT_MACROS 12 | #define __STDC_FORMAT_MACROS 13 | #endif 14 | 15 | #include 16 | 17 | 18 | 19 | static_assert(sizeof(Timestamp) == sizeof(int64_t), 20 | "Timestamp should be same size as int64_t"); 21 | 22 | string Timestamp::toString() const 23 | { 24 | char buf[32] = {0}; 25 | int64_t seconds = microSecondsSinceEpoch_ / kMicroSecondsPerSecond; 26 | int64_t microseconds = microSecondsSinceEpoch_ % kMicroSecondsPerSecond; 27 | snprintf(buf, sizeof(buf), "%" PRId64 ".%06" PRId64 "", seconds, microseconds); 28 | return buf; 29 | } 30 | 31 | string Timestamp::toFormattedString(bool showMicroseconds) const 32 | { 33 | char buf[64] = {0}; 34 | time_t seconds = static_cast(microSecondsSinceEpoch_ / kMicroSecondsPerSecond); 35 | struct tm tm_time; 36 | gmtime_r(&seconds, &tm_time); 37 | 38 | if (showMicroseconds) 39 | { 40 | int microseconds = static_cast(microSecondsSinceEpoch_ % kMicroSecondsPerSecond); 41 | snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d", 42 | tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, 43 | tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, 44 | microseconds); 45 | } 46 | else 47 | { 48 | snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d", 49 | tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, 50 | tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); 51 | } 52 | return buf; 53 | } 54 | 55 | Timestamp Timestamp::now() 56 | { 57 | struct timeval tv; 58 | gettimeofday(&tv, NULL); 59 | int64_t seconds = tv.tv_sec; 60 | return Timestamp(seconds * kMicroSecondsPerSecond + tv.tv_usec); 61 | } 62 | 63 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/copyable.h: -------------------------------------------------------------------------------- 1 | #ifndef COPYABLE_H 2 | #define COPYABLE_H 3 | 4 | /// A tag class emphasises the objects are copyable. 5 | /// The empty base class optimization applies. 6 | /// Any derived class of copyable should be a value type. 7 | class copyable 8 | { 9 | protected: 10 | copyable() = default; 11 | ~copyable() = default; 12 | }; 13 | 14 | 15 | #endif // COPYABLE_H 16 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/main_log_test.cc: -------------------------------------------------------------------------------- 1 | #include "AsyncLogging.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Logging.h" 9 | #define LOG_NUM 5000000 // 总共的写入日志行数 10 | 11 | using namespace std; 12 | off_t kRollSize = 1 * 1000 * 1000; // 只设置1M 13 | 14 | static AsyncLogging *g_asyncLog = NULL; 15 | 16 | static void asyncOutput(const char *msg, int len) 17 | { 18 | g_asyncLog->append(msg, len); 19 | } 20 | 21 | static uint64_t get_tick_count() 22 | { 23 | struct timeval tval; 24 | uint64_t ret_tick; 25 | 26 | gettimeofday(&tval, NULL); 27 | 28 | ret_tick = tval.tv_sec * 1000L + tval.tv_usec / 1000L; 29 | return ret_tick; 30 | } 31 | 32 | 33 | void testLogPerformance(int argc, char *argv[]) 34 | { 35 | printf("pid = %d\n", getpid()); 36 | 37 | char name[256] = {'\0'}; 38 | strncpy(name, argv[0], sizeof name - 1); 39 | // 回滚大小kRollSize(1M), 最大1秒刷一次盘(flush) 40 | AsyncLogging log(::basename(name), kRollSize, 1); 41 | Logger::setOutput(asyncOutput); // 不是说只有一个实例 42 | 43 | g_asyncLog = &log; 44 | log.start(); // 启动日志写入线程 45 | uint64_t begin_time = get_tick_count(); 46 | std::cout << "name:" <<::basename(name) << ", begin_time: " << begin_time << std::endl; 47 | for (int i = 0; i < LOG_NUM; i++) 48 | { 49 | LOG_INFO << "NO." << i << " Root Error Message!"; // 47个字节 50 | } 51 | 52 | // while (1) 53 | // { 54 | // /* code */ 55 | // } 56 | 57 | log.stop(); 58 | uint64_t end_time = get_tick_count(); 59 | std::cout << "end_time: " << end_time << std::endl; 60 | int64_t ops = LOG_NUM; 61 | ops = ops * 1000 / (end_time - begin_time); 62 | std::cout << "need the time1: " << end_time << " " << begin_time << ", " << end_time - begin_time << "毫秒" 63 | << ", ops = " << ops << "ops/s\n"; 64 | } 65 | 66 | void testCoredump() 67 | { 68 | AsyncLogging log("coredump", 200*1000*1000); 69 | log.start(); //开启日志线程 70 | g_asyncLog = &log; 71 | int msgcnt = 0; 72 | Logger::setOutput(asyncOutput);//设置日志输出函数 73 | 74 | 75 | for(int i=0;i<1000000;i++) {//写入100万条日志消息 76 | LOG_INFO << "0voice 0123456789" << " abcdefghijklmnopqrstuvwxyz " 77 | << ++msgcnt; 78 | if(i == 500000) { 79 | int *ptr = NULL; 80 | *ptr = 0x1234; // 人为制造异常 81 | } 82 | } 83 | 84 | } 85 | 86 | 87 | int main(int argc, char *argv[]) 88 | { 89 | // 这里每次二选1去进行测试 90 | testLogPerformance(argc, argv); 91 | // testCoredump(); 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/noncopyable.h: -------------------------------------------------------------------------------- 1 | #ifndef NONCOPYABLE_H 2 | #define NONCOPYABLE_H 3 | 4 | 5 | class noncopyable 6 | { 7 | public: 8 | noncopyable(const noncopyable&) = delete; 9 | void operator=(const noncopyable&) = delete; 10 | 11 | protected: 12 | noncopyable() = default; 13 | ~noncopyable() = default; 14 | }; 15 | 16 | 17 | #endif // NONCOPYABLE_H 18 | -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/ptr_vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _PTR_VECTOR_HH 2 | #define _PTR_VECTOR_HH 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace myself{ 9 | 10 | #define ASSERT(If, Msg) \ 11 | if(!(If)) \ 12 | {\ 13 | fprintf(stderr, "Error/(%s, %d): %s, abort.\n", __FILE__, __LINE__, Msg); abort();\ 14 | } 15 | 16 | template 17 | class ptr_vector{ 18 | public: 19 | typedef unsigned int size_type; 20 | typedef std::vector vector; 21 | typedef T* value_type; 22 | typedef value_type& reference; 23 | 24 | explicit ptr_vector(){ 25 | } 26 | 27 | ~ptr_vector(){ 28 | clear(); 29 | } 30 | 31 | void clear(){ 32 | if(!m_vector.empty()) 33 | { 34 | //typename vector::iterator it; 35 | for(auto it = m_vector.begin(); it != m_vector.end(); ++it) 36 | { 37 | delete *it;//释放指针指向的内存. 38 | } 39 | } 40 | 41 | m_vector.clear();//释放指针本身. 42 | } 43 | 44 | void push_back(T* const &v){ 45 | ASSERT(v , "NULL point at ptr_vector push_back()"); 46 | std::unique_ptr tmp(v); 47 | m_vector.push_back(v); //使用 unique_ptr 保证push_back失败时,v也能正常释放. 48 | tmp.release(); 49 | } 50 | 51 | std::unique_ptr pop_back(){ 52 | ASSERT( !m_vector.empty(), "'pop_back()' on empty container"); 53 | std::unique_ptr tmp(m_vector.back()); 54 | m_vector.pop_back(); 55 | return std::move(tmp); 56 | } 57 | 58 | reference operator[](size_type n){ 59 | ASSERT(n < size(), "operator[] n out of the border") 60 | return m_vector[n]; 61 | } 62 | 63 | bool empty(){ 64 | return m_vector.empty(); 65 | } 66 | 67 | size_type size(){ 68 | return m_vector.size(); 69 | } 70 | 71 | void reserve(size_type n){ 72 | m_vector.reserve(n); 73 | } 74 | 75 | void resize(size_type s){ 76 | size_type size = this->size(); 77 | if(s < size) 78 | { 79 | for(auto it = m_vector.begin() + s; it != m_vector.end(); ++it) 80 | { 81 | delete *it;//释放指针指向的内存. 82 | } 83 | m_vector.resize(s); 84 | } 85 | else if(s > size) 86 | { 87 | for(; size != s; ++size) 88 | { 89 | push_back(new T); 90 | } 91 | } 92 | ASSERT(s == this->size(), "'resize' error size asymmetry"); 93 | } 94 | 95 | void swap(ptr_vector& v){ 96 | m_vector.swap(v.base()); 97 | } 98 | 99 | private: 100 | ptr_vector& operator=(const ptr_vector&); 101 | ptr_vector(ptr_vector&); 102 | 103 | vector& base(){ 104 | return m_vector; 105 | } 106 | 107 | vector m_vector; 108 | }; 109 | 110 | } 111 | 112 | #endif -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/muduo_log/scoped_ptr.h: -------------------------------------------------------------------------------- 1 | #ifndef _SCOPE_PTR_HH 2 | #define _SCOPE_PTR_HH 3 | // scoped_ptr mimics a built-in pointer except that it guarantees deletion 4 | // of the object pointed to, either on destruction of the scoped_ptr or via 5 | // an explicit reset(). scoped_ptr is a simple solution for simple needs; 6 | // use shared_ptr or std::auto_ptr if your needs are more complex. 7 | 8 | /* 9 | scoped_ptr 是局部智能指针 不允许转让所有权。 10 | */ 11 | template 12 | class scoped_ptr 13 | { 14 | public: 15 | scoped_ptr(T *p = 0) :m_ptr(p) { 16 | } 17 | 18 | ~scoped_ptr(){ 19 | delete m_ptr; 20 | } 21 | 22 | T&operator*() const { 23 | return *m_ptr; 24 | } 25 | 26 | T*operator->() const { 27 | return m_ptr; 28 | } 29 | 30 | void reset(T *p)//拥有权不允许转让 但是可以让智能指针指向另一个空间 31 | { 32 | if (p != m_ptr && m_ptr != 0) 33 | delete m_ptr; 34 | m_ptr = p; 35 | } 36 | 37 | T* get() const { 38 | return m_ptr; 39 | } 40 | 41 | operator bool() const { return get() != NULL; } 42 | 43 | private://将拷贝构造和赋值 以及判等判不等 都设置为私有方法 44 | //对象不再能调用,即不能拷贝构造和赋值 也就达到了不让转移拥有权的目的 45 | scoped_ptr(const scoped_ptr &y); 46 | const scoped_ptr operator=(const scoped_ptr &); 47 | void operator==(scoped_ptr const &) const; 48 | void operator!=(scoped_ptr const &) const; 49 | 50 | T* m_ptr; 51 | }; 52 | 53 | #endif -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/src-log4cpp/2-test_log4cpp.cpp: -------------------------------------------------------------------------------- 1 | // FileName: test_log4cpp1.cpp 2 | #include "log4cpp/Category.hh" 3 | #include "log4cpp/FileAppender.hh" 4 | #include "log4cpp/OstreamAppender.hh" 5 | #include "log4cpp/BasicLayout.hh" 6 | #include "log4cpp/SimpleLayout.hh" 7 | 8 | // 编译 g++ -o 2-test_log4cpp 2-test_log4cpp.cpp -llog4cpp 9 | int main(int argc, char *argv[]) 10 | { 11 | // 1实例化一个layout 对象 12 | log4cpp::Layout *layout = new log4cpp::SimpleLayout(); // 有不同的layout 13 | // 2. 初始化一个appender 对象 14 | log4cpp::Appender *appender = new log4cpp::FileAppender("FileAppender", 15 | "./2-test_log4cpp.log"); 16 | log4cpp::Appender *osappender = new log4cpp::OstreamAppender("OstreamAppender", 17 | &std::cout); 18 | // 3. 把layout对象附着在appender对象上 19 | appender->setLayout(layout); 20 | // appender->addLayout 没有addLayout,一个layout格式样式对应一个appender 21 | // 4. 实例化一个category对象 22 | log4cpp::Category &warn_log = 23 | log4cpp::Category::getInstance("darren"); // 是一个单例工厂 24 | // 5. 设置additivity为false,替换已有的appender 25 | warn_log.setAdditivity(false); 26 | // 5. 把appender对象附到category上 27 | warn_log.setAppender(appender); 28 | warn_log.addAppender(osappender); 29 | // 6. 设置category的优先级,低于此优先级的日志不被记录 30 | warn_log.setPriority(log4cpp::Priority::INFO); 31 | // 记录一些日志 32 | warn_log.info("Program info which cannot be wirten, darren = %d", 100); 33 | warn_log.warn("Program info which cannot be wirten, darren = %d", 100); 34 | warn_log.debug("This debug message will fail to write"); 35 | warn_log.alert("Alert info"); // C 风格 36 | warn_log.log(log4cpp::Priority::CRIT, "Importance depends on context"); 37 | // 其他记录日志方式 38 | warn_log.log(log4cpp::Priority::WARN, "This will be a logged warning, darren = %d", 100); 39 | warn_log.warnStream() << "This will be a logged warning, darren = " << 100; // C++ 风格 40 | 41 | log4cpp::Priority::PriorityLevel priority; 42 | bool this_is_critical = true; 43 | if (this_is_critical) 44 | priority = log4cpp::Priority::CRIT; 45 | else 46 | priority = log4cpp::Priority::DEBUG; 47 | warn_log.log(priority, "Importance depends on context"); 48 | 49 | warn_log.critStream() << "This will show up << as " 50 | << 1 << " critical message"; 51 | // clean up and flush all appenders 52 | log4cpp::Category::shutdown(); 53 | return 0; 54 | } -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/src-log4cpp/3-test_log4cpp copy.cpp: -------------------------------------------------------------------------------- 1 | // FileName: test_log4cpp2.cpp 2 | // Test log4cpp by config file. 3 | #include "log4cpp/Category.hh" 4 | #include "log4cpp/PropertyConfigurator.hh" 5 | #include "log4cpp/NDC.hh" 6 | // 编译:g++ -o 3-test_log4cpp 3-test_log4cpp.cpp -llog4cpp -lpthread 7 | 8 | void test(log4cpp::Category& category) 9 | { 10 | log4cpp::NDC::push(__FUNCTION__); // 记录NDC信息 11 | category.info("零声学院"); 12 | log4cpp::NDC::pop(); 13 | } 14 | int main(int argc, char* argv[]) 15 | { 16 | // 1 读取解析配置文件 17 | // 读取出错, 完全可以忽略,可以定义一个缺省策略或者使用系统缺省策略 18 | // BasicLayout输出所有优先级日志到ConsoleAppender 19 | try { 20 | log4cpp::PropertyConfigurator::configure("./3-test_log4cpp.conf"); 21 | } catch(log4cpp::ConfigureFailure& f) { 22 | std::cout << "Configure Problem " << f.what() << std::endl; 23 | return -1; 24 | } 25 | 26 | // 2 实例化category对象 27 | // 这些对象即使配置文件没有定义也可以使用,不过其属性继承其父category 28 | // 通常使用引用可能不太方便,可以使用指针,以后做指针使用 29 | // log4cpp::Category* root = &log4cpp::Category::getRoot(); 30 | log4cpp::Category& root = log4cpp::Category::getRoot(); 31 | log4cpp::NDC::push(__FUNCTION__); // 记录NDC信息 32 | // log4cpp::NDC::push("ndc2"); 33 | log4cpp::Category& sub1 = 34 | log4cpp::Category::getInstance(std::string("sub1")); 35 | log4cpp::Category& sub1 = 36 | log4cpp::Category::getInstance(std::string("sub1")); 37 | log4cpp::Category& sub1_sub2 = 38 | log4cpp::Category::getInstance(std::string("sub1.sub2")); 39 | // 3 正常使用这些category对象进行日志处理。 40 | // sub1 has appender A1 and rootappender. 41 | sub1.info("sub1 This is some info"); 42 | 43 | test(root); 44 | root.info("root This is some info"); 45 | // sub1.alert("sub1 A warning"); 46 | 47 | // // sub1_sub2 only have A2 appender. 48 | sub1_sub2.debug("sub1_sub2 This debug message will fail to write"); 49 | sub1_sub2.alert("sub1_sub2 All hands abandon ship"); 50 | sub1_sub2.critStream() << "sub1_sub2 This will show up << as " << 1 << " critical message"; 51 | sub1_sub2 << log4cpp::Priority::ERROR 52 | << "sub1_sub2 And this will be an error"; 53 | sub1_sub2.log(log4cpp::Priority::WARN, "sub1_sub2 This will be a logged warning"); 54 | // clean up and flush all appenders 55 | log4cpp::Category::shutdown(); 56 | return 0; 57 | } -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/src-log4cpp/3-test_log4cpp.conf: -------------------------------------------------------------------------------- 1 | # 文件名: 3-test_log4cpp.conf 2 | # a simple test config 3 | #定义了3个category sub1, sub2, sub1.sub2 4 | # category 有两个参数 日志级别,Appender 5 | log4cpp.rootCategory=DEBUG, rootAppender 6 | # log4cpp.category.sub1设置日志级别默认和root一致, Appender为A1 7 | log4cpp.category.sub1=,A1 8 | # log4cpp.category.sub2设置为INFO,Appender默认使用root的 9 | log4cpp.category.sub2=INFO 10 | #log4cpp.category.sub1.sub2=ERROR, A2 11 | log4cpp.category.sub1.sub2=, A2 12 | # 设置sub1.sub2 的additivity属性,该属性默认值为true 13 | # 如果值为true,则该Category的Appender包含了父Category的Appender, 即是日志也从root的appender输出 14 | # 如果值为false,则该Category的Appender取代了父Category的Appender 15 | log4cpp.additivity.sub1=false 16 | # sub1.sub2的日志也从sub1的appender输出 17 | log4cpp.additivity.sub1.sub2=true 18 | #定义rootAppender类型和layout属性 19 | log4cpp.appender.rootAppender=org.apache.log4cpp.ConsoleAppender 20 | log4cpp.appender.rootAppender.layout=org.apache.log4cpp.BasicLayout 21 | #定义A1的属性 22 | log4cpp.appender.A1=org.apache.log4cpp.FileAppender 23 | log4cpp.appender.A1.fileName=A1.log 24 | log4cpp.appender.A1.layout=org.apache.log4cpp.SimpleLayout 25 | #定义A2的属性 26 | log4cpp.appender.A2=org.apache.log4cpp.ConsoleAppender 27 | log4cpp.appender.A2.layout=org.apache.log4cpp.PatternLayout 28 | #log4cpp.appender.A2.layout.ConversionPattern=The message '%m' at time 29 | # log4cpp.appender.A2.layout.ConversionPattern=%d %m %n 30 | # %d 时间戳 %t 线程名 %x NDC %p 优先级 %m log message 内容 %n 回车换行 31 | log4cpp.appender.A2.layout.ConversionPattern=%d %p %x - %m%n -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/src-log4cpp/3-test_log4cpp.cpp: -------------------------------------------------------------------------------- 1 | // FileName: test_log4cpp2.cpp 2 | // Test log4cpp by config file. 3 | #include "log4cpp/Category.hh" 4 | #include "log4cpp/PropertyConfigurator.hh" 5 | #include "log4cpp/NDC.hh" 6 | // 编译:g++ -o 3-test_log4cpp 3-test_log4cpp.cpp -llog4cpp -lpthread 7 | 8 | void test(log4cpp::Category &category) 9 | { 10 | log4cpp::NDC::push(__FUNCTION__); // 记录NDC信息 11 | category.info("零声学院"); 12 | log4cpp::NDC::pop(); 13 | } 14 | int main(int argc, char *argv[]) 15 | { 16 | // 1 读取解析配置文件 17 | // 读取出错, 完全可以忽略,可以定义一个缺省策略或者使用系统缺省策略 18 | // BasicLayout输出所有优先级日志到ConsoleAppender 19 | try 20 | { 21 | log4cpp::PropertyConfigurator::configure("./3-test_log4cpp.conf"); 22 | } 23 | catch (log4cpp::ConfigureFailure &f) 24 | { 25 | std::cout << "Configure Problem " << f.what() << std::endl; 26 | return -1; 27 | } 28 | 29 | // 2 实例化category对象 30 | // 这些对象即使配置文件没有定义也可以使用,不过其属性继承其父category 31 | // 通常使用引用可能不太方便,可以使用指针,以后做指针使用 32 | // log4cpp::Category* root = &log4cpp::Category::getRoot(); 33 | log4cpp::Category &root = log4cpp::Category::getRoot(); 34 | log4cpp::Category &sub1 = log4cpp::Category::getInstance(std::string("sub1")); 35 | log4cpp::Category &sub2 = log4cpp::Category::getInstance(std::string("sub2")); 36 | log4cpp::Category &sub1_sub2 = log4cpp::Category::getInstance(std::string("sub1.sub2")); 37 | 38 | // 3 正常使用这些category对象进行日志处理。 39 | root.debug("root debug"); 40 | root.info("root info"); 41 | root.notice("root notice"); 42 | root.warn("root warn"); 43 | root.error("root error"); 44 | root.crit("root crit"); 45 | root.alert("root alert"); 46 | root.fatal("root fatal"); 47 | root.emerg("root emerg"); 48 | 49 | printf("--------------------------------\n"); 50 | 51 | sub1.debug("sub1 debug"); 52 | sub1.info("sub1 info"); 53 | sub1.notice("sub1 notice"); 54 | sub1.warn("sub1 warn"); 55 | sub1.error("sub1 error"); 56 | sub1.crit("sub1 crit"); 57 | sub1.alert("sub1 alert"); 58 | sub1.fatal("sub1 fatal"); 59 | sub1.emerg("sub1 emerg"); 60 | printf("--------------------------------\n"); 61 | 62 | sub2.debug("sub2 debug"); 63 | sub2.info("sub2 info"); 64 | sub2.notice("sub2 notice"); 65 | sub2.warn("sub2 warn"); 66 | sub2.error("sub2 error"); 67 | sub2.crit("sub2 crit"); 68 | sub2.alert("sub2 alert"); 69 | sub2.fatal("sub2 fatal"); 70 | sub2.emerg("sub2 emerg"); 71 | printf("--------------------------------\n"); 72 | 73 | sub1_sub2.debug("sub1_sub2 debug"); 74 | sub1_sub2.info("sub1_sub2 info"); 75 | sub1_sub2.notice("sub1_sub2 notice"); 76 | sub1_sub2.warn("sub1_sub2 warn"); 77 | sub1_sub2.error("sub1_sub2 error"); 78 | sub1_sub2.crit("sub1_sub2 crit"); 79 | sub1_sub2.alert("sub1_sub2 alert"); 80 | sub1_sub2.fatal("sub1_sub2 fatal"); 81 | sub1_sub2.emerg("sub1_sub2 emerg"); 82 | // clean up and flush all appenders 83 | log4cpp::Category::shutdown(); 84 | return 0; 85 | } -------------------------------------------------------------------------------- /3.3开源组件/3.3.2 异步日志方案log4cpp/log-src-20211230/src-log4cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | project (log4cpptest) 4 | # 设置C++标准为 C++ 11 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -W -Wall -Wextra -g") 6 | include_directories(/usr/local/include/) 7 | link_directories(/usr/local/lib) 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 9 | # test1 10 | add_executable(1-file_test 1-file_test.cpp) 11 | target_link_libraries(1-file_test) 12 | # test2 13 | add_executable(2-test_log4cpp 2-test_log4cpp.cpp) 14 | target_link_libraries(2-test_log4cpp log4cpp pthread) 15 | # test3 16 | add_executable(3-test_log4cpp 3-test_log4cpp.cpp) 17 | target_link_libraries(3-test_log4cpp log4cpp pthread) 18 | # test4 19 | add_executable(4-RollingFileAppender 4-RollingFileAppender.cpp) 20 | target_link_libraries(4-RollingFileAppender log4cpp pthread) 21 | # test5 22 | add_executable(5-StringQueueAppender 5-StringQueueAppender.cpp) 23 | target_link_libraries(5-StringQueueAppender log4cpp pthread) -------------------------------------------------------------------------------- /3.3开源组件/3.3.3 应用层协议设计ProtoBufThrift/2.doc/Protobuf3语法详解-20220104.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hewei-bit/Basic-Component-design/373c511482a37b1e66efec690e2d51b33558105b/3.3开源组件/3.3.3 应用层协议设计ProtoBufThrift/2.doc/Protobuf3语法详解-20220104.pdf -------------------------------------------------------------------------------- /3.3开源组件/3.3.3 应用层协议设计ProtoBufThrift/README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计——池式组件(线程池、内存池、异步请求池)、高性能组件(原子操作CAS与锁、无锁消息队列、定时器、死锁检测、内存泄漏检测)及开源组件(libevent/libev、异步日志log4cpp、应用层协议设计ProtoBuf/Thrift) 3 | -------------------------------------------------------------------------------- /3.3开源组件/README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计——池式组件(线程池、内存池、异步请求池)、高性能组件(原子操作CAS与锁、无锁消息队列、定时器、死锁检测、内存泄漏检测)及开源组件(libevent/libev、异步日志log4cpp、应用层协议设计ProtoBuf/Thrift) 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic-Component-design 2 | 后端开发基础组件设计——池式组件(线程池、内存池、异步请求池)、高性能组件(原子操作CAS与锁、无锁消息队列、定时器、死锁检测、内存泄漏检测)及开源组件(libevent/libev、异步日志log4cpp、应用层协议设计ProtoBuf/Thrift) 3 | --------------------------------------------------------------------------------