├── AOP ├── README.md ├── main.cpp └── Aspect.hpp ├── MemoryPool ├── README.md └── main.cpp ├── README.md ├── NineBoxView ├── README.md ├── CMakeLists.txt ├── Vector2i.hpp ├── MapGrid.hpp ├── main.cpp └── Map.hpp ├── timer ├── READEME.txt ├── CMakeLists.txt ├── main.cpp ├── TimerMgr.h └── TimerMgr.cpp ├── ObjectPool ├── README.md └── main.cpp ├── Ioc ├── CMakeLists.txt ├── NonCopyable.hpp ├── Ioc_11.hpp ├── Any.hpp ├── Ioc_17.hpp └── main.cpp ├── MessageBus ├── CMakeLists.txt ├── NonCopyable.hpp ├── Define.h ├── Any.hpp ├── MessageBus.hpp ├── main.cpp └── function_traits.hpp ├── SpecailHeap ├── CMakeLists.txt ├── main.cpp └── BinaryHeap.hpp ├── ThreadPool ├── ThreadPool1 │ ├── README.md │ ├── main.cpp │ ├── ThreadPool.hpp │ └── SyncQueue.hpp └── ThreadPool2 │ ├── ThreadPool.cpp │ ├── main.cpp │ ├── ThreadSafeQueue.hpp │ └── ThreadPool.h ├── OrderedMap ├── CMakeLists.txt ├── main.cpp └── OrderedMap.h ├── RingQueue ├── CMakeLists.txt ├── main.cpp └── RingQueue.hpp ├── redis ├── distribute_lock │ ├── distribute_lock.lua │ └── distribute_lock.cpp └── delay_queue │ ├── delay_queue.lua │ └── delay_queue.cpp ├── Random ├── TestRandom.cpp └── UniformRandom.h ├── SensitiveWordsCheck ├── CMakeLists.txt ├── main.cpp └── SensitiveWordsCheck.hpp ├── ThreadLockFreeQueue ├── CMakeLists.txt ├── main.cpp ├── LockFreeQueue.hpp └── LockFreeQueue1.cpp ├── Curl ├── CMakeLists.txt └── multi_example │ ├── CMakeLists.txt │ ├── TestCurlMgr.cpp │ ├── CurlMgr.h │ └── CurlMgr.cpp ├── ThreadLockFreeStack ├── LockFreeStack2.cpp └── LockFreeStack.cpp ├── ThreadSafeQueue ├── ThreadSafeQueue.cpp └── ThreadSafeQueue2.cpp ├── ThreadsafeList └── ThreadSafeList.cpp └── ThreadSafeLookupTable └── ThreadSafeLookupTable.cpp /AOP/README.md: -------------------------------------------------------------------------------- 1 | # note: 2 | ## this is compile use c++11 -------------------------------------------------------------------------------- /MemoryPool/README.md: -------------------------------------------------------------------------------- 1 | # note: 2 | ## this is compile use c++11 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cplusplus-Common-Tools 2 | this is my learn summary c++ common tools 3 | 4 | -------------------------------------------------------------------------------- /NineBoxView/README.md: -------------------------------------------------------------------------------- 1 | # note: 2 | ## this is compile use c++11 3 | ## this is nine box view for game -------------------------------------------------------------------------------- /timer/READEME.txt: -------------------------------------------------------------------------------- 1 | # valgrind detect 2 | valgrind --leak-check=full --log-file=valgrind.log --num-callers=30 ./test 3 | -------------------------------------------------------------------------------- /ObjectPool/README.md: -------------------------------------------------------------------------------- 1 | # note: 2 | ## this is compile use c++11 3 | ## this is code is not initialize and reset statuts of objects -------------------------------------------------------------------------------- /Ioc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(learn) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | add_executable(learn main.cpp) -------------------------------------------------------------------------------- /MessageBus/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(learn) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | add_executable(learn main.cpp) -------------------------------------------------------------------------------- /NineBoxView/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(test) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | add_executable(test main.cpp) -------------------------------------------------------------------------------- /SpecailHeap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(test) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | add_executable(test main.cpp) -------------------------------------------------------------------------------- /ThreadPool/ThreadPool1/README.md: -------------------------------------------------------------------------------- 1 | # note: 2 | ## this is compile use c++11 3 | ## return type of put task in thread pool,please. template class have default type -------------------------------------------------------------------------------- /OrderedMap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(test) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | add_executable(test main.cpp OrderedMap.h) -------------------------------------------------------------------------------- /RingQueue/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(test) 2 | 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | set(CMAKE_CXX_STANDARD 11) 6 | 7 | aux_source_directory(. FILES) 8 | 9 | add_executable(test ${FILES}) -------------------------------------------------------------------------------- /ThreadPool/ThreadPool2/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include "ThreadPool.h" 2 | 3 | thread_local work_stealing_queue* ThreadPool::local_work_queue = nullptr; 4 | thread_local unsigned ThreadPool::my_index = 0; -------------------------------------------------------------------------------- /redis/distribute_lock/distribute_lock.lua: -------------------------------------------------------------------------------- 1 | local del_key = KEYS[1] 2 | local del_arg = ARGV[1] 3 | 4 | if redis.call("get",del_key) == del_arg then 5 | return redis.call("del",del_key) 6 | else 7 | return 0 8 | end -------------------------------------------------------------------------------- /Ioc/NonCopyable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class NonCopyable 3 | { 4 | public: 5 | NonCopyable(const NonCopyable&) = delete; // deleted 6 | NonCopyable& operator = (const NonCopyable&) = delete; // deleted 7 | NonCopyable() = default; // available 8 | }; 9 | -------------------------------------------------------------------------------- /MessageBus/NonCopyable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class NonCopyable 3 | { 4 | public: 5 | NonCopyable(const NonCopyable&) = delete; // deleted 6 | NonCopyable& operator = (const NonCopyable&) = delete; // deleted 7 | NonCopyable() = default; // available 8 | }; 9 | -------------------------------------------------------------------------------- /Random/TestRandom.cpp: -------------------------------------------------------------------------------- 1 | #include "Random.h" 2 | #include 3 | using namespace std; 4 | 5 | // Test program 6 | int main( ) 7 | { 8 | Random r{ 1 }; 9 | 10 | for( int i = 0; i < 20; ++i ) 11 | cout << r.randomInt( ) << endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /SensitiveWordsCheck/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(test) 3 | 4 | aux_source_directory(./ FILES) 5 | 6 | set(CMAKE_CXX_STANDARD 11) 7 | 8 | add_executable(test ${FILES}) 9 | 10 | set(THREADS_PREFER_PTHREAD_FLAG ON) 11 | find_package(Threads REQUIRED) 12 | target_link_libraries(test PRIVATE Threads::Threads) 13 | 14 | -------------------------------------------------------------------------------- /ThreadLockFreeQueue/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(test) 3 | 4 | aux_source_directory(./ FILES) 5 | 6 | set(CMAKE_CXX_STANDARD 11) 7 | 8 | add_executable(test ${FILES}) 9 | 10 | set(THREADS_PREFER_PTHREAD_FLAG ON) 11 | find_package(Threads REQUIRED) 12 | target_link_libraries(test PRIVATE Threads::Threads) 13 | 14 | -------------------------------------------------------------------------------- /timer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(test) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_BUILD_TYPE "Debug") 6 | 7 | add_executable(test main.cpp TimerMgr.h TimerMgr.cpp) 8 | 9 | #valgrind发现的错误更精确,如能够定位到源代码行 10 | list(APPEND flags "-g" "-O0") 11 | 12 | target_compile_options(test 13 | PRIVATE 14 | ${flags} 15 | ) -------------------------------------------------------------------------------- /NineBoxView/Vector2i.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __VECTOR2I__ 2 | #define __VECTOR2I__ 3 | 4 | //9宫格左下角坐标 5 | class Vector2i{ 6 | public: 7 | Vector2i() = default; 8 | Vector2i(int x,int y):m_x(x),m_y(y){}; 9 | public: 10 | bool operator ==(const Vector2i& other){ 11 | return ((m_x == other.m_x) &&(m_y==other.m_y)); 12 | } 13 | //private:示例不做权限控制了 14 | int m_x{0}; 15 | int m_y{0}; 16 | }; 17 | 18 | #endif -------------------------------------------------------------------------------- /Curl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10 FATAL_ERROR) 2 | project(curl LANGUAGES C CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | if(NOT CMAKE_BUILD_TYPE) 9 | set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE) 10 | endif() 11 | message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 12 | 13 | add_subdirectory(multi_example) 14 | -------------------------------------------------------------------------------- /MessageBus/Define.h: -------------------------------------------------------------------------------- 1 | #ifndef __CPP17 2 | #if __cplusplus > 201402L 3 | # define __CPP17 (1) 4 | #else 5 | # define __CPP17 (0) 6 | #endif 7 | #endif 8 | 9 | #ifndef __CPP14 10 | #if __cplusplus > 201103L 11 | # define __CPP14 (1) 12 | #else 13 | # define __CPP14 (0) 14 | #endif 15 | #endif 16 | 17 | #ifndef __CPP11 18 | #if __cplusplus > 199711L 19 | # define __CPP11 (1) 20 | #else 21 | # define __CPP11 (0) 22 | #endif 23 | #endif -------------------------------------------------------------------------------- /Curl/multi_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | aux_source_directory(. FILES) 2 | 3 | FIND_PACKAGE(Threads REQUIRED) 4 | if(NOT Threads_FOUND) 5 | message(FATAL_ERROR "not find thread") 6 | endif() 7 | 8 | add_executable(curltest ${FILES}) 9 | 10 | target_link_libraries(curltest 11 | curl 12 | Threads::Threads 13 | ) 14 | 15 | target_compile_options(curltest 16 | PRIVATE 17 | ${CXX_FLAGS} 18 | ${THREADS_PREFER_PTHREAD_FLAG} 19 | ) 20 | 21 | install( 22 | TARGETS 23 | curltest 24 | RUNTIME 25 | DESTINATION ${CMAKE_SOURCE_DIR}/bin 26 | ) -------------------------------------------------------------------------------- /ThreadPool/ThreadPool2/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ThreadPool.h" 2 | #include 3 | 4 | int main() 5 | { 6 | ThreadPool threadPool; 7 | int i = 1; 8 | std::vector> taskResV; 9 | 10 | taskResV.emplace_back(std::move(threadPool.submit([&]() {return i * i; }))); 11 | taskResV.emplace_back(std::move(threadPool.submit([&]() {return (i + 1) * (i + 1); }))); 12 | 13 | std::for_each(taskResV.begin(), taskResV.end(), 14 | [](ThreadPool::TaskHandle& future) { 15 | std::cout << future.get()<<" " << std::endl; 16 | }); 17 | 18 | } -------------------------------------------------------------------------------- /redis/delay_queue/delay_queue.lua: -------------------------------------------------------------------------------- 1 | local zset_key = 'delay-queue' 2 | local min_score = 0 3 | local max_score = '+inf' 4 | local offset = 0 5 | local limit = 1 6 | 7 | local status, type = next(redis.call('TYPE', zset_key)) 8 | if status ~= nil and status == 'ok' then 9 | if type == 'zset' then 10 | local list = redis.call('ZRANGEBYSCORE', zset_key, min_score, max_score, 'LIMIT', offset, limit) 11 | if list ~= nil and #list > 0 then 12 | local value = list[1] 13 | redis.call('ZREM', zset_key, value) 14 | return value 15 | end 16 | end 17 | end 18 | return nil -------------------------------------------------------------------------------- /RingQueue/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "RingQueue.hpp" 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | RingQueue ringQueue; 10 | 11 | std::cout<<"is empty:"< 2 | #include 3 | 4 | #include "CurlMgr.h" 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | std::thread HttpThread([](){ 11 | int32_t ret = 0; 12 | 13 | CurlMgr curlMgr; 14 | ret = curlMgr.Init(); 15 | if(ret != 0) 16 | { 17 | std::cout<<"init ret="<void{ 25 | std::cout<<"ret="< m_Obj; //简单举个例子 可以用内存池等等 59 | }; 60 | 61 | #endif //__MAP_GRID__H_ -------------------------------------------------------------------------------- /SpecailHeap/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "BinaryHeap.hpp" 4 | using namespace std; 5 | 6 | // Test program 7 | struct Test{ 8 | Test()= default; 9 | Test(int value,uint32_t key):value(value),key(key){} 10 | bool operator<(const Test& anther)const{ 11 | return value(const Test& anther)const{ 15 | return value>anther.value; 16 | } 17 | 18 | int value{0}; //cmp value 19 | uint32_t key{0};//hash table key 20 | }; 21 | 22 | int main(){ 23 | binaryheap::MinHeap h(std::less{});//min heap 24 | //binaryheap::MaxHeap h(std::greater{});//max heap 25 | 26 | h.Push(Test{1,11}); 27 | h.Push(Test{5,55}); 28 | h.Push(Test{3,33}); 29 | h.Push(Test{3,34}); 30 | h.Push(Test{2,22}); 31 | h.Push(Test{4,44}); 32 | h.Push(Test{8,88}); 33 | h.Push(Test{7,77}); 34 | h.Push(Test{6,66}); 35 | h.Push(Test{9,99}); 36 | 37 | //remove internal data 38 | h.Remove(55); 39 | h.Remove(33); 40 | h.Remove(77); 41 | 42 | 43 | Test x ; 44 | while(!h.Empty()){ 45 | h.Pop( x ); 46 | std::cout<<"pop:value:"< 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #include "LockFreeQueue.hpp" 8 | 9 | LockFreeQueue lockFreeQueue; 10 | 11 | void PushThreadFun() 12 | { 13 | static thread_local int i = 1; 14 | std::random_device r; 15 | std::default_random_engine e(r()); 16 | std::uniform_int_distribution uniform_dist(1, 3); 17 | while (true) 18 | { 19 | int* p = new int (i); 20 | std::cout << "PushThreadFun id:" << std::this_thread::get_id() << " value:" << i << std::endl; 21 | lockFreeQueue.Push(p); 22 | i++; 23 | std::this_thread::sleep_for(std::chrono::seconds(uniform_dist(e))); 24 | } 25 | } 26 | 27 | void GetThreadFun() 28 | { 29 | while (true) 30 | { 31 | if(!lockFreeQueue.Empty()) 32 | { 33 | auto* tmp = lockFreeQueue.Pop(); 34 | while(!tmp->empty()) 35 | { 36 | auto* pData = tmp->front(); 37 | tmp->pop(); 38 | std::cout << "GetThreadFun id:" << std::this_thread::get_id() << " value:" << *pData << std::endl; 39 | } 40 | } 41 | } 42 | } 43 | 44 | int main() 45 | { 46 | std::thread pushT(PushThreadFun); 47 | std::thread getT(GetThreadFun); 48 | 49 | pushT.join(); 50 | getT.join(); 51 | return 0; 52 | } -------------------------------------------------------------------------------- /SensitiveWordsCheck/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | #include "SensitiveWordsCheck.hpp" 7 | int main() 8 | { 9 | //std::vector vec{"你","是","傻","子"}; 10 | 11 | // std::vector sensitiveStr {"a", "b", "c"};//先假设abc是敏感词 12 | std::vector sensitiveStr1 {"傻", "蛋"}; 13 | std::vector sensitiveStr2 {"傻", "子"}; 14 | 15 | SensitiveWordsCheck wordsCheck; 16 | //加入敏感词 17 | wordsCheck.AddWords(sensitiveStr1); 18 | wordsCheck.AddWords(sensitiveStr2); 19 | 20 | // std::vector testStr {"g", "a", "b"};//测试字符串 21 | // std::vector testStr {"h", "g", "a", "b", "c", "i", "a", "b", "d"};//测试字符串 22 | std::vector testStr {"你", "是", "傻", "蛋", "我", "是", "傻", "子"}; 23 | 24 | uint32_t sIdx = 0; 25 | uint32_t eIdx = 0; 26 | while(sIdx < testStr.size()) 27 | { 28 | sIdx = eIdx == 0 ? 0 : eIdx + 1; 29 | if(wordsCheck.CheckWords(testStr, sIdx, eIdx)) 30 | { 31 | std::stringstream iss; 32 | for(uint32_t idx = sIdx; idx <= eIdx; idx++) 33 | { 34 | iss << testStr[idx]; 35 | } 36 | std::cout<<"testStr::有敏感词:"< 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | template 13 | class LockFreeQueue 14 | { 15 | public: 16 | LockFreeQueue() 17 | { 18 | mIndex.store(0); 19 | }; 20 | ~LockFreeQueue() 21 | { 22 | for(uint32_t index = 0; index < 2; index++) 23 | { 24 | std::queue& queue = queueArr[index]; 25 | while(!queue.empty()) 26 | { 27 | auto* p = queue.front(); 28 | if(p != nullptr) 29 | { 30 | delete p; 31 | } 32 | queue.pop(); 33 | } 34 | } 35 | } 36 | 37 | public: 38 | void Push(T* data) 39 | { 40 | queueArr[mIndex].push(data); 41 | } 42 | 43 | std::queue* Pop() 44 | { 45 | uint32_t cur = mIndex.load(); 46 | mIndex = (cur + 1) % 2; 47 | return &queueArr[cur]; 48 | } 49 | 50 | bool Empty() 51 | { 52 | uint32_t cur = mIndex.load(); 53 | return (queueArr[cur].empty() && queueArr[(cur + 1) % 2].empty()); 54 | } 55 | 56 | private: 57 | std::atomic mIndex; 58 | std::queue queueArr[2]; 59 | }; 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | #endif //_LOCK_FREE_QUEUE__ -------------------------------------------------------------------------------- /OrderedMap/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "OrderedMap.h" 5 | 6 | struct Role 7 | { 8 | uint64_t roleId = 0; 9 | uint32_t time = 0; 10 | }; 11 | 12 | struct RoleKey : public std::unary_function 13 | { 14 | uint64_t operator()(Role* value) const 15 | { 16 | return value->roleId; 17 | } 18 | }; 19 | 20 | struct Compare : public std::binary_function 21 | { 22 | bool operator()(Role* lval , Role* rval) const 23 | { 24 | if(lval->time != rval->time) 25 | { 26 | return lval->time < rval->time; 27 | } 28 | return lval->roleId < rval->roleId; 29 | } 30 | }; 31 | 32 | int main() 33 | { 34 | OrderedHashMap pRoles; 35 | 36 | for(uint32_t index = 1; index <= 5; index++) 37 | { 38 | Role* pRole = new Role(); 39 | pRole->roleId = index; 40 | pRole->time = index; 41 | pRoles.Insert(pRole); 42 | } 43 | 44 | pRoles.Erase(1); 45 | 46 | std::vector> removeRoles; 47 | pRoles.ForeachRemove([&](Role* pRole){ 48 | if(pRole->time >= 4) 49 | { 50 | return false; 51 | } 52 | removeRoles.push_back(std::unique_ptr(pRole)); 53 | return true; 54 | }); 55 | 56 | //4 5 57 | pRoles.Foreach([&](Role* pRole){ 58 | std::cout<<" roleId:"<roleId<<" time:"<time<roleId = 2; 65 | pRole->time = 2; 66 | pRoles.Insert(pRole); 67 | 68 | //2 4 5 69 | pRoles.Foreach([&](Role* pRole){ 70 | std::cout<<" roleId:"<roleId<<" time:"<time< 2 | #include 3 | #include 4 | #include 5 | #if __WIN32 6 | #include 7 | #endif 8 | #include "Map.hpp" 9 | using namespace std; 10 | 11 | constexpr int MAP_WIDTH = 256; 12 | constexpr int MAP_HEIGHT = 256; 13 | constexpr int MAP_GRID_SIZE = 10; 14 | 15 | static std::random_device rd; 16 | static std::mt19937 gen(rd()); 17 | static std::uniform_real_distribution<> dis(0, MAP_WIDTH); 18 | 19 | float GetPos(){ 20 | return dis(gen); 21 | } 22 | 23 | int main() { 24 | Map map; 25 | map.InitMap(MAP_WIDTH,MAP_HEIGHT,MAP_GRID_SIZE); 26 | while (1){ 27 | //模拟玩家坐标 28 | float fromPosX = GetPos(); 29 | float fromPosY = GetPos(); 30 | std::cout<<"fromPost:("< deleteArea,addArea; 50 | map.InterestArea(from,dst,deleteArea,addArea); 51 | 52 | //具体更新玩家视野 简单举个例子 53 | ObjBase * obj = new ObjBase(); 54 | obj->SetPosX(dst.m_x); 55 | obj->SetPosY(dst.m_y); 56 | map.AddObj(dst,*obj); 57 | map.RemoveObj(*obj); 58 | 59 | #if __WIN32 60 | Sleep(1000 * 1); 61 | #endif 62 | //std::this_thread::sleep_for(std::chrono::seconds(5)); 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /RingQueue/RingQueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __RING_QUEUE_H__ 2 | #define __RING_QUEUE_H__ 3 | 4 | #include 5 | #include 6 | 7 | template 8 | class RingQueue 9 | { 10 | public: 11 | RingQueue(); 12 | ~RingQueue(); 13 | 14 | bool Push(const T& item); 15 | bool Pop(T& item); 16 | 17 | bool IsEmpty(); 18 | bool IsFull(); 19 | 20 | private: 21 | uint32_t _IncIndex(uint32_t index) const; 22 | 23 | private: 24 | volatile uint32_t m_nTail{0}; 25 | volatile uint32_t m_nHead{0}; 26 | T m_items[MAX + 1]; 27 | std::mutex m_mutex; 28 | }; 29 | 30 | template 31 | RingQueue::RingQueue() : m_nTail(0), m_nHead(0){} 32 | 33 | template 34 | RingQueue::~RingQueue(){} 35 | 36 | template 37 | bool RingQueue::Push(const T& item) 38 | { 39 | std::lock_guard lg(m_mutex); 40 | uint32_t nextTail = this->_IncIndex(m_nTail); 41 | if(nextTail == m_nHead) 42 | { 43 | return false; 44 | } 45 | m_items[m_nTail] = item; 46 | m_nTail = nextTail; 47 | return true; 48 | } 49 | 50 | template 51 | bool RingQueue::Pop(T& item) 52 | { 53 | std::lock_guard lg(m_mutex); 54 | if(m_nTail == m_nHead) 55 | { 56 | return false; 57 | } 58 | item = m_items[m_nHead]; 59 | m_nHead = this->_IncIndex(m_nHead); 60 | return true; 61 | } 62 | 63 | template 64 | bool RingQueue::IsEmpty() 65 | { 66 | std::lock_guard lg(m_mutex); 67 | return (m_nHead == m_nTail); 68 | } 69 | 70 | template 71 | bool RingQueue::IsFull() 72 | { 73 | std::lock_guard lg(m_mutex); 74 | uint32_t nextTail = this->_IncIndex(m_nTail); 75 | return (nextTail == m_nHead); 76 | } 77 | 78 | template 79 | uint32_t RingQueue::_IncIndex(uint32_t index) const 80 | { 81 | return (index + 1) % (MAX + 1); 82 | } 83 | 84 | #endif //__RING_QUEUE_H__ -------------------------------------------------------------------------------- /ThreadPool/ThreadPool1/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ThreadPool.hpp" 4 | 5 | using namespace std; 6 | 7 | int add_fun1(int n) { 8 | std::cout << "commonfun:add_fun1:n=" << n << std::endl; 9 | return n + 1; 10 | } 11 | 12 | double add_fun2(int n) { 13 | std::cout << "commonfun:add_fun2:n=" << n << std::endl; 14 | return n + 1.0; 15 | } 16 | void TestThdPool(){ 17 | { 18 | ThreadPool<> pool; 19 | pool.Start(2); 20 | std::thread thd1([&pool] { 21 | for (int i = 0; i < 1; i++) { 22 | auto thdId = this_thread::get_id(); 23 | pool.AddTask([thdId] { 24 | cout << "lambda表达式:同步层线程1的线程ID:" << thdId << endl; }); 25 | }}); 26 | 27 | std::thread thd2([&pool] { 28 | auto thdId = this_thread::get_id(); 29 | pool.AddTask([thdId] { 30 | cout << "lambda表达式:同步层线程2的线程ID:" << thdId << endl; }); 31 | 32 | std::function f = std::bind(add_fun1, 1); 33 | pool.AddTask(f);//其实参数应该是std::function 34 | 35 | pool.AddTask(add_fun2, 1); 36 | 37 | }); 38 | this_thread::sleep_for(std::chrono::seconds(2)); 39 | pool.Stop(); 40 | thd1.join(); 41 | thd2.join(); 42 | } 43 | 44 | { 45 | ThreadPool pool; 46 | pool.Start(1); 47 | std::thread thd1([&pool] { 48 | auto thdId = this_thread::get_id(); 49 | auto f = std::bind(add_fun1, 1); 50 | pool.AddTask(f); 51 | }); 52 | 53 | this_thread::sleep_for(std::chrono::seconds(2)); 54 | pool.Stop(); 55 | thd1.join(); 56 | } 57 | 58 | { 59 | ThreadPool pool; 60 | pool.Start(1); 61 | std::thread thd1([&pool] { 62 | auto thdId = this_thread::get_id(); 63 | pool.AddTask(add_fun2,1); 64 | }); 65 | 66 | this_thread::sleep_for(std::chrono::seconds(2)); 67 | pool.Stop(); 68 | thd1.join(); 69 | } 70 | } 71 | 72 | int main() { 73 | TestThdPool(); 74 | return 0; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /AOP/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Aspect.hpp" 4 | 5 | using namespace std; 6 | 7 | 8 | struct AA{ 9 | void Before(int i){ 10 | cout <<"Before from AA"< f = std::bind(&HT, std::placeholders::_1); 49 | Invoke(std::function(std::bind(&HT, std::placeholders::_1)), 1); 50 | // 组合了两个切面AA BB 51 | Invoke(f, 1); 52 | 53 | // 织入普通函数 54 | Invoke(>); 55 | Invoke(&HT, 1); 56 | 57 | // 织入lambda表达式 58 | Invoke([](int i){}, 1); 59 | Invoke([]{}); 60 | } 61 | 62 | 63 | 64 | /*------------------------------------*/ 65 | struct TimeElapsedAspect{ 66 | void Before(int i){ 67 | cout <<"time start"<< endl; 68 | } 69 | void After(int i){ 70 | cout <<"time end"<< endl; 71 | } 72 | }; 73 | struct LoggingAspect{ 74 | void Before(int i){ 75 | std::cout <<"entering"<< std::endl; 76 | } 77 | void After(int i){ 78 | std::cout <<"leaving"<< std::endl; 79 | } 80 | }; 81 | void foo(int a){ 82 | cout <<"real HT function: "<(&foo, 1); //织入方法 87 | cout <<"-----------------------"<< endl; 88 | Invoke(&foo, 1); 89 | } 90 | 91 | int main() { 92 | TestAop1(); 93 | TestAop2(); 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /Ioc/Ioc_11.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Any.hpp" 7 | #include "NonCopyable.hpp" 8 | 9 | using namespace std; 10 | 11 | class IocContainer : NonCopyable 12 | { 13 | public: 14 | IocContainer() = default; 15 | ~IocContainer() = default; 16 | 17 | template 18 | typename std::enable_if::value>::type RegisterType(const string& strKey){ 19 | std::function function = [](Args&&... args){ return new T(new Depend(std::forward(args)...)); };//通过闭包擦除了参数类型 20 | RegisterType(strKey, std::move(function)); 21 | } 22 | 23 | template 24 | typename std::enable_if::value>::type RegisterType(const string& strKey){ 25 | std::function function = [](Args&&... args){ return new Depend(std::forward(args)...); }; 26 | RegisterType(strKey, std::move(function)); 27 | } 28 | 29 | template 30 | void RegisterSimple(const string& strKey){ 31 | std::function function = [](Args&&... args){return new T(std::forward(args)...);}; 32 | RegisterType(strKey,std::move(function)); 33 | } 34 | 35 | template 36 | T* Resolve(const string& strKey, Args&&... args){ 37 | if (m_creatorMap.find(strKey) == m_creatorMap.end()) 38 | return nullptr; 39 | 40 | Any resolver = m_creatorMap[strKey]; 41 | std::function function = resolver.AnyCast>(); 42 | return function(std::forward(args)...); 43 | } 44 | 45 | template 46 | std::shared_ptr ResolveShared(const string& strKey, Args&&... args){ 47 | T* t = Resolve(strKey, std::forward(args)...); 48 | return std::shared_ptr(t); 49 | } 50 | 51 | private: 52 | void RegisterType(const string& strKey, Any&& constructor){ 53 | if (m_creatorMap.find(strKey) != m_creatorMap.end()) 54 | throw std::invalid_argument("this key has already exist!"); 55 | 56 | //通过Any擦除了不同类型的构造器 57 | m_creatorMap.emplace(strKey, constructor); 58 | } 59 | 60 | private: 61 | unordered_map m_creatorMap; 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /Ioc/Any.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct Any 8 | { 9 | Any(void) : m_tpIndex(std::type_index(typeid(void))) {} 10 | Any(const Any& that) : m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {} 11 | Any(Any && that) : m_ptr(std::move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {} 12 | 13 | //创建智能指针时,对于一般的类型,通过std::decay来移除引用和cv符,从而获取原始类型 14 | template::type, Any>::value, U>::type> Any(U && value) : m_ptr(new Derived < typename std::decay::type>(std::forward(value))), 15 | m_tpIndex(std::type_index(typeid(typename std::decay::type))){} 16 | 17 | bool IsNull() const { return !bool(m_ptr); } 18 | 19 | template bool Is() const 20 | { 21 | return m_tpIndex == std::type_index(typeid(U)); 22 | } 23 | 24 | //将Any转换为实际的类型 25 | template 26 | U& AnyCast() 27 | { 28 | if (!Is()) 29 | { 30 | std::cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << std::endl; 31 | throw std::logic_error{"bad cast"}; 32 | } 33 | 34 | auto derived = dynamic_cast*> (m_ptr.get()); 35 | return derived->m_value; 36 | } 37 | 38 | Any& operator=(const Any& a) 39 | { 40 | if (m_ptr == a.m_ptr) 41 | return *this; 42 | 43 | m_ptr = a.Clone(); 44 | m_tpIndex = a.m_tpIndex; 45 | return *this; 46 | } 47 | 48 | Any& operator=(Any&& a) 49 | { 50 | if (m_ptr == a.m_ptr) 51 | return *this; 52 | 53 | m_ptr = std::move(a.m_ptr); 54 | m_tpIndex = a.m_tpIndex; 55 | return *this; 56 | } 57 | 58 | private: 59 | struct Base; 60 | typedef std::unique_ptr BasePtr; 61 | 62 | struct Base 63 | { 64 | virtual ~Base() {} 65 | virtual BasePtr Clone() const = 0; 66 | }; 67 | 68 | template 69 | struct Derived : Base 70 | { 71 | template 72 | Derived(U && value) : m_value(std::forward(value)) { } 73 | 74 | BasePtr Clone() const 75 | { 76 | return BasePtr(new Derived(m_value)); 77 | } 78 | 79 | T m_value; 80 | }; 81 | 82 | BasePtr Clone() const 83 | { 84 | if (m_ptr != nullptr) 85 | return m_ptr->Clone(); 86 | 87 | return nullptr; 88 | } 89 | 90 | BasePtr m_ptr; 91 | std::type_index m_tpIndex; 92 | }; 93 | -------------------------------------------------------------------------------- /MessageBus/Any.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Define.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct Any{ 10 | Any(void) : m_tpIndex(std::type_index(typeid(void))) {} 11 | Any(const Any& that) : m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {} 12 | Any(Any && that) noexcept : m_ptr(std::move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {} 13 | 14 | //创建智能指针时,对于一般的类型,通过std::decay来移除引用和cv符,从而获取原始类型 15 | template::type, Any>::value, U>::type> Any(U && value) 16 | : m_ptr(new Derived < typename std::decay::type>(std::forward(value))),m_tpIndex(std::type_index(typeid(typename std::decay::type))){} 17 | 18 | bool IsNull() const { 19 | return !bool(m_ptr); 20 | } 21 | 22 | template 23 | bool Is() const{ 24 | return m_tpIndex == std::type_index(typeid(U)); 25 | } 26 | 27 | //将Any转换为实际的类型 28 | template 29 | U& AnyCast(){ 30 | if (!Is()){ 31 | std::cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << std::endl; 32 | throw std::logic_error{"bad cast"}; 33 | } 34 | 35 | auto derived = dynamic_cast*> (m_ptr.get()); 36 | return derived->m_value; 37 | } 38 | 39 | Any& operator=(const Any& a){ 40 | if (m_ptr == a.m_ptr) 41 | return *this; 42 | 43 | m_ptr = a.Clone(); 44 | m_tpIndex = a.m_tpIndex; 45 | return *this; 46 | } 47 | 48 | Any& operator=(Any&& a){ 49 | if (m_ptr == a.m_ptr) 50 | return *this; 51 | 52 | m_ptr = std::move(a.m_ptr); 53 | m_tpIndex = a.m_tpIndex; 54 | return *this; 55 | } 56 | 57 | private: 58 | struct Base; 59 | typedef std::unique_ptr BasePtr; 60 | 61 | struct Base{ 62 | virtual ~Base() = default; 63 | virtual BasePtr Clone() const = 0; 64 | }; 65 | 66 | template 67 | struct Derived : Base{ 68 | template 69 | Derived(U && value) : m_value(std::forward(value)) { } 70 | 71 | BasePtr Clone() const override { 72 | return BasePtr(new Derived(m_value)); 73 | } 74 | 75 | T m_value; 76 | }; 77 | 78 | BasePtr Clone() const{ 79 | if (m_ptr != nullptr) 80 | return m_ptr->Clone(); 81 | 82 | return nullptr; 83 | } 84 | 85 | BasePtr m_ptr; 86 | std::type_index m_tpIndex; 87 | }; 88 | 89 | -------------------------------------------------------------------------------- /ThreadLockFreeStack/LockFreeStack2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | 使用无锁std::shared_ptr<>的实现:std::atomic_is_lock_free(&some_shared_ptr)返回true 10 | */ 11 | 12 | template 13 | class LockFreeStack 14 | { 15 | private: 16 | struct node 17 | { 18 | std::shared_ptr data; 19 | std::shared_ptr next; 20 | node(T const& data_) : 21 | data(std::make_shared(data_)) 22 | {} 23 | }; 24 | std::shared_ptr head; 25 | public: 26 | void push(T const& data) 27 | { 28 | std::shared_ptr const new_node = std::make_shared(data); 29 | new_node->next = head; 30 | while (!std::atomic_compare_exchange_weak( 31 | &head, &new_node->next, new_node)); 32 | } 33 | std::shared_ptr pop() 34 | { 35 | std::shared_ptr old_head = std::atomic_load(&head); 36 | while (old_head && !std::atomic_compare_exchange_weak( 37 | &head, &old_head, old_head->next)); 38 | return old_head ? old_head->data : std::shared_ptr(); 39 | } 40 | }; 41 | 42 | void PushThreadFun(LockFreeStack& stack) { 43 | static thread_local int i = 1; 44 | std::random_device r; 45 | std::default_random_engine e(r()); 46 | std::uniform_int_distribution uniform_dist(1, 3); 47 | while (1) { 48 | std::cout << "PushThreadFun id:" << std::this_thread::get_id()<<" value:"<& stack) { 55 | while (1) { 56 | auto res = stack.pop(); 57 | if (res.get() != nullptr) { 58 | std::cout << "GetThreadFun id:" << std::this_thread::get_id() << " value:" << *res << std::endl; 59 | } 60 | } 61 | } 62 | 63 | int main() 64 | { 65 | LockFreeStack stack; 66 | std::thread pushT1(PushThreadFun,std::ref(stack)); 67 | std::thread pushT2(PushThreadFun, std::ref(stack)); 68 | std::thread getT1(GetThreadFun, std::ref(stack)); 69 | std::thread getT2(GetThreadFun, std::ref(stack)); 70 | 71 | pushT1.join(); 72 | pushT2.join(); 73 | getT1.join(); 74 | getT2.join(); 75 | std::cout << "Hello World!\n"; 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /Ioc/Ioc_17.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "NonCopyable.hpp" 8 | 9 | using namespace std; 10 | 11 | class IocContainer : NonCopyable 12 | { 13 | public: 14 | IocContainer() = default; 15 | ~IocContainer() = default; 16 | 17 | template 18 | typename std::enable_if::value>::type RegisterType(const string& strKey){ 19 | std::function function = [](Args&&... args){ return new T(new Depend(std::forward(args)...)); };//通过闭包擦除了参数类型 20 | RegisterType(strKey, std::move(function)); 21 | } 22 | 23 | template 24 | typename std::enable_if::value>::type RegisterType(const string& strKey){ 25 | std::function function = [](Args&&... args){ return new Depend(std::forward(args)...); }; 26 | RegisterType(strKey, std::move(function)); 27 | } 28 | 29 | template 30 | void RegisterSimple(const string& strKey){ 31 | std::function function = [](Args&&... args){return new T(std::forward(args)...);}; 32 | RegisterType(strKey,std::move(function)); 33 | } 34 | 35 | template 36 | T* Resolve(const string& strKey, Args&&... args){ 37 | if (m_creatorMap.find(strKey) == m_creatorMap.end()) 38 | return nullptr; 39 | 40 | std::any resolver = m_creatorMap[strKey]; 41 | std::function function = std::any_cast>(resolver); 42 | return function(std::forward(args)...); 43 | } 44 | 45 | template 46 | std::shared_ptr ResolveShared(const string& strKey, Args&&... args){ 47 | T* t = Resolve(strKey, std::forward(args)...); 48 | return std::shared_ptr(t); 49 | } 50 | 51 | private: 52 | void RegisterType(const string& strKey, std::any&& constructor){ 53 | if (m_creatorMap.find(strKey) != m_creatorMap.end()) 54 | throw std::invalid_argument("this key has already exist!"); 55 | 56 | //通过Any擦除了不同类型的构造器 57 | m_creatorMap.emplace(strKey, constructor); 58 | } 59 | 60 | private: 61 | unordered_map m_creatorMap; 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /MessageBus/MessageBus.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "Define.h" 7 | 8 | #if __CPP17 9 | #include 10 | #else 11 | #include "Any.hpp" 12 | #endif 13 | 14 | #include "function_traits.hpp" 15 | #include "NonCopyable.hpp" 16 | 17 | using namespace std; 18 | 19 | class MessageBus: NonCopyable{ 20 | public: 21 | //注册消息 22 | template 23 | void Attach(F&& f, const string& strTopic=""){ 24 | auto func = to_function(std::forward(f)); 25 | Add(strTopic, std::move(func)); 26 | } 27 | 28 | //发送消息 是下面发消息函数的特化版本 29 | template 30 | void SendReq(const string& strTopic = ""){ 31 | using function_type = std::function; 32 | string strMsgType =strTopic+ typeid(function_type).name(); 33 | auto range = m_map.equal_range(strMsgType); 34 | for (auto it = range.first; it != range.second; ++it){ 35 | #if __CPP17 36 | auto f = std::any_cast(it->second); 37 | #else 38 | auto f = it->second.AnyCast < function_type >(); 39 | #endif 40 | f(); 41 | } 42 | } 43 | template 44 | void SendReq(Args&&... args, const string& strTopic = ""){ 45 | using function_type = std::function; 46 | string strMsgType =strTopic+ typeid(function_type).name(); 47 | auto range = m_map.equal_range(strMsgType); 48 | for (auto it = range.first; it != range.second; ++it){ 49 | #if __CPP17 50 | auto f = std::any_cast(it->second); 51 | #else 52 | auto f = it->second.AnyCast < function_type >(); 53 | #endif 54 | f(std::forward(args)...); 55 | } 56 | } 57 | 58 | //移除某个主题, 需要主题和消息类型 59 | template 60 | void Remove(const string& strTopic = ""){ 61 | using function_type = std::function; //typename function_traits::stl_function_type; 62 | 63 | string strMsgType =strTopic +typeid(function_type).name(); 64 | int count = m_map.count(strMsgType); 65 | auto range = m_map.equal_range(strMsgType); 66 | m_map.erase(range.first, range.second); 67 | } 68 | 69 | private: 70 | template 71 | void Add(const string& strTopic, F&& f){ 72 | string strMsgType = strTopic + typeid(F).name(); 73 | m_map.emplace(std::move(strMsgType), std::forward(f)); 74 | } 75 | 76 | private: 77 | #if __CPP17 78 | std::multimap m_map; 79 | #else 80 | std::multimap m_map; 81 | #endif 82 | }; 83 | -------------------------------------------------------------------------------- /Ioc/main.cpp: -------------------------------------------------------------------------------- 1 | #ifndef __CPP17 2 | #if __cplusplus > 201402L 3 | # define __CPP17 (1) 4 | #else 5 | # define __CPP17 (0) 6 | #endif 7 | #endif 8 | 9 | #ifndef __CPP14 10 | #if __cplusplus > 201103L 11 | # define __CPP14 (1) 12 | #else 13 | # define __CPP14 (0) 14 | #endif 15 | #endif 16 | 17 | #ifndef __CPP11 18 | #if __cplusplus > 199711L 19 | # define __CPP11 (1) 20 | #else 21 | # define __CPP11 (0) 22 | #endif 23 | #endif 24 | 25 | #if __CPP17 26 | #include "Ioc_17.hpp" 27 | #elif __CPP11 28 | #include "Ioc_11.hpp" 29 | #endif 30 | 31 | #include 32 | using namespace std; 33 | 34 | /*test code*/ 35 | //测试继承对象 36 | struct Base 37 | { 38 | virtual void Func(){} 39 | virtual ~Base(){} 40 | }; 41 | 42 | struct DerivedB : public Base 43 | { 44 | DerivedB(int a, double b):m_a(a),m_b(b) 45 | { 46 | } 47 | void Func()override 48 | { 49 | cout<<"DerivedB::Fun()::"<Func(); 73 | } 74 | 75 | ~A() 76 | { 77 | if(m_ptr!=nullptr) 78 | { 79 | delete m_ptr; 80 | m_ptr = nullptr; 81 | } 82 | } 83 | 84 | private: 85 | Base * m_ptr; 86 | }; 87 | 88 | //测试普通对象 89 | struct Bus 90 | { 91 | void Func() const { std::cout <<"Bus::Func()"<("C"); //配置依赖关系 103 | ioc.RegisterType("B"); //注册时要注意DerivedB的参数int和double 104 | 105 | //注册普通对象 106 | ioc.RegisterSimple("Bus"); 107 | ioc.RegisterSimple("Car"); 108 | 109 | auto c = ioc.ResolveShared("C"); 110 | c->Func(); 111 | auto b = ioc.ResolveShared("B", 1, 2.0); //还要传入参数 112 | b->Func(); 113 | 114 | auto bus = ioc.ResolveShared("Bus"); 115 | bus->Func(); 116 | auto car = ioc.ResolveShared("Car"); 117 | car->Func(); 118 | 119 | } 120 | 121 | int main() { 122 | TestIoc(); 123 | 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /AOP/Aspect.hpp: -------------------------------------------------------------------------------- 1 | _Pragma("once") 2 | 3 | #define HAS_MEMBER(member)\ 4 | template \ 5 | struct has_member_##member\ 6 | {\ 7 | private:\ 8 | template \ 9 | static auto Check(int) -> decltype(std::declval().member(std::declval()...), std::true_type()); \ 10 | template \ 11 | static std::false_type Check(...);\ 12 | public:\ 13 | enum{value = std::is_same(0)), std::true_type>::value};\ 14 | };\ 15 | 16 | HAS_MEMBER(Before) 17 | HAS_MEMBER(After) 18 | 19 | class NonCopyable{ 20 | public: 21 | NonCopyable(const NonCopyable&) = delete; // deleted 22 | NonCopyable& operator = (const NonCopyable&) = delete; // deleted 23 | NonCopyable() = default; // available 24 | }; 25 | 26 | template 27 | struct Aspect : NonCopyable 28 | { 29 | Aspect(Func&& f) : m_func(std::forward(f)) 30 | { 31 | } 32 | 33 | template 34 | typename std::enable_if::value&&has_member_After::value>::type Invoke(Args&&... args, T&& aspect) 35 | { 36 | aspect.Before(std::forward(args)...);//核心逻辑之前的切面逻辑 37 | m_func(std::forward(args)...);//核心逻辑 38 | aspect.After(std::forward(args)...);//核心逻辑之后的切面逻辑 39 | } 40 | 41 | template 42 | typename std::enable_if::value&&!has_member_After::value>::type Invoke(Args&&... args, T&& aspect) 43 | { 44 | aspect.Before(std::forward(args)...);//核心逻辑之前的切面逻辑 45 | m_func(std::forward(args)...);//核心逻辑 46 | } 47 | 48 | template 49 | typename std::enable_if::value&&has_member_After::value>::type Invoke(Args&&... args, T&& aspect) 50 | { 51 | m_func(std::forward(args)...);//核心逻辑 52 | aspect.After(std::forward(args)...);//核心逻辑之后的切面逻辑 53 | } 54 | 55 | template 56 | void Invoke(Args&&... args, Head&&headAspect, Tail&&... tailAspect) 57 | { 58 | headAspect.Before(std::forward(args)...); 59 | Invoke(std::forward(args)..., std::forward(tailAspect)...); 60 | headAspect.After(std::forward(args)...); 61 | } 62 | 63 | private: 64 | Func m_func; //被织入的函数 65 | }; 66 | 67 | //AOP的辅助函数,简化调用 68 | template 69 | void Invoke(Func&&f, Args&&... args){ 70 | Aspect asp(std::forward(f)); 71 | asp.Invoke(std::forward(args)..., AP()...); 72 | } -------------------------------------------------------------------------------- /ThreadPool/ThreadPool1/ThreadPool.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __THREAD_POOL__ 2 | #define __THREAD_POOL__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "SyncQueue.hpp" 11 | 12 | const int MaxTaskCount = 100; 13 | 14 | template 15 | class ThreadPool { 16 | public: 17 | using Task = std::function; 18 | 19 | public: 20 | ThreadPool(int numThreads = std::thread::hardware_concurrency()) : m_queue(MaxTaskCount) { 21 | Start(numThreads); 22 | } 23 | ~ThreadPool(void) { 24 | // stop thread pool 25 | Stop(); 26 | } 27 | void Stop() { 28 | // only invoke once StopThreadGroup 29 | std::call_once(m_flag, [this] {StopThreadGroup(); }); 30 | } 31 | 32 | public: 33 | void AddTask(Task&& task) { 34 | m_queue.Put(std::forward(task)); 35 | } 36 | void AddTask(const Task& task) { 37 | m_queue.Put(task); 38 | } 39 | 40 | template 41 | void AddTask(Fun&& f, Arg&& arg,Args&&... args) { 42 | auto f_task = std::bind(std::forward(f), std::forward(arg),std::forward(args)...); 43 | m_queue.Put(std::move(f_task)); 44 | } 45 | public: 46 | void Start(int numThreads) { 47 | m_running = true; 48 | // create thread group 49 | for (int i = 0; i < numThreads; ++i) { 50 | m_threadgroup.push_back(std::make_shared(&ThreadPool::RunInThread, this)); 51 | } 52 | } 53 | 54 | void RunInThread() { 55 | while (m_running) { 56 | // detach all task 57 | std::list list; 58 | m_queue.Take(list); 59 | for (auto& task : list) { 60 | if (!m_running) 61 | return; 62 | task(); 63 | } 64 | } 65 | } 66 | void StopThreadGroup() { 67 | m_queue.Stop(); //let thread stop of syncqueue 68 | m_running = false; // set thread status 69 | for (auto thread : m_threadgroup) { 70 | if (thread) 71 | thread->join(); 72 | } 73 | m_threadgroup.clear(); 74 | } 75 | 76 | private: 77 | std::list> m_threadgroup; // thread group 78 | SyncQueue m_queue; // sync queue 79 | atomic_bool m_running; // thread status 80 | std::once_flag m_flag; 81 | }; 82 | 83 | 84 | #endif // !__THREAD_POOL__ 85 | 86 | -------------------------------------------------------------------------------- /MessageBus/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "MessageBus.hpp" 5 | 6 | MessageBus g_bus; 7 | const string Topic = "Drive"; 8 | const string CallBackTopic = "DriveOk"; 9 | 10 | //TEST CODE 11 | struct Subject{ 12 | Subject(){ 13 | g_bus.Attach([this]{DriveOk();},CallBackTopic); 14 | } 15 | void SendReq(const string& topic){ 16 | g_bus.SendReq(50, topic); 17 | } 18 | void DriveOk(){ 19 | cout<<"drive ok"<(CallBackTopic); 29 | } 30 | }; 31 | struct Bus{ 32 | Bus(){ 33 | g_bus.Attach([this](int speed){Drive(speed);}); 34 | } 35 | void Drive(int speed){ 36 | cout << "Bus drive " << speed << endl; 37 | g_bus.SendReq(CallBackTopic); 38 | } 39 | }; 40 | struct Truck{ 41 | Truck(){ 42 | g_bus.Attach([this](int speed){Drive(speed);}); 43 | } 44 | void Drive(int speed){ 45 | cout << "Truck drive " << speed << endl; 46 | g_bus.SendReq(CallBackTopic); 47 | } 48 | }; 49 | 50 | void TestBus(){ 51 | Subject subject; 52 | Car car; 53 | Bus bus; 54 | Truck truck; 55 | subject.SendReq(Topic); 56 | subject.SendReq(""); 57 | } 58 | 59 | //TEST CODE 60 | void TestMsgBus(){ 61 | MessageBus bus; 62 | // 注册消息 63 | bus.Attach([](int a){cout << "no reference" << a << endl; }); 64 | bus.Attach([](int& a){cout << "lvalue reference" << a << endl; }); 65 | bus.Attach([](int&& a){cout << "rvalue reference" << a << endl; }); 66 | bus.Attach([](const int& a){cout << "const lvalue reference" << a << endl; }); 67 | bus.Attach([](int a){cout << "no reference has return value and key" << a << endl;return a;}, "a"); 68 | int i = 2; 69 | 70 | // 发送消息 71 | bus.SendReq(2); 72 | bus.SendReq(2, "a"); 73 | bus.SendReq( i); 74 | bus.SendReq(2); 75 | bus.SendReq(2); 76 | 77 | // 移除消息 78 | bus.Remove(); 79 | bus.Remove("a"); 80 | bus.Remove(); 81 | bus.Remove(); 82 | bus.Remove(); 83 | 84 | // 发送消息 85 | bus.SendReq(2); 86 | bus.SendReq(2, "a"); 87 | bus.SendReq(i); 88 | bus.SendReq(2); 89 | bus.SendReq(2); 90 | } 91 | 92 | int main() { 93 | TestBus(); 94 | std::cout<<"----------------------------"< 3 | #include 4 | #include "Define.h" 5 | //普通函数. 6 | //函数指针. 7 | //function/lambda. 8 | //成员函数. 9 | //函数对象. 10 | 11 | //转换为std::function和函数指针. 12 | template 13 | struct function_traits; 14 | 15 | //普通函数. 16 | template 17 | struct function_traits{ 18 | public: 19 | enum { arity = sizeof...(Args) }; 20 | typedef Ret function_type(Args...); 21 | typedef Ret return_type; 22 | using stl_function_type = std::function; 23 | typedef Ret(*pointer)(Args...); 24 | 25 | template 26 | struct args{ 27 | static_assert(I < arity, "index is out of range, index must less than sizeof Args"); 28 | using type = typename std::tuple_element>::type; 29 | }; 30 | 31 | # if __CPP14 32 | using tuple_type = std::tuple>...>; 33 | using bare_tuple_type = std::tuple>...>; 34 | #elif __CPP11 35 | using tuple_type = std::tuple::type>::type...>; 36 | using bare_tuple_type = std::tuple::type >::type...>; 37 | #endif 38 | }; 39 | 40 | //函数指针. 41 | template 42 | struct function_traits : function_traits{}; 43 | 44 | //std::function. 45 | template 46 | struct function_traits> : function_traits{}; 47 | 48 | //member function. 49 | #define FUNCTION_TRAITS(...)\ 50 | template \ 51 | struct function_traits : function_traits{};\ 52 | 53 | FUNCTION_TRAITS() 54 | FUNCTION_TRAITS(const) 55 | FUNCTION_TRAITS(volatile) 56 | FUNCTION_TRAITS(const volatile) 57 | 58 | //函数对象. 59 | template 60 | struct function_traits : function_traits{}; 61 | 62 | template 63 | typename function_traits::stl_function_type to_function(const Function& lambda){ 64 | return static_cast::stl_function_type>(lambda); 65 | } 66 | 67 | template 68 | typename function_traits::stl_function_type to_function(Function&& lambda){ 69 | return static_cast::stl_function_type>(std::forward(lambda)); 70 | } 71 | 72 | template 73 | typename function_traits::pointer to_function_pointer(const Function& lambda){ 74 | return static_cast::pointer>(lambda); 75 | } 76 | -------------------------------------------------------------------------------- /OrderedMap/OrderedMap.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Administrator on 2022/9/27. 3 | // 4 | 5 | #ifndef ORDEREDMAP_H 6 | #define ORDEREDMAP_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | template 15 | class OrderedMapHandle 16 | { 17 | public: 18 | using key_type = typename KEY_FUNC::result_type; 19 | 20 | private: 21 | static_assert(std::is_pointer::value, "V is not pointer"); 22 | static_assert(std::is_same::value, "V is not same KEY_FUNC argument_type"); 23 | static_assert(std::is_same::value, "V is not same COMPARE_FUNC first argument_type"); 24 | static_assert(std::is_same::value, "V is not same COMPARE_FUNC second argument_type"); 25 | 26 | public: 27 | OrderedMapHandle() = default; 28 | ~OrderedMapHandle() = default; 29 | 30 | public: 31 | bool Insert(V value) 32 | { 33 | auto ret = map_.emplace(KEY_FUNC()(value), std::make_pair(value, list_.end())); 34 | if(!ret.second) 35 | { 36 | return false; 37 | } 38 | ret.first->second.second = list_.emplace(std::find_if(list_.begin(), list_.end(), std::bind(COMPARE_FUNC(), value, std::placeholders::_1)), value); 39 | return true; 40 | } 41 | 42 | void Erase(const key_type key) 43 | { 44 | auto it = map_.find(key); 45 | if(it != map_.end()) 46 | { 47 | list_.erase(it->second.second); 48 | map_.erase(it); 49 | } 50 | } 51 | 52 | template 53 | void Foreach(FUNC&& func) 54 | { 55 | for(auto it = list_.begin(); it != list_.end(); ++it) 56 | { 57 | func(*it); 58 | } 59 | } 60 | 61 | template 62 | void ForeachRemove(FUNC&& func) 63 | { 64 | for(auto it = list_.begin(); it != list_.end();) 65 | { 66 | auto iter_cur = it++; 67 | auto* value = *iter_cur; 68 | if(!func(value)) 69 | { 70 | break; 71 | } 72 | this->Erase(KEY_FUNC()(value)); 73 | } 74 | } 75 | 76 | private: 77 | std::list list_; 78 | CONTAINER map_; 79 | }; 80 | 81 | template 82 | using OrderedMap = OrderedMapHandle::iterator> >, V, KEY_FUNC, COMPARE_FUNC>; 83 | 84 | template 85 | using OrderedHashMap = OrderedMapHandle::iterator> >, V, KEY_FUNC, COMPARE_FUNC>; 86 | 87 | #endif //ORDEREDMAP_H 88 | -------------------------------------------------------------------------------- /ThreadSafeQueue/ThreadSafeQueue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | use c++ 11 10 | */ 11 | 12 | template 13 | class ThreadsafeQueue 14 | { 15 | private: 16 | std::mutex mut; 17 | std::queue data_queue; 18 | std::condition_variable data_cond; 19 | public: 20 | ThreadsafeQueue() 21 | {} 22 | ThreadsafeQueue(ThreadsafeQueue const& other) 23 | { 24 | std::lock_guard lk(other.mut); 25 | data_queue = other.data_queue; 26 | } 27 | 28 | void push(T new_value) 29 | { 30 | std::lock_guard lk(mut); 31 | data_queue.push(new_value); 32 | data_cond.notify_one(); 33 | } 34 | 35 | void wait_and_pop(T& value) 36 | { 37 | std::unique_lock lk(mut); 38 | data_cond.wait(lk, [this] {return !data_queue.empty(); }); 39 | value = data_queue.front(); 40 | data_queue.pop(); 41 | } 42 | 43 | std::shared_ptr wait_and_pop() 44 | { 45 | std::unique_lock lk(mut); 46 | data_cond.wait(lk, [this] {return !data_queue.empty(); }); 47 | std::shared_ptr res(std::make_shared(data_queue.front())); 48 | data_queue.pop(); 49 | return res; 50 | } 51 | 52 | bool try_pop(T& value) 53 | { 54 | std::lock_guard lk(mut); 55 | if (data_queue.empty) 56 | return false; 57 | value = data_queue.front(); 58 | data_queue.pop(); 59 | } 60 | 61 | std::shared_ptr try_pop() 62 | { 63 | std::lock_guard lk(mut); 64 | if (data_queue.empty()) 65 | return std::shared_ptr(); 66 | std::shared_ptr res(std::make_shared(data_queue.front())); 67 | data_queue.pop(); 68 | return res; 69 | } 70 | 71 | bool empty() const 72 | { 73 | std::lock_guard lk(mut); 74 | return data_queue.empty(); 75 | } 76 | }; 77 | 78 | //test 79 | void PrepareData(ThreadsafeQueue& queue) { 80 | while (true) { 81 | static int i = 1; 82 | std::cout << "threadid=" << std::this_thread::get_id() << " push:i=" << i << std::endl; 83 | queue.push(i++); 84 | std::this_thread::sleep_for(std::chrono::seconds(1)); 85 | } 86 | } 87 | 88 | void ProcessData(ThreadsafeQueue& queue) { 89 | while (true) { 90 | int i = 0; 91 | queue.wait_and_pop(i); 92 | std::cout << "threadid=" << std::this_thread::get_id << " wait_and_pop:i=" << i << std::endl; 93 | std::this_thread::sleep_for(std::chrono::seconds(1)); 94 | } 95 | } 96 | 97 | int main() 98 | { 99 | ThreadsafeQueue queue; 100 | 101 | std::thread t1(PrepareData,std::ref(queue)); 102 | std::thread t2(ProcessData, std::ref(queue)); 103 | t1.join(); 104 | t2.join(); 105 | } 106 | 107 | 108 | -------------------------------------------------------------------------------- /ThreadPool/ThreadPool1/SyncQueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SYNC_QUEUE__ 2 | #define __SYNC_QUEUE__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | template 12 | class SyncQueue { 13 | public: 14 | SyncQueue(int maxSize) :m_maxSize(maxSize), m_needStop(false) {} 15 | void Put(const T& x) { 16 | Add(x); 17 | } 18 | void Put(T&& x) { 19 | Add(std::forward(x)); 20 | } 21 | 22 | void Take(std::list& list) { 23 | std::unique_lock locker(m_mutex); 24 | m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); }); 25 | if (m_needStop) 26 | return; 27 | list = std::move(m_queue); 28 | m_notFull.notify_one(); 29 | } 30 | void Take(T& t){ 31 | std::unique_lock locker(m_mutex); 32 | m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); }); 33 | if (m_needStop) 34 | return; 35 | t = m_queue.front(); 36 | m_queue.pop_front(); 37 | m_notFull.notify_one(); 38 | } 39 | void Stop(){ 40 | { 41 | std::lock_guard locker(m_mutex); 42 | m_needStop = true; 43 | } 44 | m_notFull.notify_all(); 45 | m_notEmpty.notify_all(); 46 | } 47 | bool Empty(){ 48 | std::lock_guard locker(m_mutex); 49 | return m_queue.empty(); 50 | } 51 | bool Full(){ 52 | std::lock_guard locker(m_mutex); 53 | return m_queue.size() == m_maxSize; 54 | } 55 | size_t Size(){ 56 | std::lock_guard locker(m_mutex); 57 | return m_queue.size(); 58 | } 59 | int Count(){ 60 | return m_queue.size(); 61 | } 62 | private: 63 | bool NotFull() const{ 64 | bool full = m_queue.size() >= m_maxSize; 65 | //if (full) 66 | // cout << "cache full,need wait..." << endl; 67 | return !full; 68 | } 69 | bool NotEmpty() const{ 70 | bool empty = m_queue.empty(); 71 | //if (empty) 72 | // cout << "cache empty,need wait..., thread id: " << std::this_thread::get_id() << endl; 73 | return !empty; 74 | } 75 | template 76 | void Add(F&& x){ 77 | std::unique_lock< std::mutex> locker(m_mutex); 78 | m_notFull.wait(locker, [this] {return m_needStop || NotFull(); }); 79 | if (m_needStop) 80 | return; 81 | m_queue.push_back(std::forward(x)); 82 | m_notEmpty.notify_one(); 83 | } 84 | private: 85 | std::list m_queue; // cache 86 | std::mutex m_mutex; // lock 87 | std::condition_variable m_notEmpty; // not empty condition variable 88 | std::condition_variable m_notFull; // not full condition variable 89 | unsigned int m_maxSize; // syncqueue max size 90 | bool m_needStop; // thread status 91 | }; 92 | 93 | #endif // !__SYNC_QUEUE__ -------------------------------------------------------------------------------- /timer/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | #include "TimerMgr.h" 7 | 8 | struct TestA 9 | { 10 | int count = 0; 11 | }; 12 | 13 | void Test1() 14 | { 15 | auto now = time(nullptr); 16 | INIT_TIMERMGR(timerMgr, now * 1000, 1); 17 | 18 | std::string* user = new std::string("test"); 19 | 20 | TestA test; 21 | TestA testFirst; 22 | 23 | auto f = [](void* data, void* user){ 24 | TestA* dataTmp = (TestA*)data; 25 | std::cout<<"count=" << ++dataTmp->count << " time="<= 5) 90 | { 91 | UNREG_TIMER(timerMgr, timerId); 92 | break; 93 | } 94 | } 95 | 96 | UNINIT_TIMERMGR(timerMgr); 97 | 98 | delete user; 99 | } 100 | 101 | void TestFun(void* data, void* user) 102 | { 103 | A* dataTmp = (A*)data; 104 | std::string* userTmp = (std::string*)user; 105 | std::cout<<"count=" << ++dataTmp->count <<" user=" << *userTmp<<" time="< 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | * github:https://github.com/cameron314/concurrentqueue 14 | * 15 | *“单生产者,单消费者”(single-producer,single-consumer SPSC)队列 16 | */ 17 | 18 | template 19 | class LockFreeQueue 20 | { 21 | private: 22 | struct node 23 | { 24 | std::shared_ptr data; 25 | node* next; 26 | node() : 27 | next(nullptr) 28 | {} 29 | }; 30 | std::atomic head; 31 | std::atomic tail; 32 | node* pop_head() 33 | { 34 | node* const old_head = head.load(); 35 | if (old_head == tail.load()) // 1 36 | { 37 | return nullptr; 38 | } 39 | head.store(old_head->next); 40 | return old_head; 41 | } 42 | public: 43 | LockFreeQueue() : 44 | head(new node), tail(head.load()) 45 | {} 46 | LockFreeQueue(const LockFreeQueue& other) = delete; 47 | LockFreeQueue& operator=(const LockFreeQueue& other) = delete; 48 | ~LockFreeQueue() 49 | { 50 | while (node* const old_head = head.load()) 51 | { 52 | head.store(old_head->next); 53 | delete old_head; 54 | } 55 | } 56 | std::shared_ptr pop() 57 | { 58 | node* old_head = pop_head(); 59 | if (!old_head) 60 | { 61 | return std::shared_ptr(); 62 | } 63 | std::shared_ptr const res(old_head->data); 64 | delete old_head; 65 | return res; 66 | } 67 | void push(T new_value) 68 | { 69 | std::shared_ptr new_data(std::make_shared(new_value)); 70 | node* p = new node; 71 | node* const old_tail = tail.load(); 72 | old_tail->data.swap(new_data); 73 | old_tail->next = p; 74 | tail.store(p); 75 | } 76 | }; 77 | 78 | void PushThreadFun(LockFreeQueue& queue) { 79 | static thread_local int i = 1; 80 | std::random_device r; 81 | std::default_random_engine e(r()); 82 | std::uniform_int_distribution uniform_dist(1, 3); 83 | while (1) { 84 | std::cout << "PushThreadFun id:" << std::this_thread::get_id() << " value:" << i << std::endl; 85 | queue.push(i++); 86 | std::this_thread::sleep_for(std::chrono::seconds(uniform_dist(e))); 87 | } 88 | } 89 | 90 | void GetThreadFun(LockFreeQueue& queue) { 91 | while (1) { 92 | auto res = queue.pop(); 93 | if (res.get() != nullptr) { 94 | std::cout << "GetThreadFun id:" << std::this_thread::get_id() << " value:" << *res << std::endl; 95 | } 96 | } 97 | } 98 | 99 | // int main() 100 | // { 101 | // LockFreeQueue queue; 102 | // std::thread pushT(PushThreadFun, std::ref(queue)); 103 | // std::thread getT(GetThreadFun, std::ref(queue)); 104 | 105 | // pushT.join(); 106 | // getT.join(); 107 | // } 108 | 109 | #endif //_LOCK_FREE_QUEUE1__H__ -------------------------------------------------------------------------------- /redis/distribute_lock/distribute_lock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* single redis instance distribute lock of example*/ 13 | 14 | //lua script: http://www.redis.cn/commands/eval.html 15 | 16 | //g++ distribute_lock.cpp -I/usr/include/hiredis/ -L /usr/lib/x86_64-linux-gnu/ -lhiredis -ggdb 17 | 18 | 19 | void Lock(redisReply *reply,redisContext *c , uint32_t& uniqueKey){ 20 | //生成唯一的锁标识符,这里为了简单 就用时间戳代替了 21 | uniqueKey = time(NULL); 22 | 23 | //set lock:books 1 ex 10 nx 24 | stringstream iss; 25 | iss << "set lock:books " << uniqueKey<<" ex 10 nx"; 26 | std::cout<errstr); 30 | }else{ 31 | printf("set lock: %s\n", reply->str); 32 | } 33 | freeReplyObject(reply); 34 | } 35 | 36 | 37 | void Unlock(redisReply *reply,redisContext *c , uint32_t uniqueKey){ 38 | /* lua script*/ 39 | std::string lua = "local del_key = KEYS[1] \ 40 | local del_arg = ARGV[1] \ 41 | if redis.call('get',del_key) == del_arg then \ 42 | return redis.call('del',del_key) \ 43 | else \ 44 | return 0 \ 45 | end"; 46 | 47 | reply = (redisReply*)redisCommand(c,"eval %s 1 %s %d",lua.c_str(),"lock:books",uniqueKey); 48 | if(reply==nullptr){ 49 | printf("del lock: %s\n", c->errstr); 50 | }else{ 51 | printf("del lock: %s\n", reply->str); 52 | } 53 | 54 | freeReplyObject(reply); 55 | 56 | } 57 | 58 | int main(int argc, char **argv) { 59 | unsigned int j, isunix = 0; 60 | redisContext *c; 61 | redisReply *reply; 62 | const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; 63 | 64 | if (argc > 2) { 65 | if (*argv[2] == 'u' || *argv[2] == 'U') { 66 | isunix = 1; 67 | /* in this case, host is the path to the unix socket */ 68 | printf("Will connect to unix socket @%s\n", hostname); 69 | } 70 | } 71 | 72 | int port = (argc > 2) ? atoi(argv[2]) : 6379; 73 | 74 | struct timeval timeout = { 1, 500000 }; // 1.5 seconds 75 | if (isunix) { 76 | c = redisConnectUnixWithTimeout(hostname, timeout); 77 | } else { 78 | c = redisConnectWithTimeout(hostname, port, timeout); 79 | } 80 | if (c == NULL || c->err) { 81 | if (c) { 82 | printf("Connection error: %s\n", c->errstr); 83 | redisFree(c); 84 | } else { 85 | printf("Connection error: can't allocate redis context\n"); 86 | } 87 | exit(1); 88 | } 89 | 90 | /* lock fun in thread */ 91 | uint32_t uniqueKey = 0; 92 | Lock(reply,c,uniqueKey); 93 | 94 | /* unlock fun in up thread*/ 95 | /* this is test fun*/ 96 | Unlock(reply,c,uniqueKey+1); 97 | /* this is real fun*/ 98 | Unlock(reply,c,uniqueKey); 99 | 100 | 101 | /* Disconnects and frees the context */ 102 | redisFree(c); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /ThreadsafeList/ThreadSafeList.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | template 7 | class ThreadsafeList 8 | { 9 | struct node 10 | { 11 | std::mutex m; 12 | std::shared_ptr data; 13 | std::unique_ptr next; 14 | 15 | node() : next(){} 16 | 17 | node(T const& value) : data(std::make_shared(value)) 18 | {} 19 | }; 20 | 21 | node head; 22 | 23 | public: 24 | ThreadsafeList() 25 | {} 26 | 27 | ~ThreadsafeList() 28 | { 29 | remove_if([](T const&) {return true; }); 30 | } 31 | 32 | ThreadsafeList(ThreadsafeList const& other) = delete; 33 | ThreadsafeList& operator=(ThreadsafeList const& other) = delete; 34 | 35 | void push_front(T const& value) 36 | { 37 | std::unique_ptr new_node(new node(value)); 38 | std::lock_guard lk(head.m); 39 | new_node->next = std::move(head.next); 40 | head.next = std::move(new_node); 41 | } 42 | 43 | template 44 | void for_each(Function f) 45 | { 46 | node* current = &head; 47 | std::unique_lock lk(head.m); 48 | while (node* const next = current->next.get()) 49 | { 50 | std::unique_lock next_lk(next->m); 51 | lk.unlock(); 52 | f(*next->data); 53 | current = next; 54 | lk = std::move(next_lk); 55 | } 56 | } 57 | 58 | template 59 | std::shared_ptr find_first_if(Predicate p) 60 | { 61 | node* current = &head; 62 | std::unique_lock lk(head.m); 63 | while (node* const next = current->next.get()) 64 | { 65 | std::unique_lock next_lk(next->m); 66 | lk.unlock(); 67 | if (p(*next->data)) 68 | { 69 | return next->data; 70 | } 71 | current = next; 72 | lk = std::move(next_lk); 73 | } 74 | return std::shared_ptr(); 75 | } 76 | 77 | template 78 | void remove_if(Predicate p) 79 | { 80 | node* current = &head; 81 | std::unique_lock lk(head.m); 82 | while (node* const next = current->next.get()) 83 | { 84 | std::unique_lock next_lk(next->m); 85 | if (p(*next->data)) 86 | { 87 | std::unique_ptr old_next = std::move(current->next); 88 | current->next = std::move(next->next); 89 | next_lk.unlock(); 90 | } 91 | else 92 | { 93 | lk.unlock(); 94 | current = next; 95 | lk = std::move(next_lk); 96 | } 97 | } 98 | } 99 | }; 100 | 101 | 102 | int main() 103 | { 104 | //简单函数功能测试 105 | ThreadsafeList list; 106 | list.push_front(1); 107 | list.for_each([](const int& item) { 108 | std::cout << item << " "; 109 | }); 110 | std::cout << std::endl; 111 | std::shared_ptr ptr=list.find_first_if([](const int& item) {return item == 1; }); 112 | if (ptr.get()!=nullptr) { 113 | std::cout << *ptr << std::endl; 114 | } 115 | } 116 | 117 | 118 | -------------------------------------------------------------------------------- /ObjectPool/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const int MaxObjectNum = 10; 9 | 10 | class NonCopyable{ 11 | protected: 12 | NonCopyable() = default; 13 | virtual ~NonCopyable() = default; 14 | public: 15 | NonCopyable(const NonCopyable&) = delete; // 禁用复制构造 16 | NonCopyable& operator = (const NonCopyable&) = delete; // 禁用赋值构造 17 | }; 18 | 19 | template 20 | class ObjectPool : NonCopyable{ 21 | template 22 | using Constructor = std::function(Args...)>; 23 | using DelType = std::function; 24 | 25 | public: 26 | // 默认创建多少个对象 27 | template 28 | void Init(size_t num, Args&&... args){ 29 | if (num<= 0 || num> MaxObjectNum) 30 | throw std::logic_error("object num out of range."); 31 | auto constructName = typeid(Constructor).name(); // 不区分引用 32 | for (size_t i = 0; i (new T(std::forward(args)...))); 34 | } 35 | } 36 | 37 | // 从对象池中获取一个对象 38 | template 39 | std::unique_ptr Get(){ 40 | string constructName = typeid(Constructor).name(); 41 | auto range = m_object_map.equal_range(constructName); 42 | for (auto it = range.first; it != range.second; ++it){ 43 | std::unique_ptr ptr(it->second.release(), [this,constructName](T* p){ 44 | m_object_map.emplace(constructName,unique_ptr(p)); //删除函数执行的操作 45 | }); 46 | m_object_map.erase(it); 47 | return ptr; 48 | } 49 | return nullptr; 50 | } 51 | 52 | inline size_t Size() const{ 53 | return m_object_map.size(); 54 | } 55 | inline bool empty() const{ 56 | return m_object_map.empty(); 57 | } 58 | private: 59 | unordered_multimap> m_object_map; 60 | }; 61 | 62 | /*-----------------------------*/ 63 | struct BigObject{ 64 | BigObject() = default; 65 | explicit BigObject(int a) {}; 66 | BigObject(const int& a, const int& b){} 67 | void Print(const string& str){ 68 | cout < 73 | void Print(T&& p, const string& str){ 74 | if (p != nullptr){ 75 | p->Print(str); 76 | } 77 | } 78 | 79 | void TestObjPool(){ 80 | ObjectPool pool; 81 | pool.Init(2); // 初始化对象池,初始创建两个对象 82 | { 83 | auto p = pool.Get(); 84 | Print(std::move(p), "p"); 85 | pool.Get(); 86 | std::cout<<"pool.size()="<(); 103 | Print(std::move(p5), "p5"); 104 | } 105 | std::cout<<"pool.size()="< 5 | #include 6 | 7 | using namespace std; 8 | 9 | template 10 | class WordNode 11 | { 12 | template 13 | friend class SensitiveWordsCheck; 14 | 15 | private: 16 | //添加敏感词,如"你是傻子" 添加"你" 17 | bool AddWord(const std::vector& words, uint32_t idx); 18 | 19 | //检查敏感词,如"你是傻子" 20 | bool CheckWords(const std::vector& words, uint32_t& sIdx, uint32_t& eIdx); 21 | 22 | //释放节点资源 23 | void Free(); 24 | 25 | private: 26 | std::unordered_map wordsMap;//子节点 27 | }; 28 | 29 | template 30 | class SensitiveWordsCheck 31 | { 32 | public: 33 | SensitiveWordsCheck() = default; 34 | ~SensitiveWordsCheck();//如果用智能指针就不用写析构函数具体逻辑了啊 35 | 36 | public: 37 | //添加敏感词,如"你是傻子" 38 | bool AddWords(const std::vector& words); 39 | //检查敏感词,如"你是傻子" 40 | bool CheckWords(const std::vector& words, uint32_t& sIdx, uint32_t& eIdx); 41 | 42 | private: 43 | std::unordered_map*/*也可以用智能指针*/> wordsMap;//子森林 44 | }; 45 | 46 | template 47 | bool WordNode::AddWord(const std::vector& words, uint32_t idx) 48 | { 49 | if(idx < words.size() - 1) 50 | { 51 | WordNode*& node = wordsMap[words[++idx]]; 52 | if(node == nullptr) 53 | { 54 | node = new WordNode(); 55 | } 56 | node->AddWord(words,idx); 57 | } 58 | return true; 59 | } 60 | 61 | template 62 | bool WordNode::CheckWords(const std::vector& words, uint32_t &sIdx, uint32_t &eIdx) 63 | { 64 | uint32_t sIdxTmp = sIdx; 65 | if(++sIdxTmp >= words.size()) 66 | { 67 | eIdx = sIdxTmp - 1; 68 | return true; 69 | } 70 | const auto iter = wordsMap.find(words[sIdxTmp]); 71 | if(iter == wordsMap.end()) 72 | { 73 | eIdx = sIdxTmp - 1; 74 | return true; 75 | } 76 | iter->second->CheckWords(words, sIdxTmp, eIdx); 77 | return true; 78 | } 79 | 80 | template 81 | void WordNode::Free() 82 | { 83 | for(auto pair : wordsMap) 84 | { 85 | if(pair.second != nullptr) 86 | { 87 | pair.second->Free(); 88 | delete pair.second; 89 | } 90 | } 91 | } 92 | 93 | template 94 | SensitiveWordsCheck::~SensitiveWordsCheck() 95 | { 96 | for(auto pair : wordsMap) 97 | { 98 | if(pair.second != nullptr) 99 | { 100 | pair.second->Free(); 101 | delete pair.second; 102 | } 103 | } 104 | } 105 | 106 | template 107 | bool SensitiveWordsCheck::AddWords(const std::vector& words) 108 | { 109 | if(!words.empty()) 110 | { 111 | WordNode*& node = wordsMap[words[0]]; 112 | if(node == nullptr) 113 | { 114 | node = new WordNode(); 115 | } 116 | node->AddWord(words, 0); 117 | } 118 | return true; 119 | } 120 | 121 | template 122 | bool SensitiveWordsCheck::CheckWords(const std::vector& words, uint32_t& sIdx, uint32_t& eIdx) 123 | { 124 | eIdx = 0; 125 | for(uint32_t index = sIdx ; index < words.size(); index++) 126 | { 127 | const auto iter = wordsMap.find(words[index]); 128 | if(iter == wordsMap.end()) 129 | { 130 | sIdx++; 131 | continue; 132 | } 133 | return iter->second->CheckWords(words, sIdx, eIdx); 134 | } 135 | return (sIdx != words.size()); 136 | } 137 | 138 | #endif //_SENSITIVE_WORDS_CHECK_H__ -------------------------------------------------------------------------------- /redis/delay_queue/delay_queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* delay queue*/ 13 | 14 | //lua script: http://www.redis.cn/commands/eval.html 15 | 16 | //g++ delay_queue.cpp -I/usr/include/hiredis/ -L /usr/lib/x86_64-linux-gnu/ -lhiredis -ggdb 17 | 18 | void Delay(redisReply *reply,redisContext *c ,const string& msg){ 19 | //序列化工具序列化成字符串 20 | //这里省略了 21 | int32_t delayTime = time(NULL) + 5; 22 | /* add sort set */ 23 | stringstream iss; 24 | iss << "zadd delay-queue " << delayTime<<" " << msg<<"-"<errstr); 29 | } 30 | freeReplyObject(reply); 31 | } 32 | 33 | void GetMsg(redisReply *reply,redisContext *c){ 34 | /* lua script*/ 35 | std::string lua = "local zset_key = KEYS[1] \ 36 | local min_score = 0 \ 37 | local max_score = ARGV[1] \ 38 | local offset = 0 \ 39 | local limit = 1 \ 40 | \ 41 | local status, type = next(redis.call('TYPE', zset_key)) \ 42 | if status ~= nil and status == 'ok' then \ 43 | if type == 'zset' then \ 44 | local list = redis.call('ZRANGEBYSCORE', zset_key, min_score, max_score, 'LIMIT', offset, limit) \ 45 | if list ~= nil and #list > 0 then \ 46 | local value = list[1] \ 47 | redis.call('ZREM', zset_key, value) \ 48 | return value \ 49 | end \ 50 | end \ 51 | end \ 52 | return nil"; 53 | 54 | reply = (redisReply*)redisCommand(c,"eval %s 1 %s %d",lua.c_str(),"delay-queue",time(NULL)); 55 | if(reply==nullptr){ 56 | printf("zget: %s\n", c->errstr); 57 | }else{ 58 | /* get msg */ 59 | printf("zget delay-queue: %s\n", reply->str); 60 | } 61 | 62 | freeReplyObject(reply); 63 | } 64 | 65 | int main(int argc, char **argv) { 66 | unsigned int j, isunix = 0; 67 | redisContext *c; 68 | redisReply *reply; 69 | const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; 70 | 71 | if (argc > 2) { 72 | if (*argv[2] == 'u' || *argv[2] == 'U') { 73 | isunix = 1; 74 | /* in this case, host is the path to the unix socket */ 75 | printf("Will connect to unix socket @%s\n", hostname); 76 | } 77 | } 78 | 79 | int port = (argc > 2) ? atoi(argv[2]) : 6379; 80 | 81 | struct timeval timeout = { 1, 500000 }; // 1.5 seconds 82 | if (isunix) { 83 | c = redisConnectUnixWithTimeout(hostname, timeout); 84 | } else { 85 | c = redisConnectWithTimeout(hostname, port, timeout); 86 | } 87 | if (c == NULL || c->err) { 88 | if (c) { 89 | printf("Connection error: %s\n", c->errstr); 90 | redisFree(c); 91 | } else { 92 | printf("Connection error: can't allocate redis context\n"); 93 | } 94 | exit(1); 95 | } 96 | 97 | 98 | /* delay queue */ 99 | //one thread push msg 100 | Delay(reply,c,"test"); 101 | 102 | //another thread get msg 103 | GetMsg(reply,c); 104 | 105 | /* Disconnects and frees the context */ 106 | redisFree(c); 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /Curl/multi_example/CurlMgr.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURL_MGR_H__ 2 | #define __CURL_MGR_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | /** 10 | * @brief multi curl 11 | * curl version 7.58.0 12 | */ 13 | class CurlMgr 14 | { 15 | public: 16 | /** 17 | * @brief request call back 18 | * 19 | */ 20 | using CurlFun = std::function; 21 | 22 | /** 23 | * @brief max request 24 | * 25 | */ 26 | const static uint32_t MAX_REQ_SIZE = 1024; 27 | 28 | /** 29 | * @brief time out, ms 30 | * 31 | */ 32 | const static uint32_t MAX_CURL_TIME_OUT = 5000; 33 | 34 | /** 35 | * @brief curl error 36 | * 37 | */ 38 | enum CurlError 39 | { 40 | CurlError_MultiInitFail = -1, 41 | CurlError_CurlSizeLimit = -2, 42 | CurlError_EasyInitFail = -3, 43 | CurlError_SetOptFail = -4, 44 | CurlError_MultiAddFail = -5, 45 | CurlError_AllocUrlReqFail = -6, 46 | CurlError_Slist_Append = -7 47 | 48 | }; 49 | 50 | public: 51 | CurlMgr(); 52 | ~CurlMgr(); 53 | 54 | public: 55 | /** 56 | * @brief initialize resource 57 | * 58 | * @return int32_t 59 | */ 60 | int32_t Init(); 61 | 62 | /** 63 | * @brief destroy resource 64 | * 65 | */ 66 | void Final(); 67 | 68 | /** 69 | * @brief update, main loop call 70 | * 71 | */ 72 | void Update(); 73 | 74 | /** 75 | * @brief add url request 76 | * 77 | * @param sUrl http url 78 | * @param sPost post data 79 | * @param fResCall request call back 80 | * @param sUserData user data 81 | * @param headers header 82 | * @return int32_t 83 | */ 84 | int32_t AddRequest(const std::string& sUrl, const std::string& sPost, CurlFun&& fResCall, void* sUserData, const char* headers); 85 | private: 86 | /** 87 | * @brief request param 88 | * 89 | */ 90 | struct UrlReq 91 | { 92 | UrlReq(){} 93 | virtual ~UrlReq(){ 94 | if(userPwd != nullptr) 95 | { 96 | free(userPwd); 97 | } 98 | if(headers != nullptr) 99 | { 100 | curl_slist_free_all(headers); 101 | } 102 | if(pCurl != nullptr) 103 | { 104 | curl_easy_cleanup(pCurl); 105 | } 106 | } 107 | 108 | CURL* pCurl = nullptr; 109 | std::string sResult; 110 | CurlFun fCall; 111 | void* sUserData = nullptr; 112 | char* userPwd = nullptr; 113 | struct curl_slist* headers = nullptr; 114 | }; 115 | 116 | /** 117 | * @brief private initialize curl 118 | * 119 | * @param req req param 120 | * @param sUrl http url 121 | * @param sPost post data 122 | * @param headers http header 123 | * @return int32_t 124 | */ 125 | int32_t _InitCurl(UrlReq& req, const std::string& sUrl, const std::string& sPost, const char* headers); 126 | 127 | /** 128 | * @brief This callback function gets called by libcurl as soon as there is data received that needs to be saved. 129 | * For most transfers, this callback gets called many times and each invoke delivers another chunk of data. 130 | * buf points to the delivered data, and the size of that data is nmemb; size is always 1. 131 | * @param buf buf data 132 | * @param size size of nmemb 133 | * @param nmemb mem block 134 | * @param userP Set the userP argument with the CURLOPT_WRITEDATA option. 135 | * @return size_t 136 | */ 137 | static size_t _DataWrite(void* buf, size_t size, size_t nmemb, void* userP); 138 | 139 | private: 140 | using UrlReqMap = std::unordered_map; 141 | using UrlReqMapIter = UrlReqMap::iterator; 142 | 143 | UrlReqMap m_mapReq; 144 | CURLM* m_pMultiHandle = nullptr; 145 | }; 146 | 147 | 148 | #endif -------------------------------------------------------------------------------- /ThreadLockFreeStack/LockFreeStack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class LockFreeStack 10 | { 11 | private: 12 | struct node; 13 | struct counted_node_ptr 14 | { 15 | int external_count{0}; 16 | node* ptr{nullptr}; 17 | }; 18 | struct node 19 | { 20 | std::shared_ptr data; 21 | std::atomic internal_count; 22 | counted_node_ptr next; 23 | node(T const& data_) : 24 | data(std::make_shared(data_)), 25 | internal_count(0) 26 | {} 27 | }; 28 | std::atomic head; 29 | void increase_head_count(counted_node_ptr& old_counter) 30 | { 31 | counted_node_ptr new_counter; 32 | do 33 | { 34 | new_counter = old_counter; 35 | ++new_counter.external_count; 36 | } while (!head.compare_exchange_strong( 37 | old_counter, new_counter, 38 | std::memory_order_acquire, 39 | std::memory_order_relaxed)); 40 | old_counter.external_count = new_counter.external_count; 41 | } 42 | public: 43 | ~LockFreeStack() 44 | { 45 | if (head.load(std::memory_order_relaxed).ptr != nullptr) { 46 | while (pop()); 47 | } 48 | } 49 | void push(T const& data) 50 | { 51 | counted_node_ptr new_node; 52 | new_node.ptr = new node(data); 53 | new_node.external_count = 1; 54 | new_node.ptr->next = head.load(std::memory_order_relaxed); 55 | while (!head.compare_exchange_weak( 56 | new_node.ptr->next, new_node, 57 | std::memory_order_release, 58 | std::memory_order_relaxed)); 59 | } 60 | std::shared_ptr pop() 61 | { 62 | counted_node_ptr old_head = 63 | head.load(std::memory_order_relaxed); 64 | for (;;) 65 | { 66 | increase_head_count(old_head); 67 | node* const ptr = old_head.ptr; 68 | if (!ptr) 69 | { 70 | return std::shared_ptr(); 71 | } 72 | if (head.compare_exchange_strong( 73 | old_head, ptr->next, std::memory_order_relaxed)) 74 | { 75 | std::shared_ptr res; 76 | res.swap(ptr->data); 77 | int const count_increase = old_head.external_count - 2; 78 | if (ptr->internal_count.fetch_add( 79 | count_increase, std::memory_order_release) == -count_increase) 80 | { 81 | delete ptr; 82 | } 83 | return res; 84 | } 85 | else if (ptr->internal_count.fetch_add( 86 | -1, std::memory_order_relaxed) == 1) 87 | { 88 | ptr->internal_count.load(std::memory_order_acquire); 89 | delete ptr; 90 | } 91 | } 92 | } 93 | }; 94 | 95 | void PushThreadFun(LockFreeStack& stack) { 96 | static thread_local int i = 1; 97 | std::random_device r; 98 | std::default_random_engine e(r()); 99 | std::uniform_int_distribution uniform_dist(1, 3); 100 | while (1) { 101 | std::cout << "PushThreadFun id:" << std::this_thread::get_id()<<" value:"<& stack) { 108 | while (1) { 109 | auto res = stack.pop(); 110 | if (res.get() != nullptr) { 111 | std::cout << "GetThreadFun id:" << std::this_thread::get_id() << " value:" << *res << std::endl; 112 | } 113 | } 114 | } 115 | 116 | int main() 117 | { 118 | LockFreeStack stack; 119 | std::thread pushT1(PushThreadFun,std::ref(stack)); 120 | std::thread pushT2(PushThreadFun, std::ref(stack)); 121 | std::thread getT1(GetThreadFun, std::ref(stack)); 122 | std::thread getT2(GetThreadFun, std::ref(stack)); 123 | 124 | pushT1.join(); 125 | pushT2.join(); 126 | getT1.join(); 127 | getT2.join(); 128 | std::cout << "Hello World!\n"; 129 | } 130 | 131 | 132 | -------------------------------------------------------------------------------- /MemoryPool/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | template 12 | class MemPool{ 13 | public: 14 | using CycleFun = std::function; 15 | public: 16 | inline MemPool(){objs_.fill(nullptr);} 17 | virtual ~MemPool() 18 | { 19 | for(auto *&p : objs_) 20 | { 21 | if(p != nullptr) 22 | { 23 | Free(p); 24 | p = nullptr; 25 | } 26 | } 27 | 28 | for(auto *&p : allobjs_) 29 | { 30 | if(p != nullptr) 31 | { 32 | p->empty = true; 33 | p->~T(); 34 | Free(p); 35 | p = nullptr; 36 | } 37 | } 38 | } 39 | 40 | public: 41 | template 42 | inline T* Get(Args&&... args) 43 | { 44 | T* obj = nullptr; 45 | if(count_ == 0) 46 | { 47 | obj = Alloc(std::forward(args)...); 48 | obj->empty = false;//防止构造函数不初始化 49 | obj->index = index_++; 50 | }else 51 | { 52 | -- count_; 53 | //防止构造函数把index初始化 54 | int index = objs_[count_]->index; 55 | obj = new(objs_[count_]) T(std::forward(args)...); 56 | obj->empty = false;//防止构造函数不初始化 57 | obj->index = index; 58 | objs_[count_] = nullptr; 59 | } 60 | 61 | assert(obj->index != -1); 62 | 63 | if(static_cast(index_) >= this->allobjs_.size()){ 64 | this->allobjs_.resize(index_ * 2 + 1); 65 | } 66 | this->allobjs_[obj->index] = obj; 67 | return obj; 68 | } 69 | 70 | inline void Cycle(T* obj) 71 | { 72 | assert(obj != nullptr); 73 | assert(static_cast(obj->index) < allobjs_.size()); 74 | if(count_ < MF) 75 | { 76 | //防止析构函数将index也初始化了 77 | int index = obj->index; 78 | obj->empty = true; 79 | obj->~T(); 80 | obj->index = index; 81 | objs_[count_++] = obj; 82 | allobjs_[obj->index] = nullptr; 83 | }else 84 | { 85 | allobjs_[obj->index] = nullptr; 86 | obj->empty = true; 87 | obj->~T(); 88 | Free(obj); 89 | } 90 | } 91 | 92 | inline T* GetByIndex(int index) const 93 | { 94 | if(index == -1) 95 | { 96 | return nullptr; 97 | } 98 | 99 | if(static_cast(index) < allobjs_.size()) 100 | { 101 | if(allobjs_[index] != nullptr && (!allobjs_[index]->empty)) 102 | { 103 | return allobjs_[index]; 104 | } 105 | } 106 | return nullptr; 107 | } 108 | 109 | private: 110 | template 111 | static inline T* Alloc(Args&&... args) 112 | { 113 | char* p = new char[sizeof(T) + sizeof(int)]; 114 | return new (p) T(std::forward(args)...); 115 | } 116 | 117 | static inline void Free(T* obj) 118 | { 119 | if(obj != nullptr) 120 | { 121 | char* p = reinterpret_cast(obj); 122 | delete [] p; 123 | } 124 | } 125 | private: 126 | int index_ = 0; 127 | int count_ = 0; 128 | std::vector allobjs_; 129 | std::array objs_; 130 | }; 131 | 132 | class A{ 133 | public: 134 | std::string string = ""; 135 | int index = -1; //内存池中初始索引 136 | bool empty = false; 137 | virtual ~A() 138 | { 139 | empty = true; 140 | } 141 | }; 142 | 143 | 144 | int main(){ 145 | MemPool APoll; 146 | { 147 | A* aptr = APoll.Get(); 148 | aptr->string = "test a"; 149 | 150 | A* bptr = APoll.Get(); 151 | aptr->string = "test b"; 152 | 153 | APoll.Cycle(aptr); 154 | APoll.Cycle(bptr); 155 | 156 | A* cptr = APoll.Get(); 157 | aptr->string = "test c"; 158 | APoll.Cycle(cptr); 159 | 160 | std::unique_ptr::CycleFun> dptr(APoll.Get(),[&](A*p){APoll.Cycle(p);}); 161 | dptr->string="test d"; 162 | } 163 | { 164 | A* eptr = APoll.Get(); 165 | eptr->string = "test e"; 166 | APoll.Cycle(eptr); 167 | } 168 | 169 | return 0; 170 | } -------------------------------------------------------------------------------- /ThreadSafeQueue/ThreadSafeQueue2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | use c++ 11 10 | */ 11 | 12 | template 13 | class ThreadsafeQueue 14 | { 15 | private: 16 | struct node 17 | { 18 | std::shared_ptr data; 19 | std::unique_ptr next; 20 | }; 21 | 22 | std::mutex head_mutex; 23 | std::unique_ptr head; 24 | std::mutex tail_mutex; 25 | node* tail; 26 | std::condition_variable data_cond; 27 | 28 | private: 29 | node* get_tail() 30 | { 31 | std::lock_guard tail_lock(tail_mutex); 32 | return tail; 33 | } 34 | 35 | std::unique_ptr pop_head() 36 | { 37 | std::unique_ptr old_head = std::move(head); 38 | head = std::move(old_head->next); 39 | return old_head; 40 | } 41 | 42 | std::unique_lock wait_for_data() 43 | { 44 | std::unique_lock head_lock(head_mutex); 45 | data_cond.wait(head_lock, [&] {return head.get() != get_tail(); }); 46 | return head_lock; 47 | } 48 | 49 | std::unique_ptr wait_pop_head() 50 | { 51 | std::unique_lock head_lock(wait_for_data()); 52 | return pop_head(); 53 | } 54 | 55 | std::unique_ptr wait_pop_head(T& value) 56 | { 57 | std::unique_lock head_lock(wait_for_data()); 58 | value = std::move(*head->data); 59 | return pop_head(); 60 | } 61 | std::unique_ptr try_pop_head() 62 | { 63 | std::lock_guard head_lock(head_mutex); 64 | if (head.get() == get_tail()) 65 | { 66 | return std::unique_ptr(); 67 | } 68 | return pop_head(); 69 | } 70 | 71 | std::unique_ptr try_pop_head(T& value) 72 | { 73 | std::lock_guard head_lock(head_mutex); 74 | if (head.get() == get_tail()) 75 | { 76 | return std::unique_ptr(); 77 | } 78 | value = std::move(*head->data); 79 | return pop_head(); 80 | } 81 | public: 82 | ThreadsafeQueue() :head(new node), tail(head.get()){} 83 | ThreadsafeQueue(const ThreadsafeQueue& other) = delete; 84 | ThreadsafeQueue& operator=(const ThreadsafeQueue& other) = delete; 85 | 86 | std::shared_ptr try_pop() 87 | { 88 | const std::unique_ptr old_head = try_pop_head(); 89 | return old_head ? old_head->data : std::shared_ptr(); 90 | } 91 | bool try_pop(T& value) 92 | { 93 | const std::unique_ptr old_head = try_pop_head(value); 94 | return old_head; 95 | } 96 | std::shared_ptr wait_and_pop() 97 | { 98 | const std::unique_ptr old_head = wait_pop_head(); 99 | return old_head->data; 100 | } 101 | void wait_and_pop(T& value) 102 | { 103 | const std::unique_ptr old_head = wait_pop_head(value); 104 | } 105 | void push(T new_value) 106 | { 107 | std::shared_ptr new_data( 108 | std::make_shared(std::move(new_value))); 109 | std::unique_ptr p(new node); 110 | { 111 | std::lock_guard tail_lock(tail_mutex); 112 | tail->data = new_data; 113 | node* const new_tail = p.get(); 114 | tail->next = std::move(p); 115 | tail = new_tail; 116 | } 117 | data_cond.notify_one(); 118 | } 119 | void empty() 120 | { 121 | std::lock_guard head_lock(head_mutex); 122 | return (head == get_tail()); 123 | } 124 | }; 125 | 126 | //test 127 | void PrepareData(ThreadsafeQueue& queue) { 128 | while (true) { 129 | static int i = 1; 130 | std::cout << "threadid=" << std::this_thread::get_id() << " push:i=" << i << std::endl; 131 | queue.push(i++); 132 | std::this_thread::sleep_for(std::chrono::seconds(1)); 133 | } 134 | } 135 | 136 | void ProcessData(ThreadsafeQueue& queue) { 137 | while (true) { 138 | int i = 0; 139 | queue.wait_and_pop(i); 140 | std::cout << "threadid=" << std::this_thread::get_id << " wait_and_pop:i=" << i << std::endl; 141 | std::this_thread::sleep_for(std::chrono::seconds(1)); 142 | } 143 | } 144 | 145 | int main() 146 | { 147 | ThreadsafeQueue queue; 148 | 149 | std::thread t1(PrepareData,std::ref(queue)); 150 | std::thread t2(ProcessData, std::ref(queue)); 151 | t1.join(); 152 | t2.join(); 153 | } 154 | 155 | 156 | -------------------------------------------------------------------------------- /ThreadPool/ThreadPool2/ThreadSafeQueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _THREAD_SAFE_QUEUE_HPP__ 2 | #define _THREAD_SAFE_QUEUE_HPP__ 3 | 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | use c++ 11 14 | */ 15 | 16 | template 17 | class ThreadsafeQueue 18 | { 19 | private: 20 | struct node 21 | { 22 | std::shared_ptr data; 23 | std::unique_ptr next; 24 | }; 25 | 26 | std::mutex head_mutex; 27 | std::unique_ptr head; 28 | std::mutex tail_mutex; 29 | node* tail; 30 | std::condition_variable data_cond; 31 | 32 | private: 33 | node* get_tail() 34 | { 35 | std::lock_guard tail_lock(tail_mutex); 36 | return tail; 37 | } 38 | 39 | std::unique_ptr pop_head() 40 | { 41 | std::unique_ptr old_head = std::move(head); 42 | head = std::move(old_head->next); 43 | return old_head; 44 | } 45 | 46 | std::unique_lock wait_for_data() 47 | { 48 | std::unique_lock head_lock(head_mutex); 49 | data_cond.wait(head_lock, [&] {return head.get() != get_tail(); }); 50 | return head_lock; 51 | } 52 | 53 | std::unique_ptr wait_pop_head() 54 | { 55 | std::unique_lock head_lock(wait_for_data()); 56 | return pop_head(); 57 | } 58 | 59 | std::unique_ptr wait_pop_head(T& value) 60 | { 61 | std::unique_lock head_lock(wait_for_data()); 62 | value = std::move(*head->data); 63 | return pop_head(); 64 | } 65 | std::unique_ptr try_pop_head() 66 | { 67 | std::lock_guard head_lock(head_mutex); 68 | if (head.get() == get_tail()) 69 | { 70 | return std::unique_ptr(); 71 | } 72 | return pop_head(); 73 | } 74 | 75 | std::unique_ptr try_pop_head(T& value) 76 | { 77 | std::lock_guard head_lock(head_mutex); 78 | if (head.get() == get_tail()) 79 | { 80 | return std::unique_ptr(); 81 | } 82 | value = std::move(*head->data); 83 | return pop_head(); 84 | } 85 | public: 86 | ThreadsafeQueue() :head(new node), tail(head.get()){} 87 | ThreadsafeQueue(const ThreadsafeQueue& other) = delete; 88 | ThreadsafeQueue& operator=(const ThreadsafeQueue& other) = delete; 89 | 90 | std::shared_ptr try_pop() 91 | { 92 | const std::unique_ptr old_head = try_pop_head(); 93 | return old_head ? old_head->data : std::shared_ptr(); 94 | } 95 | bool try_pop(T& value) 96 | { 97 | const std::unique_ptr old_head = try_pop_head(value); 98 | return old_head!=nullptr; 99 | } 100 | std::shared_ptr wait_and_pop() 101 | { 102 | const std::unique_ptr old_head = wait_pop_head(); 103 | return old_head->data; 104 | } 105 | void wait_and_pop(T& value) 106 | { 107 | const std::unique_ptr old_head = wait_pop_head(value); 108 | } 109 | void push(T new_value) 110 | { 111 | std::shared_ptr new_data( 112 | std::make_shared(std::move(new_value))); 113 | std::unique_ptr p(new node); 114 | { 115 | std::lock_guard tail_lock(tail_mutex); 116 | tail->data = new_data; 117 | node* const new_tail = p.get(); 118 | tail->next = std::move(p); 119 | tail = new_tail; 120 | } 121 | data_cond.notify_one(); 122 | } 123 | void empty() 124 | { 125 | std::lock_guard head_lock(head_mutex); 126 | return (head == get_tail()); 127 | } 128 | }; 129 | 130 | //test 131 | //void PrepareData(ThreadsafeQueue& queue) { 132 | // while (true) { 133 | // static int i = 1; 134 | // std::cout << "threadid=" << std::this_thread::get_id() << " push:i=" << i << std::endl; 135 | // queue.push(i++); 136 | // std::this_thread::sleep_for(std::chrono::seconds(1)); 137 | // } 138 | //} 139 | // 140 | //void ProcessData(ThreadsafeQueue& queue) { 141 | // while (true) { 142 | // int i = 0; 143 | // queue.wait_and_pop(i); 144 | // std::cout << "threadid=" << std::this_thread::get_id << " wait_and_pop:i=" << i << std::endl; 145 | // std::this_thread::sleep_for(std::chrono::seconds(1)); 146 | // } 147 | //} 148 | // 149 | //int main() 150 | //{ 151 | // ThreadsafeQueue queue; 152 | // 153 | // std::thread t1(PrepareData,std::ref(queue)); 154 | // std::thread t2(ProcessData, std::ref(queue)); 155 | // t1.join(); 156 | // t2.join(); 157 | //} 158 | 159 | #endif // !_THREAD_SAFE_QUEUE_HPP__ 160 | -------------------------------------------------------------------------------- /Curl/multi_example/CurlMgr.cpp: -------------------------------------------------------------------------------- 1 | #include "CurlMgr.h" 2 | 3 | CurlMgr::CurlMgr() : m_pMultiHandle(nullptr) 4 | {} 5 | 6 | 7 | CurlMgr::~CurlMgr() 8 | { 9 | Final(); 10 | } 11 | 12 | int32_t CurlMgr::Init() 13 | { 14 | m_pMultiHandle = curl_multi_init(); 15 | if(m_pMultiHandle == nullptr) 16 | { 17 | return CurlError_MultiInitFail; 18 | } 19 | return 0; 20 | } 21 | 22 | void CurlMgr::Final() 23 | { 24 | if(m_pMultiHandle != nullptr) 25 | { 26 | curl_multi_cleanup(m_pMultiHandle); 27 | } 28 | 29 | for(auto& urlReq : m_mapReq) 30 | { 31 | curl_easy_cleanup(urlReq.first); 32 | } 33 | m_mapReq.clear(); 34 | } 35 | 36 | int32_t CurlMgr::AddRequest(const std::string& sUrl, const std::string& sPost, CurlFun&& fResCall, void* sUserData, const char* headers) 37 | { 38 | if(m_mapReq.size() > MAX_REQ_SIZE) 39 | { 40 | return CurlError_CurlSizeLimit; 41 | } 42 | 43 | UrlReq* pReq = new UrlReq(); 44 | if(pReq == nullptr) 45 | { 46 | return CurlError_AllocUrlReqFail; 47 | } 48 | int32_t ret = _InitCurl(*pReq, sUrl, sPost, headers); 49 | if(ret != 0) 50 | { 51 | delete pReq; 52 | return ret; 53 | } 54 | 55 | pReq->fCall = fResCall; 56 | pReq->sUserData = sUserData; 57 | m_mapReq[pReq->pCurl] = pReq; 58 | return 0; 59 | } 60 | 61 | int32_t CurlMgr::_InitCurl(UrlReq& req, const std::string& sUrl, const std::string& sPost, const char* headers) 62 | { 63 | CURL* pCurl = curl_easy_init(); 64 | if(pCurl == nullptr) 65 | { 66 | return CurlError_EasyInitFail; 67 | } 68 | 69 | req.pCurl = pCurl; 70 | 71 | if(headers != nullptr) 72 | { 73 | req.headers = curl_slist_append(nullptr, headers); 74 | if(req.headers == nullptr) 75 | { 76 | return CurlError_Slist_Append; 77 | } 78 | CURLcode ret = curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, req.headers); 79 | if(ret != CURLE_OK) 80 | { 81 | return CurlError_SetOptFail; 82 | } 83 | } 84 | 85 | CURLcode ret = curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, &_DataWrite); 86 | if(ret != CURLE_OK) 87 | { 88 | return CurlError_SetOptFail; 89 | } 90 | 91 | ret = curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 1L); 92 | if(ret != CURLE_OK) 93 | { 94 | return CurlError_SetOptFail; 95 | } 96 | 97 | ret = curl_easy_setopt(pCurl, CURLOPT_FOLLOWLOCATION, 1L); 98 | if(ret != CURLE_OK) 99 | { 100 | return CurlError_SetOptFail; 101 | } 102 | 103 | //_DataWrite userP 104 | ret = curl_easy_setopt(pCurl, CURLOPT_FILE, &req); 105 | if(ret != CURLE_OK) 106 | { 107 | return CurlError_SetOptFail; 108 | } 109 | 110 | ret = curl_easy_setopt(pCurl, CURLOPT_TIMEOUT_MS, MAX_CURL_TIME_OUT); 111 | if(ret != CURLE_OK) 112 | { 113 | return CurlError_SetOptFail; 114 | } 115 | 116 | ret = curl_easy_setopt(pCurl, CURLOPT_URL, sUrl.c_str()); 117 | if(ret != CURLE_OK) 118 | { 119 | return CurlError_SetOptFail; 120 | } 121 | 122 | if(!sPost.empty()) 123 | { 124 | ret = curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, sPost.c_str()); 125 | if(ret != CURLE_OK) 126 | { 127 | return CurlError_SetOptFail; 128 | } 129 | } 130 | 131 | CURLMcode mRet = curl_multi_add_handle(m_pMultiHandle, pCurl); 132 | if(mRet != CURLM_OK) 133 | { 134 | return CurlError_MultiAddFail; 135 | } 136 | return 0; 137 | } 138 | 139 | size_t CurlMgr::_DataWrite(void* buf, size_t size, size_t nmemb, void* userP) 140 | { 141 | if(userP != nullptr) 142 | { 143 | UrlReq* pReq = static_cast(userP); 144 | pReq->sResult.append((char*)buf, size * nmemb); 145 | return size * nmemb; 146 | } 147 | return 0; 148 | } 149 | 150 | void CurlMgr::Update() 151 | { 152 | if(m_mapReq.empty()) 153 | { 154 | return ; 155 | } 156 | 157 | int32_t iLeftMsg = 0; 158 | int32_t iRunning = 0; 159 | CURLMsg* msg = nullptr; 160 | 161 | curl_multi_perform(m_pMultiHandle, &iRunning); 162 | 163 | while((msg = curl_multi_info_read(m_pMultiHandle, &iLeftMsg)) != nullptr) 164 | { 165 | if(msg->msg == CURLMSG_DONE) 166 | { 167 | CURL* pHandle = msg->easy_handle; 168 | UrlReqMapIter iter = m_mapReq.find(pHandle); 169 | if(iter != m_mapReq.end()) 170 | { 171 | iter->second->fCall(msg->data.result, std::move(iter->second->sResult), iter->second->sUserData); 172 | delete iter->second; 173 | m_mapReq.erase(iter); 174 | } 175 | 176 | curl_multi_remove_handle(m_pMultiHandle, pHandle); 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /ThreadSafeLookupTable/ThreadSafeLookupTable.cpp: -------------------------------------------------------------------------------- 1 | // ThreadSafeLookupTable.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | //#include 14 | 15 | template > 16 | class ThreadsafeLookupTable 17 | { 18 | private: 19 | class bucket_type 20 | { 21 | private: 22 | typedef std::pair bucket_value; 23 | typedef std::list bucket_data; 24 | typedef typename bucket_data::iterator bucket_iterator; 25 | typedef typename bucket_data::const_iterator bucket_const_iterator; 26 | 27 | bucket_data data; 28 | //mutable boost::shared_mutex mutex; 29 | mutable std::shared_mutex mutex; 30 | 31 | bucket_const_iterator find_entry_for(Key const& key) const 32 | { 33 | return std::find_if(data.begin(), data.end(), 34 | [&](const bucket_value& item) 35 | {return item.first == key; }); 36 | } 37 | public: 38 | Value value_for(Key const& key, Value const& default_value) const 39 | { 40 | // boost::shared_lock lock(mutex); 41 | std::shared_lock lock(mutex); 42 | bucket_const_iterator found_entry = find_entry_for(key); 43 | return (found_entry == data.end()) ? default_value : found_entry->second; 44 | } 45 | 46 | void add_or_update_mapping(Key const& key, Value const& value) 47 | { 48 | //std::unique_lock lock(mutex); 49 | std::unique_lock lock(mutex); 50 | bucket_const_iterator found_entry = find_entry_for(key); 51 | if (found_entry == data.end()) 52 | { 53 | data.push_back(bucket_value(key, value)); 54 | } 55 | else 56 | { 57 | auto data = const_cast(*found_entry); 58 | data.second = value; 59 | } 60 | } 61 | 62 | void remove_mapping(Key const& key) 63 | { 64 | //std::unique_lock lock(mutex); 65 | std::unique_lock lock(mutex); 66 | bucket_const_iterator found_entry = find_entry_for(key); 67 | if (found_entry != data.end()) 68 | { 69 | data.erase(found_entry); 70 | } 71 | } 72 | }; 73 | 74 | std::vector > buckets; 75 | Hash hasher; 76 | 77 | bucket_type& get_bucket(Key const& key) const 78 | { 79 | std::size_t const bucket_index = hasher(key) % buckets.size(); 80 | return *buckets[bucket_index]; 81 | } 82 | 83 | public: 84 | typedef Key key_type; 85 | typedef Value mapped_type; 86 | typedef Hash hash_type; 87 | 88 | ThreadsafeLookupTable( 89 | unsigned num_buckets = 19, Hash const& hasher_ = Hash()) : 90 | buckets(num_buckets), hasher(hasher_) 91 | { 92 | for (unsigned i = 0; i < num_buckets; ++i) 93 | { 94 | buckets[i].reset(new bucket_type); 95 | } 96 | } 97 | 98 | ThreadsafeLookupTable(ThreadsafeLookupTable const& other) = delete; 99 | ThreadsafeLookupTable& operator=( 100 | ThreadsafeLookupTable const& other) = delete; 101 | 102 | Value value_for(Key const& key,Value const& default_value = Value()) const 103 | { 104 | return get_bucket(key).value_for(key, default_value); 105 | } 106 | 107 | void add_or_update_mapping(Key const& key, Value const& value) 108 | { 109 | get_bucket(key).add_or_update_mapping(key, value); 110 | } 111 | 112 | void remove_mapping(Key const& key) 113 | { 114 | get_bucket(key).remove_mapping(key); 115 | } 116 | 117 | std::map get_map() const 118 | { 119 | //std::vector > locks; 120 | std::vector > locks; 121 | for (unsigned i = 0; i < buckets.size(); ++i) 122 | { 123 | locks.push_back( 124 | //std::unique_lock(buckets[i].mutex)); 125 | std::unique_lock(buckets[i].mutex)); 126 | } 127 | std::map res; 128 | for (unsigned i = 0; i < buckets.size(); ++i) 129 | { 130 | for (auto& it = buckets[i].data.begin(); 131 | it != buckets[i].data.end(); 132 | ++it) 133 | { 134 | res.insert(*it); 135 | } 136 | } 137 | return res; 138 | } 139 | }; 140 | 141 | 142 | int main() 143 | { 144 | ThreadsafeLookupTable hashTable; 145 | hashTable.add_or_update_mapping(1, 2); 146 | auto value = hashTable.value_for(1); 147 | std::cout << value << std::endl; 148 | hashTable.remove_mapping(1); 149 | value = hashTable.value_for(1); 150 | if (value == 0) { 151 | std::cout << "remove" << std::endl; 152 | } 153 | } 154 | 155 | -------------------------------------------------------------------------------- /Random/UniformRandom.h: -------------------------------------------------------------------------------- 1 | #ifndef UNIFORM_RANDOM 2 | #define UNIFORM_RANDOM 3 | 4 | //#include 5 | //using namespace std; 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | // UniformRandom class 14 | // 15 | // CONSTRUCTION: with (a) no initializer or (b) a long 16 | // that specifies the initial state of the generator. 17 | // This random number generator is similar to 18 | // drand48 in C/C++. 19 | // 20 | // ******************PUBLIC OPERATIONS********************* 21 | // Return a random number according to some distribution: 22 | // int nextInt( ) --> Uniform 23 | // int nextDouble( ) --> Uniform, [0 to 1) 24 | // int nextInt( int high ) --> Uniform [0..high) 25 | // int nextInt( int low, int high ) --> Uniform [low..high) 26 | // long nextLong( ) --> Uniform 27 | 28 | /** 29 | * Uniform Random Number generator class, using a 48-bit 30 | * linear congruential generator. 31 | */ 32 | class Random48 33 | { 34 | private: 35 | static long long currentTimeMicroSeconds( ) 36 | { 37 | auto now = chrono::high_resolution_clock::now( ).time_since_epoch( ); 38 | return (chrono::duration_cast( now ) ).count( ); 39 | } 40 | 41 | public: 42 | /** 43 | * Construct this Random object with specified initial state 44 | */ 45 | Random48( long long initialValue = currentTimeMicroSeconds( ) ) 46 | { 47 | state = initialValue & MASK; 48 | } 49 | 50 | 51 | /** 52 | * Return a pseudorandom int, and change the 53 | * internal state. 54 | */ 55 | int nextInt( ) 56 | { 57 | return next( 32 ); 58 | } 59 | 60 | /** 61 | * Return a pseudorandom int in range [0..high), 62 | * and change the internal state. 63 | */ 64 | int nextInt( int high ) 65 | { 66 | return static_cast( abs( nextLong( ) % high ) ); 67 | } 68 | 69 | /** 70 | * Return a pseudorandom double in the range [0..1) 71 | * and change the internal state. 72 | */ 73 | double nextDouble( ) 74 | { 75 | return ( ( static_cast( ( next( 26 ) ) ) << 27 ) + next( 27 ) ) 76 | / static_cast( 1LL << 53 ); 77 | } 78 | 79 | /** 80 | * Return an int in the closed range [low,high], and 81 | * change the internal state. 82 | */ 83 | int nextInt( int low, int high ) 84 | { 85 | return nextInt( high - low + 1 ) + low; 86 | } 87 | 88 | /** 89 | * Return a 64-bit long, and change the internal state. 90 | * Note that all longs can be generated. 91 | */ 92 | long long nextLong( ) 93 | { 94 | return ( ( static_cast( next( 32 ) ) ) << 32 ) + next( 32 ); 95 | } 96 | 97 | private: 98 | long long state; 99 | 100 | static const long long A = 25214903917LL; 101 | static const long long C = 11; 102 | static const long long M = ( 1LL << 48 ); 103 | static const long long MASK = M - 1; 104 | 105 | /** 106 | * Return specified number of random bits 107 | */ 108 | int next( int bits ) 109 | { 110 | state = ( A * state + C ) & MASK; 111 | 112 | return state >> ( 48 - bits ); 113 | } 114 | }; 115 | 116 | // UniformRandom class 117 | // 118 | // CONSTRUCTION: with (a) no initializer or (b) a int 119 | // that specifies the initial state of the generator. 120 | // This random number generator uses the 32-bit Mersenne Twister 121 | // 122 | // ******************PUBLIC OPERATIONS********************* 123 | // Return a random number according to some distribution: 124 | // int nextInt( ) --> Uniform 125 | // int nextDouble( ) --> Uniform, [0 to 1) 126 | // int nextInt( int high ) --> Uniform [0..high) 127 | // int nextInt( int low, int high ) --> Uniform [low..high) 128 | 129 | 130 | static int currentTimeSeconds( ) 131 | { 132 | auto now = chrono::high_resolution_clock::now( ).time_since_epoch( ); 133 | return chrono::duration_cast( now ).count( ); 134 | } 135 | 136 | /** 137 | * Uniform Random Number generator class, using C++ Mersenne Twister. 138 | */ 139 | class UniformRandom 140 | { 141 | public: 142 | UniformRandom( int seed = currentTimeSeconds( ) ) : generator{ seed } 143 | { 144 | } 145 | 146 | /** 147 | * Return a pseudorandom int. 148 | */ 149 | int nextInt( ) 150 | { 151 | static uniform_int_distribution distribution; 152 | return distribution( generator ); 153 | } 154 | 155 | /** 156 | * Return a pseudorandom int in range [0..high). 157 | */ 158 | int nextInt( int high ) 159 | { 160 | return nextInt( 0, high - 1 ); 161 | } 162 | 163 | /** 164 | * Return a pseudorandom double in the range [0..1). 165 | */ 166 | double nextDouble( ) 167 | { 168 | static uniform_real_distribution distribution( 0, 1 ); 169 | return distribution( generator ); 170 | } 171 | 172 | /** 173 | * Return an int in the closed range [low,high]. 174 | */ 175 | int nextInt( int low, int high ) 176 | { 177 | uniform_int_distribution distribution( low, high ); 178 | return distribution( generator ); 179 | } 180 | 181 | private: 182 | mt19937 generator; 183 | }; 184 | #endif 185 | 186 | -------------------------------------------------------------------------------- /ThreadPool/ThreadPool2/ThreadPool.h: -------------------------------------------------------------------------------- 1 | #ifndef _THREAD_POOL_HPP__ 2 | #define _THREAD_POOL_HPP__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "ThreadSafeQueue.hpp" 12 | 13 | class function_wrapper 14 | { 15 | struct impl_base { 16 | virtual void call() = 0; 17 | virtual ~impl_base() {} 18 | }; 19 | std::unique_ptr impl; 20 | template 21 | struct impl_type : impl_base 22 | { 23 | F f; 24 | impl_type(F&& f_) : f(std::move(f_)) {} 25 | void call() { f(); } 26 | }; 27 | public: 28 | void operator()() { impl->call(); } 29 | 30 | function_wrapper() = default; 31 | 32 | template 33 | function_wrapper(F&& f) : impl(new impl_type(std::move(f))){} 34 | 35 | function_wrapper(function_wrapper&& other) :impl(std::move(other.impl)){} 36 | 37 | function_wrapper& operator=(function_wrapper&& other) 38 | { 39 | impl = std::move(other.impl); 40 | return *this; 41 | } 42 | 43 | function_wrapper(const function_wrapper&) = delete; 44 | function_wrapper(function_wrapper&) = delete; 45 | function_wrapper& operator=(const function_wrapper&) = delete; 46 | }; 47 | 48 | class work_stealing_queue 49 | { 50 | private: 51 | typedef function_wrapper data_type; 52 | std::deque the_queue; 53 | mutable std::mutex the_mutex; 54 | 55 | public: 56 | work_stealing_queue() 57 | {} 58 | 59 | work_stealing_queue(const work_stealing_queue& other) = delete; 60 | work_stealing_queue& operator=( 61 | const work_stealing_queue& other) = delete; 62 | 63 | void push(data_type data) 64 | { 65 | std::lock_guard lock(the_mutex); 66 | the_queue.push_front(std::move(data)); 67 | } 68 | 69 | bool empty() const 70 | { 71 | std::lock_guard lock(the_mutex); 72 | return the_queue.empty(); 73 | } 74 | 75 | bool try_pop(data_type& res) 76 | { 77 | std::lock_guard lock(the_mutex); 78 | if (the_queue.empty()) 79 | { 80 | return false; 81 | } 82 | 83 | res = std::move(the_queue.front()); 84 | the_queue.pop_front(); 85 | return true; 86 | } 87 | 88 | bool try_steal(data_type& res) 89 | { 90 | std::lock_guard lock(the_mutex); 91 | if (the_queue.empty()) 92 | { 93 | return false; 94 | } 95 | 96 | res = std::move(the_queue.back()); 97 | the_queue.pop_back(); 98 | return true; 99 | } 100 | }; 101 | 102 | 103 | 104 | 105 | class ThreadPool 106 | { 107 | typedef function_wrapper task_type; 108 | 109 | std::atomic_bool done; 110 | ThreadsafeQueue pool_work_queue; 111 | std::vector > queues; 112 | std::vector threads; 113 | 114 | static thread_local work_stealing_queue* local_work_queue; 115 | static thread_local unsigned my_index; 116 | 117 | void worker_thread(unsigned my_index_) 118 | { 119 | my_index = my_index_; 120 | local_work_queue = queues[my_index].get(); 121 | while (!done) 122 | { 123 | run_pending_task(); 124 | } 125 | } 126 | 127 | bool pop_task_from_local_queue(task_type& task) 128 | { 129 | return local_work_queue && local_work_queue->try_pop(task); 130 | } 131 | 132 | bool pop_task_from_pool_queue(task_type& task) 133 | { 134 | return pool_work_queue.try_pop(task); 135 | } 136 | 137 | bool pop_task_from_other_thread_queue(task_type& task) 138 | { 139 | for (unsigned i = 0; i < queues.size(); ++i) 140 | { 141 | unsigned const index = (my_index + i + 1) % queues.size(); 142 | if (queues[index]->try_steal(task)) 143 | { 144 | return true; 145 | } 146 | } 147 | 148 | return false; 149 | } 150 | 151 | public: 152 | ThreadPool() : done(false) 153 | { 154 | unsigned const thread_count = std::thread::hardware_concurrency(); 155 | 156 | try 157 | { 158 | for (unsigned i = 0; i < thread_count; ++i) 159 | { 160 | queues.push_back(std::unique_ptr(new work_stealing_queue)); 161 | threads.push_back(std::thread(&ThreadPool::worker_thread, this, i)); 162 | } 163 | } 164 | catch (...) 165 | { 166 | done = true; 167 | throw; 168 | } 169 | } 170 | 171 | ~ThreadPool() 172 | { 173 | done = true; 174 | std::for_each(threads.begin(), threads.end(),[](std::thread& thread) { thread.join();}); 175 | } 176 | 177 | template 178 | using TaskHandle = std::future; 179 | 180 | template 181 | TaskHandle::type> submit(FunctionType f) 182 | { 183 | typedef typename std::result_of::type result_type; 184 | 185 | std::packaged_task task(f); 186 | TaskHandle res(task.get_future()); 187 | if (local_work_queue) 188 | { 189 | local_work_queue->push(std::move(task)); 190 | } 191 | else 192 | { 193 | pool_work_queue.push(std::move(task)); 194 | } 195 | return res; 196 | } 197 | 198 | void run_pending_task() 199 | { 200 | task_type task; 201 | if (pop_task_from_local_queue(task) || 202 | pop_task_from_pool_queue(task) || 203 | pop_task_from_other_thread_queue(task)) 204 | { 205 | task(); 206 | } 207 | else 208 | { 209 | std::this_thread::yield(); 210 | } 211 | } 212 | }; 213 | 214 | 215 | #endif // !_THREAD_POOL_HPP__ 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /NineBoxView/Map.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __MAP_HPP_H__ 2 | #define __MAP_HPP_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Vector2i.hpp" 8 | #include "MapGrid.hpp" 9 | 10 | using namespace std; 11 | 12 | class Map{ 13 | public: 14 | Map() = default; 15 | 16 | public: 17 | /*地图初始化 18 | * 参数: 19 | * mapWidth:地图宽 20 | * mapHeight:地图高 21 | * gridSize:格子数 22 | * 返回值: 23 | * 无 24 | * */ 25 | void InitMap(int mapWidth,int mapHeight,int gridSize){ 26 | m_ColCount = mapWidth / gridSize + 1; 27 | m_RowCount = mapHeight / gridSize + 1; 28 | m_GridSize = gridSize; 29 | m_MapWidth = mapWidth; 30 | m_MapHeight = mapHeight; 31 | 32 | m_MaxIndex = m_ColCount * m_RowCount; 33 | m_MapGridVec.resize(m_MaxIndex); 34 | } 35 | 36 | /*计算移动坐标所在的格子坐标 37 | * 参数: 38 | * posX:移动的横坐标 39 | * posY:移动的纵坐标 40 | * 返回值: 41 | * 格子所在的坐标 42 | * */ 43 | Vector2i ComputerGrid(int posX,int posY){ 44 | if(posX<0) posX = 0; 45 | if(posY<0) posY = 0; 46 | if(posX>m_MapWidth) posX = m_MapWidth; 47 | if(posY>m_MapHeight) posY = m_MapHeight; 48 | return {posX/m_GridSize,posY/m_GridSize}; 49 | } 50 | 51 | /*计算移动坐标所在格子的索引 52 | * 参数: 53 | * posX:移动的横坐标 54 | * posY:移动的纵坐标 55 | * 返回值: 56 | * 格子所在的索引 57 | * */ 58 | int ComputerGridIndex(int posX, int posY){ 59 | if(posX<0) posX = 0; 60 | if(posY<0) posY = 0; 61 | if(posX>m_MapWidth) posX = m_MapWidth; 62 | if(posY>m_MapHeight) posY = m_MapHeight; 63 | return (posY/m_GridSize * m_ColCount + posX/m_GridSize); 64 | } 65 | 66 | /*计算移动过程中增加或者减少的格子区域 67 | * 参数: 68 | * from:出发坐标点所在的格子坐标 69 | * dst:目的坐标点所在的格子坐标 70 | * deleteArea:移动过程中减少的格子区域(视野区域) 71 | * addArea:移动过程中增加的格子区域 72 | * 返回值: 73 | * 无 74 | * */ 75 | void InterestArea(const Vector2i& from,const Vector2i& dst,set& deleteArea, set& addArea){ 76 | set fromArea = GetAll9Grid(from); 77 | set dstArea = GetAll9Grid(dst); 78 | 79 | //求set交集 80 | set intersection; 81 | std::set_intersection(fromArea.begin(),fromArea.end(),dstArea.begin(),dstArea.end(),std::inserter(intersection,intersection.begin()));//C++11 82 | 83 | //deleteArea = fromArea - 交集 84 | std::set_difference(fromArea.begin(),fromArea.end(),intersection.begin(),intersection.end(),std::inserter(deleteArea,deleteArea.begin())); 85 | //addArea = dstArea - 交集 86 | std::set_difference(dstArea.begin(),dstArea.end(),intersection.begin(),intersection.end(),std::inserter(addArea,addArea.begin())); 87 | 88 | //DEBUG LOG 89 | std::cout<<"fromArea:"<& deleteArea, set& addArea){ 113 | Vector2i from = ComputerGrid(fromPosX,fromPosY); 114 | Vector2i dst = ComputerGrid(dstPosX,dstPosY); 115 | return InterestArea(from,dst,deleteArea,addArea); 116 | } 117 | 118 | 119 | /*将角色添加到对应的格子中 120 | * 参数: 121 | * pos:角色移动的目标点对应格子所在的坐标 122 | * obj:角色对象 123 | * 返回值: 124 | * 无 125 | * */ 126 | void AddObj(const Vector2i& pos,ObjBase& obj){ 127 | m_MapGridVec[pos.m_y*m_ColCount + pos.m_x].AddObj(obj);//近似实现类似unordered的查找效率 128 | } 129 | 130 | /*将角色在对应的格子中删除 131 | * 参数: 132 | * obj:角色对象 133 | * 返回值: 134 | * 无 135 | * */ 136 | void RemoveObj(const ObjBase& obj){ 137 | m_MapGridVec[obj.GetPosY()*m_ColCount + obj.GetPosX()].RemoveObj(obj.GetUid()); 138 | } 139 | 140 | //... 其他函数 141 | 142 | private: 143 | /*计算出pos点周围的9宫格格子索引 144 | * 参数: 145 | * pos:9宫格中心点格子坐标点 146 | * 返回值: 147 | * 9宫格格子索引 148 | * */ 149 | set GetAll9Grid(const Vector2i& pos){ 150 | int curIndex = pos.m_y * m_ColCount + pos.m_x; //当前索引值 151 | int curColIndexMax = (pos.m_y+1) * m_ColCount -1; //当前行最大索引值 152 | int curColIndexMin = pos.m_y * m_ColCount ; //当前行最小索引值 153 | 154 | set setIndex; 155 | setIndex.emplace(curIndex); //中间格子 156 | 157 | int leftIndex = curIndex-1 ; //左边格子索引 158 | if(leftIndex>=0 && leftIndex >=curColIndexMin){ 159 | setIndex.emplace(leftIndex); 160 | } 161 | int rightIndex = (curIndex+1)<=curColIndexMax?(curIndex+1):curColIndexMax;//右边格子索引 162 | if(rightIndex<=m_MaxIndex-1){ 163 | setIndex.emplace(rightIndex); 164 | } 165 | 166 | int midUpIndex = curIndex+m_ColCount;//中上格子索引 167 | if(midUpIndex<=m_MaxIndex-1){ 168 | setIndex.emplace(midUpIndex); 169 | } 170 | 171 | int midDownIndex = curIndex-m_ColCount; //中下格子索引 172 | if(midDownIndex>=0){ 173 | setIndex.emplace(midDownIndex); 174 | } 175 | 176 | int leftUpIndex = midUpIndex-1; //左上格子索引 177 | if(leftUpIndex>=0 && (leftUpIndex>= curColIndexMin + m_ColCount && leftUpIndex<=m_MaxIndex-1)){ 178 | setIndex.emplace(leftUpIndex); 179 | } 180 | int rightUpIndex = (midUpIndex+1)<=(curColIndexMax+m_ColCount)?(midUpIndex+1):(curColIndexMax+m_ColCount);//右上格子索引 181 | if(rightUpIndex<=m_MaxIndex-1){ 182 | setIndex.emplace(rightUpIndex); 183 | } 184 | 185 | int leftDownIndex = midDownIndex-1; //左下格子索引 186 | if(leftDownIndex>=0 && leftDownIndex>=curColIndexMin-m_ColCount){ 187 | setIndex.emplace(leftDownIndex); 188 | } 189 | int rightDownIndex = (midDownIndex+1)<=(curColIndexMax-m_ColCount)?(midDownIndex+1):(curColIndexMax-m_ColCount);//右下格子索引 190 | if(rightDownIndex>=0){ 191 | setIndex.emplace(rightDownIndex); 192 | } 193 | return setIndex; 194 | } 195 | 196 | private: 197 | void Print(const set& set){ 198 | std::cout<<"("; 199 | for(auto it : set){ 200 | std::cout< m_MapGridVec; 213 | }; 214 | 215 | 216 | #endif //__MAP_HPP_H__ -------------------------------------------------------------------------------- /SpecailHeap/BinaryHeap.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BINARY_HEAP_H 2 | #define BINARY_HEAP_H 3 | 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | namespace binaryheap{ 10 | /* 11 | BinaryHeap class 12 | ******************PUBLIC OPERATIONS********************* 13 | void Push( x ) --> Push x 14 | Pop( minItem ) --> Remove (and optionally return) smallest item 15 | T Top( ) --> Return smallest item 16 | bool Empty( ) --> Return true if empty; else false 17 | void Clear( ) --> Remove all items 18 | void Remove() --> Remove heap intenal data 19 | 20 | attention: 21 | T is can be int string double userclass and so on 22 | 23 | if T is user class: 24 | 1. T must have value filed and value type is integral, be used to cmp function. 25 | 2. T must have key filed, be used hash table 26 | 3. T must override operator < or >,be used to cmp function 27 | 4. assume T is string or userclass when T is class 28 | */ 29 | 30 | //common T template 31 | template 32 | class BinaryHeap {}; 33 | 34 | //specail T is int 35 | template 36 | class BinaryHeap::value>::type> {}; 37 | 38 | //specail T is string 39 | template 40 | class BinaryHeap::value>::type> {}; 41 | 42 | //special T is user class 43 | template 44 | class BinaryHeap::value 45 | && std::is_class::value && std::is_integral::value>::type>{ 46 | private: 47 | using CmpType = decltype(T().value);//get T operator fun parameter type 48 | using Key = decltype(T().key); //get T hash table key 49 | 50 | public: 51 | explicit BinaryHeap(CmpFun&& cmpF, int capacity=5000 ):cmpF(std::forward(cmpF)), 52 | currentSize{0},capacity(capacity+1),array(capacity+1){} 53 | explicit BinaryHeap(CmpFun&& cmpF, const vector& items):cmpF(std::forward(cmpF)), 54 | array(items.size()+10),currentSize{items.size()}{ 55 | for( int i=0; i O(logN) 134 | */ 135 | void Remove(const Key& key){ 136 | int hole = GetHole(key); 137 | if(hole==0){ 138 | return; 139 | } 140 | DelKey(key); 141 | array[hole].value = value; //这里假设比较值为整数值 142 | PercolateUp(hole); 143 | Pop(); 144 | } 145 | 146 | /** 147 | * clear all item. 148 | */ 149 | void Clear(){ 150 | currentSize = 0; 151 | array.resize(capacity); 152 | keyMap.clear(); 153 | } 154 | 155 | public: 156 | void Print(){//Debug Function 157 | for(int i=1;i<=currentSize;i++){ 158 | std::cout<<"index:"<0;--i){ 176 | PercolateDown(i); 177 | } 178 | } 179 | 180 | /** 181 | * Internal method to percolate down in the heap. 182 | * hole is the index at which the percolate begins. 183 | * O(logN) 184 | */ 185 | void PercolateDown( int hole ){ 186 | int child; 187 | T tmp = std::move(array[hole]); 188 | for( ;hole*2<=currentSize; hole=child ){ 189 | child = hole*2; 190 | if(child!=currentSize && cmpF(array[child+1],array[child])){ 191 | ++child; 192 | } 193 | if(cmpF(array[child],tmp)){ 194 | array[hole] = std::move(array[child]); 195 | AddKey(array[hole].key,hole); 196 | }else{ 197 | break; 198 | } 199 | } 200 | array[hole] = std::move(tmp); 201 | AddKey(array[hole].key,hole); 202 | } 203 | 204 | /** 205 | * Internal method to percolate up in the heap. 206 | * hole is the index at which the percolate begins. 207 | * O(logN) 208 | */ 209 | void PercolateUp(int hole){ 210 | array[0] = std::move(array[hole]); 211 | for(;hole>1 && cmpF(array[0],array[hole/2]);hole/=2){ 212 | array[hole] = std::move(array[hole/2]); 213 | AddKey(array[hole].key,hole); 214 | } 215 | array[hole] = std::move(array[0]); 216 | AddKey(array[hole].key,hole); 217 | } 218 | 219 | /** 220 | * Internal method to add key in the hash table. 221 | * key is T key, hole is the index. 222 | */ 223 | void AddKey(const Key& key, int hole){ 224 | keyMap[key]=hole; 225 | } 226 | 227 | /** 228 | * Internal method to get hole by T key in the hash table. 229 | * key is T key, hole is the index. 230 | */ 231 | int GetHole(const Key& key){ 232 | const auto& iter = keyMap.find(key); 233 | if(iter!=keyMap.end()){ 234 | return iter->second; 235 | } 236 | return 0; 237 | } 238 | 239 | /** 240 | * Internal method to delete key in the hash table. 241 | * key is T key, hole is the index. 242 | */ 243 | void DelKey(const Key& key){ 244 | const auto& iter = keyMap.find(key); 245 | if(iter!=keyMap.end()){ 246 | keyMap.erase(iter); 247 | } 248 | } 249 | 250 | private: 251 | CmpType value {std::is_same{})>::value 252 | ?std::numeric_limits::min():std::numeric_limits::max()}; //cmpF value, T is min or max 253 | CmpFun cmpF; // cmpF function 254 | 255 | int currentSize {0}; // Number of elements in heap 256 | int capacity {0}; // array capacity 257 | std::vector array; // The heap array 258 | std::unordered_map keyMap;//key hash table 259 | }; 260 | 261 | template 262 | using MinHeap = BinaryHeap{})>; 263 | template 264 | using MaxHeap = BinaryHeap{})>; 265 | 266 | } 267 | 268 | #endif 269 | -------------------------------------------------------------------------------- /timer/TimerMgr.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itimer.h - Application Level Implementation of Linux Kernel Timer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef __ITIMERMGR_H__ 10 | #define __ITIMERMGR_H__ 11 | 12 | #include 13 | #include 14 | 15 | //===================================================================== 16 | // 32BIT INTEGER DEFINITION 17 | //===================================================================== 18 | #ifndef __INTEGER_32_BITS__ 19 | #define __INTEGER_32_BITS__ 20 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) && defined(__UINT64_TYPE__) && defined(__UINT64_TYPE__) 21 | typedef __UINT32_TYPE__ ISTDUINT32; 22 | typedef __INT32_TYPE__ ISTDINT32; 23 | typedef __UINT64_TYPE__ ISTDUINT64; 24 | typedef __INT64_TYPE__ ISTDINT64; 25 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 26 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 27 | typedef __INT_FAST32_TYPE__ ISTDINT32; 28 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 29 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 30 | defined(_M_AMD64) 31 | typedef unsigned int ISTDUINT32; 32 | typedef int ISTDINT32; 33 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 34 | defined(__i386) || defined(_M_X86) 35 | typedef unsigned long ISTDUINT32; 36 | typedef long ISTDINT32; 37 | #elif defined(__MACOS__) 38 | typedef UInt32 ISTDUINT32; 39 | typedef SInt32 ISTDINT32; 40 | #elif defined(__APPLE__) && defined(__MACH__) 41 | #include 42 | typedef u_int32_t ISTDUINT32; 43 | typedef int32_t ISTDINT32; 44 | #elif defined(__BEOS__) 45 | #include 46 | typedef u_int32_t ISTDUINT32; 47 | typedef int32_t ISTDINT32; 48 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 49 | typedef unsigned __int32 ISTDUINT32; 50 | typedef __int32 ISTDINT32; 51 | #elif defined(__GNUC__) && (__GNUC__ > 3) 52 | #include 53 | typedef uint32_t ISTDUINT32; 54 | typedef int32_t ISTDINT32; 55 | typedef uint64_t ISTDUINT64; 56 | typedef int64_t ISTDINT64; 57 | #else 58 | typedef unsigned long ISTDUINT32; 59 | typedef long ISTDINT32; 60 | #endif 61 | #endif 62 | 63 | 64 | //===================================================================== 65 | // Integer Definition 66 | //===================================================================== 67 | #ifndef __IINT8_DEFINED 68 | #define __IINT8_DEFINED 69 | typedef char IINT8; 70 | #endif 71 | 72 | #ifndef __IUINT8_DEFINED 73 | #define __IUINT8_DEFINED 74 | typedef unsigned char IUINT8; 75 | #endif 76 | 77 | #ifndef __IUINT16_DEFINED 78 | #define __IUINT16_DEFINED 79 | typedef unsigned short IUINT16; 80 | #endif 81 | 82 | #ifndef __IINT16_DEFINED 83 | #define __IINT16_DEFINED 84 | typedef short IINT16; 85 | #endif 86 | 87 | #ifndef __IINT32_DEFINED 88 | #define __IINT32_DEFINED 89 | typedef ISTDINT32 IINT32; 90 | #endif 91 | 92 | #ifndef __IUINT32_DEFINED 93 | #define __IUINT32_DEFINED 94 | typedef ISTDUINT32 IUINT32; 95 | #endif 96 | 97 | #ifndef __IUINT64_DEFINED 98 | #define __IUINT64_DEFINED 99 | typedef ISTDUINT64 IUINT64; 100 | #endif 101 | 102 | 103 | /*====================================================================*/ 104 | /* LIST DEFINITION */ 105 | /*====================================================================*/ 106 | #ifndef __ILIST_DEF__ 107 | #define __ILIST_DEF__ 108 | 109 | struct ILISTHEAD { 110 | struct ILISTHEAD *next, *prev; 111 | }; 112 | 113 | typedef struct ILISTHEAD ilist_head; 114 | 115 | 116 | /*--------------------------------------------------------------------*/ 117 | /* list init */ 118 | /*--------------------------------------------------------------------*/ 119 | #define ILIST_HEAD_INIT(name) { &(name), &(name) } 120 | #define ILIST_HEAD(name) \ 121 | struct ILISTHEAD name = ILIST_HEAD_INIT(name) 122 | 123 | #define ILIST_INIT(ptr) ( \ 124 | (ptr)->next = (ptr), (ptr)->prev = (ptr)) 125 | 126 | #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 127 | 128 | #define ICONTAINEROF(ptr, type, member) ( \ 129 | (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) 130 | 131 | #define ILIST_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) 132 | 133 | 134 | /*--------------------------------------------------------------------*/ 135 | /* list operation */ 136 | /*--------------------------------------------------------------------*/ 137 | #define ILIST_ADD(node, head) ( \ 138 | (node)->prev = (head), (node)->next = (head)->next, \ 139 | (head)->next->prev = (node), (head)->next = (node)) 140 | 141 | #define ILIST_ADD_TAIL(node, head) ( \ 142 | (node)->prev = (head)->prev, (node)->next = (head), \ 143 | (head)->prev->next = (node), (head)->prev = (node)) 144 | 145 | #define ILIST_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) 146 | 147 | #define ILIST_DEL(entry) (\ 148 | (entry)->next->prev = (entry)->prev, \ 149 | (entry)->prev->next = (entry)->next, \ 150 | (entry)->next = 0, (entry)->prev = 0) 151 | 152 | #define ILIST_DEL_INIT(entry) do { \ 153 | ILIST_DEL(entry); ILIST_INIT(entry); } while (0) 154 | 155 | #define ILIST_IS_EMPTY(entry) ((entry) == (entry)->next) 156 | 157 | #define ilist_init ILIST_INIT 158 | #define ilist_entry ILIST_ENTRY 159 | #define ilist_add ILIST_ADD 160 | #define ilist_add_tail ILIST_ADD_TAIL 161 | #define ilist_del ILIST_DEL 162 | #define ilist_del_init ILIST_DEL_INIT 163 | #define ilist_is_empty ILIST_IS_EMPTY 164 | 165 | #define ILIST_FOREACH(iterator, head, TYPE, MEMBER) \ 166 | for ((iterator) = ilist_entry((head)->next, TYPE, MEMBER); \ 167 | &((iterator)->MEMBER) != (head); \ 168 | (iterator) = ilist_entry((iterator)->MEMBER.next, TYPE, MEMBER)) 169 | 170 | #define ilist_foreach(iterator, head, TYPE, MEMBER) \ 171 | ILIST_FOREACH(iterator, head, TYPE, MEMBER) 172 | 173 | #define ilist_foreach_entry(pos, head) \ 174 | for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next ) 175 | 176 | 177 | #define __ilist_splice(list, head) do { \ 178 | ilist_head *first = (list)->next, *last = (list)->prev; \ 179 | ilist_head *at = (head)->next; \ 180 | (first)->prev = (head), (head)->next = (first); \ 181 | (last)->next = (at), (at)->prev = (last); } while (0) 182 | 183 | #define ilist_splice(list, head) do { \ 184 | if (!ilist_is_empty(list)) __ilist_splice(list, head); } while (0) 185 | 186 | #define ilist_splice_init(list, head) do { \ 187 | ilist_splice(list, head); ilist_init(list); } while (0) 188 | 189 | 190 | #ifdef _MSC_VER 191 | #pragma warning(disable:4311) 192 | #pragma warning(disable:4312) 193 | #pragma warning(disable:4996) 194 | #endif 195 | 196 | #endif 197 | 198 | 199 | //===================================================================== 200 | // Timer Vector 201 | //===================================================================== 202 | #define ITVN_BITS 6 203 | #define ITVR_BITS 8 204 | #define ITVN_SIZE (1 << ITVN_BITS) 205 | #define ITVR_SIZE (1 << ITVR_BITS) 206 | #define ITVN_MASK (ITVN_SIZE - 1) 207 | #define ITVR_MASK (ITVR_SIZE - 1) 208 | 209 | struct itimer_vec { 210 | ilist_head vec[ITVN_SIZE]; 211 | }; 212 | 213 | struct itimer_vec_root { 214 | ilist_head vec[ITVR_SIZE]; 215 | }; 216 | 217 | struct itimer_core { 218 | IUINT32 timer_jiffies; 219 | struct itimer_vec *tvecs[6]; 220 | struct itimer_vec_root tv1; 221 | struct itimer_vec tv2; 222 | struct itimer_vec tv3; 223 | struct itimer_vec tv4; 224 | struct itimer_vec tv5; 225 | }; 226 | 227 | struct itimer_node { 228 | ilist_head head; 229 | IUINT32 expires; 230 | IUINT32 state; 231 | void *data; 232 | void (*callback)(void *data); 233 | struct itimer_core *core; 234 | }; 235 | 236 | 237 | //===================================================================== 238 | // global definition 239 | //===================================================================== 240 | typedef struct itimer_core itimer_core; 241 | typedef struct itimer_node itimer_node; 242 | 243 | #define itimer_core_jiffies(core) ((core)->jiffies) 244 | #define itimer_node_pending(node) (!iqueue_is_empty(&(node)->head)) 245 | 246 | 247 | #ifdef __cplusplus 248 | extern "C" { 249 | #endif 250 | 251 | //===================================================================== 252 | // Core Timer 253 | //===================================================================== 254 | 255 | // initialize timer core 256 | void itimer_core_init(itimer_core *core, IUINT32 jiffies); 257 | 258 | // destroy timer core 259 | void itimer_core_destroy(itimer_core *core); 260 | 261 | // run timer core 262 | void itimer_core_run(itimer_core *core, IUINT32 jiffies); 263 | 264 | 265 | // initialize node 266 | void itimer_node_init(itimer_node *node, void (*fn)(void*), void *data); 267 | 268 | // destroy node 269 | void itimer_node_destroy(itimer_node *node); 270 | 271 | // add node to core 272 | void itimer_node_add(itimer_core *core, itimer_node *node, IUINT32 expires); 273 | 274 | // remove node from core 275 | int itimer_node_del(itimer_core *core, itimer_node *node); 276 | 277 | // modify node 278 | int itimer_node_mod(itimer_core *core, itimer_node *node, IUINT32 expires); 279 | 280 | 281 | 282 | //===================================================================== 283 | // Timer Manager 284 | //===================================================================== 285 | struct itimer_mgr 286 | { 287 | IUINT32 interval; 288 | IUINT32 current; 289 | IUINT32 millisec; 290 | IUINT32 jiffies; 291 | itimer_core core; 292 | }; 293 | 294 | struct itimer_evt 295 | { 296 | IUINT64 evtId; //自己添加的 用于C++的简单封装 297 | std::function fn; //自己添加的 用于C++的简单封装 298 | IUINT32 period; 299 | IUINT32 slap; 300 | int repeat; 301 | int running; 302 | void *data; 303 | void *user; 304 | struct itimer_mgr *mgr; 305 | itimer_node node; 306 | }; 307 | 308 | // type defines 309 | typedef struct itimer_mgr itimer_mgr; 310 | typedef struct itimer_evt itimer_evt; 311 | 312 | // initialize timer manager 313 | // millisec - current time stamp 314 | // interval - internal working interval 315 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 millisec, IUINT32 interval); 316 | 317 | // destroy timer manager 318 | void itimer_mgr_destroy(itimer_mgr *mgr); 319 | 320 | // run timer events: 321 | // millisec - current time stamp 322 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec); 323 | 324 | 325 | // initialize timer event 326 | void itimer_evt_init(itimer_evt *evt, std::function&& fn, 327 | void *data, void *user); 328 | 329 | // destroy timer event 330 | void itimer_evt_destroy(itimer_evt *evt); 331 | 332 | // start timer: repeat <= 0 (infinite repeat) 333 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 334 | IUINT32 period, int repeat, IUINT32 firstInterval); 335 | 336 | // stop timer 337 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt); 338 | 339 | 340 | 341 | #ifdef __cplusplus 342 | } 343 | #endif 344 | 345 | //下面采用C++简单封装一下便于使用 346 | #include 347 | #include 348 | using namespace std; 349 | 350 | class TimerMgr 351 | { 352 | public: 353 | using EvtCallBack = std::function; 354 | public: 355 | /** 356 | * @param curMillSec:ms 357 | * @param interval:ms 358 | */ 359 | TimerMgr(uint64_t curMillSec, uint32_t interval); 360 | ~TimerMgr(); 361 | 362 | /** 363 | * 364 | * @param callBack 365 | * @param data 366 | * @param user 367 | * @return evt_id 368 | */ 369 | uint64_t TimerEvtInit(EvtCallBack&& callBack, void* data, void* user); 370 | 371 | /** 372 | * @param evtId 373 | * @param period 374 | * @param repeat 375 | * @param firstInterval 376 | */ 377 | void TimerEvtStart(uint64_t evtId, uint32_t period, uint32_t repeat, uint32_t firstInterval = 0); 378 | 379 | /** 380 | * @param evtId 381 | */ 382 | void TimerEvtStop(uint64_t evtId); 383 | 384 | /** 385 | * @param evtId 386 | */ 387 | void TimerEvtDestroy(uint64_t evtId); 388 | 389 | void TimerMgrDestroy(); 390 | 391 | /** 392 | * @param curMillSec:ms 393 | */ 394 | void Run(uint64_t curMillSec); 395 | 396 | private: 397 | /** 398 | * @param evt 399 | */ 400 | void AddEvt(itimer_evt* evt); 401 | 402 | /** 403 | * @param evtId 404 | * @return 405 | */ 406 | itimer_evt* FindEvt(uint64_t evtId); 407 | 408 | /** 409 | * @param evtId 410 | */ 411 | void RemoveEvt(uint64_t evtId); 412 | private: 413 | uint64_t mIndex = 0; 414 | itimer_mgr* mMgr = nullptr; 415 | std::unordered_map mEvt; 416 | }; 417 | 418 | #define INIT_TIMERMGR(timerMgr, now, interval) \ 419 | TimerMgr timerMgr(now, interval); 420 | 421 | #define REG_TIMER(timerMgr, func, data, user ,period, repeat, timerId) \ 422 | { \ 423 | timerId = timerMgr.TimerEvtInit(std::move(func), (void*)data, (void*)user); \ 424 | timerMgr.TimerEvtStart(timerId, period, repeat); \ 425 | } 426 | 427 | #define REG_TIMER_FIRST(timerMgr, func, data, user ,period, repeat, firstInterval, timerId) \ 428 | { \ 429 | timerId = timerMgr.TimerEvtInit(std::move(func), (void*)data, (void*)user); \ 430 | timerMgr.TimerEvtStart(timerId, period, repeat, firstInterval); \ 431 | } 432 | 433 | #define REG_CLASS_TIMER(timerMgr, func, ins, user, period, repeat, timerId) \ 434 | { \ 435 | auto callBack = std::bind(&func, ins, std::placeholders::_1, std::placeholders::_2); \ 436 | timerId = timerMgr.TimerEvtInit(std::move(callBack), (void*)ins, (void*)user); \ 437 | timerMgr.TimerEvtStart(timerId, period, repeat); \ 438 | } 439 | 440 | #define REG_CLASS_TIMER_FIRST(timerMgr, func, ins, user, period, repeat, firstInterval, timerId) \ 441 | { \ 442 | auto callBack = std::bind(&func, ins, std::placeholders::_1, std::placeholders::_2); \ 443 | timerId = timerMgr.TimerEvtInit(std::move(callBack), (void*)ins, (void*)user); \ 444 | timerMgr.TimerEvtStart(timerId, period, repeat, firstInterval); \ 445 | } 446 | 447 | #define START_TIMER(timerMgr, timerId, period, repeat) \ 448 | { \ 449 | timerMgr.TimerEvtStart(timerId, period, repeat); \ 450 | } 451 | 452 | #define STOP_TIMER(timerMgr, timerId) \ 453 | { \ 454 | timerMgr.TimerEvtStop(timerId); \ 455 | } 456 | 457 | #define UNREG_TIMER(timerMgr, timerId) \ 458 | { \ 459 | timerMgr.TimerEvtDestroy(timerId); \ 460 | } 461 | 462 | #define RUN_TIMERMGR(timerMgr, now) \ 463 | { \ 464 | timerMgr.Run(now); \ 465 | } 466 | 467 | #define UNINIT_TIMERMGR(timerMgr) \ 468 | { \ 469 | timerMgr.TimerMgrDestroy(); \ 470 | } 471 | 472 | #endif 473 | 474 | 475 | -------------------------------------------------------------------------------- /timer/TimerMgr.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itimer.c - Application Level Implementation of Linux Kernel Timer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #include 10 | #include 11 | 12 | #include "TimerMgr.h" 13 | 14 | //===================================================================== 15 | // Local Definition 16 | //===================================================================== 17 | #define ITIMER_NODE_STATE_OK 0x1981 18 | #define ITIMER_NODE_STATE_BAD 0x2014 19 | 20 | static void itimer_internal_add(itimer_core *core, itimer_node *node); 21 | static void itimer_internal_cascade(struct itimer_vec *vec, int index); 22 | static void itimer_internal_update(itimer_core *core, IUINT32 jiffies); 23 | 24 | 25 | //--------------------------------------------------------------------- 26 | // initialize timer core 27 | //--------------------------------------------------------------------- 28 | void itimer_core_init(itimer_core *core, IUINT32 jiffies) 29 | { 30 | union { struct itimer_vec *vn; struct itimer_vec_root *vr; } uv; 31 | int i; 32 | 33 | uv.vr = &core->tv1; 34 | core->timer_jiffies = jiffies; 35 | core->tvecs[0] = uv.vn; 36 | core->tvecs[1] = &core->tv2; 37 | core->tvecs[2] = &core->tv3; 38 | core->tvecs[3] = &core->tv4; 39 | core->tvecs[4] = &core->tv5; 40 | 41 | for (i = 0; i < ITVR_SIZE; i++) { 42 | ilist_init(&core->tv1.vec[i]); 43 | } 44 | 45 | for (i = 0; i < ITVN_SIZE; i++) { 46 | ilist_init(&core->tv2.vec[i]); 47 | ilist_init(&core->tv3.vec[i]); 48 | ilist_init(&core->tv4.vec[i]); 49 | ilist_init(&core->tv5.vec[i]); 50 | } 51 | } 52 | 53 | 54 | //--------------------------------------------------------------------- 55 | // destroy timer core 56 | //--------------------------------------------------------------------- 57 | void itimer_core_destroy(itimer_core *core) 58 | { 59 | int i, j; 60 | for (i = 0; i < 5; i++) { 61 | int count = (i == 0)? ITVR_SIZE : ITVN_SIZE; 62 | for (j = 0; j < count; j++) { 63 | ilist_head *root = &(core->tv1.vec[j]); 64 | if (i > 0) root = &(core->tvecs[i]->vec[j]); 65 | while (!ilist_is_empty(root)) { 66 | itimer_node *node = ilist_entry(root->next, 67 | itimer_node, head); 68 | if (!ilist_is_empty(&node->head)) { 69 | ilist_del_init(&node->head); 70 | } 71 | node->core = NULL; 72 | } 73 | } 74 | } 75 | } 76 | 77 | 78 | //--------------------------------------------------------------------- 79 | // run timer core 80 | //--------------------------------------------------------------------- 81 | void itimer_core_run(itimer_core *core, IUINT32 jiffies) 82 | { 83 | itimer_internal_update(core, jiffies); 84 | } 85 | 86 | 87 | //--------------------------------------------------------------------- 88 | // initialize node 89 | //--------------------------------------------------------------------- 90 | void itimer_node_init(itimer_node *node, void (*fn)(void*), void *data) 91 | { 92 | ilist_init(&node->head); 93 | node->expires = 0; 94 | node->state = ITIMER_NODE_STATE_OK; 95 | node->callback = fn; 96 | node->data = data; 97 | node->core = NULL; 98 | } 99 | 100 | 101 | //--------------------------------------------------------------------- 102 | // destroy node 103 | //--------------------------------------------------------------------- 104 | void itimer_node_destroy(itimer_node *node) 105 | { 106 | if (node->state != ITIMER_NODE_STATE_OK) { 107 | assert(node->state == ITIMER_NODE_STATE_OK); 108 | return ; 109 | } 110 | if (!ilist_is_empty(&node->head)) { 111 | ilist_del_init(&node->head); 112 | node->core = NULL; 113 | } 114 | node->state = ITIMER_NODE_STATE_BAD; 115 | node->callback = NULL; 116 | node->data = NULL; 117 | node->core = NULL; 118 | node->expires = 0; 119 | } 120 | 121 | 122 | //--------------------------------------------------------------------- 123 | // add node to core 124 | //--------------------------------------------------------------------- 125 | void itimer_node_add(itimer_core *core, itimer_node *node, IUINT32 expires) 126 | { 127 | if (node->state != ITIMER_NODE_STATE_OK) { 128 | assert(node->state == ITIMER_NODE_STATE_OK); 129 | return ; 130 | } 131 | 132 | if (!ilist_is_empty(&node->head)) { 133 | ilist_del_init(&node->head); 134 | node->core = NULL; 135 | } 136 | 137 | node->expires = expires; 138 | 139 | itimer_internal_add(core, node); 140 | } 141 | 142 | 143 | //--------------------------------------------------------------------- 144 | // remove node from core 145 | //--------------------------------------------------------------------- 146 | int itimer_node_del(itimer_core *core, itimer_node *node) 147 | { 148 | if (node->state != ITIMER_NODE_STATE_OK) { 149 | assert(node->state == ITIMER_NODE_STATE_OK); 150 | return -1; 151 | } 152 | if (!ilist_is_empty(&node->head)) { 153 | assert(node->core != NULL); 154 | ilist_del_init(&node->head); 155 | node->core = NULL; 156 | return 1; 157 | } 158 | return 0; 159 | } 160 | 161 | 162 | //--------------------------------------------------------------------- 163 | // modify node 164 | //--------------------------------------------------------------------- 165 | int itimer_node_mod(itimer_core *core, itimer_node *node, IUINT32 expires) 166 | { 167 | int ret = itimer_node_del(core, node); 168 | itimer_node_add(core, node, expires); 169 | return ret; 170 | } 171 | 172 | 173 | //--------------------------------------------------------------------- 174 | // itimer_internal_add 175 | //--------------------------------------------------------------------- 176 | static void itimer_internal_add(itimer_core *core, itimer_node *node) 177 | { 178 | IUINT32 expires = node->expires; 179 | IUINT32 idx = expires - core->timer_jiffies; 180 | ilist_head *vec = NULL; 181 | 182 | if (idx < ITVR_SIZE) { 183 | int i = expires & ITVR_MASK; 184 | vec = core->tv1.vec + i; 185 | } 186 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS))) { 187 | int i = (expires >> ITVR_BITS) & ITVN_MASK; 188 | vec = core->tv2.vec + i; 189 | } 190 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 2))) { 191 | int i = (expires >> (ITVR_BITS + ITVN_BITS)) & ITVN_MASK; 192 | vec = core->tv3.vec + i; 193 | } 194 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 3))) { 195 | int i = (expires >> (ITVR_BITS + ITVN_BITS * 2)) & ITVN_MASK; 196 | vec = core->tv4.vec + i; 197 | } 198 | else if ((IINT32)idx < 0) { 199 | vec = core->tv1.vec + (core->timer_jiffies & ITVR_MASK); 200 | } 201 | else { 202 | int i = (expires >> (ITVR_BITS + ITVN_BITS * 3)) & ITVN_MASK; 203 | vec = core->tv5.vec + i; 204 | } 205 | 206 | ilist_add_tail(&node->head, vec); 207 | node->core = core; 208 | } 209 | 210 | 211 | //--------------------------------------------------------------------- 212 | // itimer_internal_cascade 213 | //--------------------------------------------------------------------- 214 | static void itimer_internal_cascade(struct itimer_vec *tv, int index) 215 | { 216 | ilist_head queued; 217 | ilist_init(&queued); 218 | ilist_splice_init(tv->vec + index, &queued); 219 | while (!ilist_is_empty(&queued)) { 220 | itimer_node *node; 221 | node = ilist_entry(queued.next, itimer_node, head); 222 | ilist_del_init(&node->head); 223 | itimer_internal_add(node->core, node); 224 | } 225 | } 226 | 227 | 228 | //--------------------------------------------------------------------- 229 | // itimer_internal_update 230 | //--------------------------------------------------------------------- 231 | static void itimer_internal_update(itimer_core *core, IUINT32 jiffies) 232 | { 233 | #define ITIMER_INDEX(C, N) \ 234 | (((C)->timer_jiffies >> (ITVR_BITS + (N) * ITVN_BITS)) & ITVN_MASK) 235 | while ((IINT32)(jiffies - core->timer_jiffies) >= 0) { 236 | ilist_head queued; 237 | int index = core->timer_jiffies & ITVR_MASK; 238 | ilist_init(&queued); 239 | if (index == 0) { 240 | int i = ITIMER_INDEX(core, 0); 241 | itimer_internal_cascade(&core->tv2, i); 242 | if (i == 0) { 243 | i = ITIMER_INDEX(core, 1); 244 | itimer_internal_cascade(&core->tv3, i); 245 | if (i == 0) { 246 | i = ITIMER_INDEX(core, 2); 247 | itimer_internal_cascade(&core->tv4, i); 248 | if (i == 0) { 249 | i = ITIMER_INDEX(core, 3); 250 | itimer_internal_cascade(&core->tv5, i); 251 | } 252 | } 253 | } 254 | } 255 | core->timer_jiffies++; 256 | ilist_splice_init(core->tv1.vec + index, &queued); 257 | while (!ilist_is_empty(&queued)) { 258 | itimer_node *node; 259 | void(*fn)(void*); 260 | void *data; 261 | node = ilist_entry(queued.next, itimer_node, head); 262 | fn = node->callback; 263 | data = node->data; 264 | ilist_del_init(&node->head); 265 | node->core = NULL; 266 | if (fn) fn(data); 267 | } 268 | } 269 | #undef ITIMER_INDEX 270 | } 271 | 272 | 273 | 274 | //===================================================================== 275 | // Timer Manager 276 | //===================================================================== 277 | 278 | // initialize timer manager 279 | // millisec - current time stamp 280 | // interval - internal working interval 281 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 millisec, IUINT32 interval) 282 | { 283 | mgr->current = millisec; 284 | mgr->interval = (interval < 1)? 1 : interval; 285 | mgr->jiffies = 0; 286 | mgr->millisec = 0; 287 | itimer_core_init(&mgr->core, mgr->jiffies); 288 | } 289 | 290 | // destroy timer manager 291 | void itimer_mgr_destroy(itimer_mgr *mgr) 292 | { 293 | itimer_core_destroy(&mgr->core); 294 | } 295 | 296 | #ifndef ITIMER_MGR_LIMIT 297 | #define ITIMER_MGR_LIMIT 300000 // 300 seconds 298 | #endif 299 | 300 | // run timer events 301 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec) 302 | { 303 | IUINT32 interval = mgr->interval; 304 | IINT32 limit = (IINT32)interval * 64; 305 | IINT32 diff = (IINT32)(millisec - mgr->millisec); 306 | if (diff > ITIMER_MGR_LIMIT + limit) { 307 | mgr->millisec = millisec; 308 | } 309 | else if (diff < -ITIMER_MGR_LIMIT - limit) { 310 | mgr->millisec = millisec; 311 | } 312 | while ((IINT32)(millisec - mgr->millisec) >= 0) { 313 | itimer_core_run(&mgr->core, mgr->jiffies); 314 | mgr->jiffies++; 315 | mgr->current += mgr->interval; 316 | mgr->millisec += mgr->interval; 317 | } 318 | } 319 | 320 | // callback 321 | static void itimer_evt_cb(void *p) 322 | { 323 | itimer_evt *evt = (itimer_evt*)p; 324 | itimer_mgr *mgr = evt->mgr; 325 | IUINT32 current = mgr->current; 326 | int count = 0; 327 | int stop = 0; 328 | while (current >= evt->slap) { 329 | count++; 330 | evt->slap += evt->period; 331 | if (evt->repeat == 1) { 332 | stop = 1; 333 | break; 334 | } 335 | if (evt->repeat > 1) { 336 | evt->repeat--; 337 | } 338 | } 339 | if (stop == 0) { 340 | IUINT32 interval = mgr->interval; 341 | IUINT32 expires = (evt->slap - current + interval - 1) / interval; 342 | if (expires >= 0x70000000) expires = 0x70000000; 343 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 344 | } else { 345 | itimer_evt_stop(mgr, evt); 346 | } 347 | evt->running = 1; 348 | for (; count > 0; count--) { 349 | if (evt->fn && evt->running) { 350 | evt->fn(evt->data, evt->user); 351 | } else { 352 | break; 353 | } 354 | } 355 | evt->running = 0; 356 | } 357 | 358 | // initialize timer event 359 | void itimer_evt_init(itimer_evt *evt, std::function&& fn, 360 | void *data, void *user) 361 | { 362 | itimer_node_init(&evt->node, itimer_evt_cb, evt); 363 | evt->fn = std::move(fn); 364 | evt->data = data; 365 | evt->user = user; 366 | evt->mgr = NULL; 367 | evt->period = 0; 368 | evt->slap = 0; 369 | evt->repeat = 0; 370 | evt->running = 0; 371 | } 372 | 373 | // destroy timer event 374 | void itimer_evt_destroy(itimer_evt *evt) 375 | { 376 | itimer_node_destroy(&evt->node); 377 | evt->fn = nullptr; 378 | evt->data = NULL; 379 | evt->user = NULL; 380 | evt->mgr = NULL; 381 | evt->period = 0; 382 | evt->slap = 0; 383 | evt->repeat = 0; 384 | evt->running = 0; 385 | } 386 | 387 | // start timer: repeat <= 0 (infinite repeat) 388 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 389 | IUINT32 period, int repeat, IUINT32 firstInterval) 390 | { 391 | IUINT32 interval = mgr->interval; 392 | IUINT32 expires; 393 | if (evt->mgr) { 394 | itimer_evt_stop(evt->mgr, evt); 395 | } 396 | evt->period = period; 397 | evt->repeat = repeat; 398 | evt->slap = mgr->current + firstInterval + period; 399 | evt->mgr = mgr; 400 | expires = (evt->slap - mgr->current + interval - 1) / interval; 401 | if (expires >= 0x70000000) expires = 0x70000000; 402 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 403 | evt->running = 0; 404 | } 405 | 406 | // stop timer 407 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt) 408 | { 409 | if (evt->mgr) { 410 | itimer_node_del(&evt->mgr->core, &evt->node); 411 | evt->mgr = NULL; 412 | } 413 | evt->running = 0; 414 | } 415 | 416 | 417 | //下面采用C++简单封装一下便于使用 418 | TimerMgr::TimerMgr(uint64_t curMillSec/*ms*/, uint32_t interval/*ms*/) 419 | { 420 | mMgr = new itimer_mgr(); 421 | itimer_mgr_init(mMgr, static_cast(curMillSec) , interval); 422 | } 423 | 424 | TimerMgr::~TimerMgr() 425 | { 426 | for(auto& iter : mEvt) 427 | { 428 | if(iter.second != nullptr) 429 | { 430 | itimer_evt_destroy(iter.second); 431 | } 432 | } 433 | 434 | TimerMgrDestroy(); 435 | } 436 | 437 | uint64_t TimerMgr::TimerEvtInit(EvtCallBack&& callBack, void* data, void* user) 438 | { 439 | itimer_evt* evt = new itimer_evt(); 440 | evt->evtId = ++mIndex; 441 | assert(evt->evtId != 0); 442 | itimer_evt_init(evt, std::forward(callBack), data, user); 443 | AddEvt(evt); 444 | return evt->evtId; 445 | } 446 | 447 | void TimerMgr::TimerEvtStart(uint64_t evtId, uint32_t period, uint32_t repeat, uint32_t firstInterval) 448 | { 449 | itimer_evt* pEvt = FindEvt(evtId); 450 | if(pEvt != nullptr) 451 | { 452 | itimer_evt_start(mMgr, pEvt, period, repeat, firstInterval); 453 | } 454 | } 455 | 456 | void TimerMgr::TimerEvtStop(uint64_t evtId) 457 | { 458 | itimer_evt* pEvt = FindEvt(evtId); 459 | if(pEvt != nullptr && mMgr != nullptr) 460 | { 461 | itimer_evt_stop(mMgr,pEvt); 462 | } 463 | } 464 | 465 | void TimerMgr::TimerEvtDestroy(uint64_t evtId) 466 | { 467 | itimer_evt* pEvt = FindEvt(evtId); 468 | if(pEvt != nullptr) 469 | { 470 | itimer_evt_destroy(pEvt); 471 | RemoveEvt(evtId); 472 | delete pEvt; 473 | } 474 | } 475 | 476 | void TimerMgr::TimerMgrDestroy() 477 | { 478 | for(auto& iter : mEvt) 479 | { 480 | if(iter.second != nullptr) 481 | { 482 | itimer_evt_destroy(iter.second); 483 | } 484 | } 485 | 486 | if(mMgr != nullptr) 487 | { 488 | itimer_mgr_destroy(mMgr); 489 | delete mMgr; 490 | mMgr = nullptr; 491 | } 492 | 493 | mIndex=0; 494 | mEvt.clear(); 495 | } 496 | 497 | void TimerMgr::Run(uint64_t curMillSec) 498 | { 499 | itimer_mgr_run(mMgr, static_cast(curMillSec)); 500 | } 501 | 502 | void TimerMgr::AddEvt(itimer_evt* evt) 503 | { 504 | itimer_evt* pEvt = FindEvt(evt->evtId); 505 | if(pEvt == nullptr) 506 | { 507 | mEvt[evt->evtId] = evt; 508 | } 509 | } 510 | 511 | itimer_evt* TimerMgr::FindEvt(uint64_t evtId) 512 | { 513 | const auto& iter = mEvt.find(evtId); 514 | if(iter != mEvt.end()) 515 | { 516 | return iter->second; 517 | } 518 | return nullptr; 519 | } 520 | 521 | void TimerMgr::RemoveEvt(uint64_t evtId) 522 | { 523 | mEvt.erase(evtId); 524 | } 525 | 526 | --------------------------------------------------------------------------------