├── README.md ├── LICENSE ├── example └── main.cpp └── src ├── cppThreadPool.cpp └── cppThreadPool.h /README.md: -------------------------------------------------------------------------------- 1 | # cppThreadPool 2 | C++ thread pool class 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 LongTengFly 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | // g++ -o testtp ../src/cppThreadPool.cpp main.cpp -lpthread 2 | 3 | #include 4 | #include "../src/cppThreadPool.h" 5 | 6 | using namespace std; 7 | 8 | void func1(int a) 9 | { 10 | cout << "func1() a=" << a << endl; 11 | } 12 | void func2(int a, string b) 13 | { 14 | cout << "func2() a=" << a << ", b=" << b<< endl; 15 | } 16 | 17 | void func3() 18 | { 19 | cout<<"func3"< ret01=threadpool.exec(func1_future,10); 58 | future ret02=threadpool.exec(func2_future,20,"FLY."); 59 | 60 | threadpool.waitForAllDone(); 61 | 62 | cout<<"ret01 = "< lock(_mutex); 18 | if(!_threads.empty()) 19 | return false; 20 | _threadNum=num; 21 | return true; 22 | } 23 | 24 | void CPP_ThreadPool::stop() 25 | { 26 | // 注意要有这个{},不然会死锁。 27 | { 28 | unique_lock lock(_mutex); 29 | _bTerminate=true; 30 | _condition.notify_all(); 31 | } 32 | size_t thdCount=_threads.size(); 33 | for(size_t i=0;ijoinable()) 36 | { 37 | _threads[i]->join(); 38 | } 39 | delete _threads[i]; 40 | _threads[i]=NULL; 41 | } 42 | unique_lock lock(_mutex); 43 | _threads.clear(); 44 | } 45 | 46 | bool CPP_ThreadPool::start() 47 | { 48 | unique_lock lock(_mutex); 49 | if(!_threads.empty()) 50 | return false; 51 | 52 | for(size_t i=0;i<_threadNum;i++) 53 | { 54 | _threads.push_back(new thread(&CPP_ThreadPool::run,this)); 55 | } 56 | return true; 57 | } 58 | 59 | bool CPP_ThreadPool::get(TaskFuncPtr& task) 60 | { 61 | unique_lock lock(_mutex); 62 | if(_tasks.empty()) 63 | { 64 | _condition.wait(lock,[this]{ 65 | return _bTerminate || !_tasks.empty(); 66 | }); 67 | } 68 | 69 | if(_bTerminate) 70 | return false; 71 | 72 | if(!_tasks.empty()) 73 | { 74 | task=move(_tasks.front()); 75 | _tasks.pop(); 76 | return true; 77 | } 78 | return false; 79 | } 80 | 81 | // 执行任务的线程 82 | void CPP_ThreadPool::run() 83 | { 84 | while(!isTerminate()) 85 | { 86 | TaskFuncPtr task; 87 | // 读取任务 88 | bool ok=get(task); 89 | if(ok) 90 | { 91 | ++_atomic; 92 | try 93 | { 94 | if(task->_expireTime!=0 && task->_expireTime < TNOWMS) 95 | { 96 | // 处理超时任务 97 | } 98 | else 99 | task->_func();//执行任务 100 | } 101 | catch(...) 102 | {} 103 | --_atomic; 104 | // 任务执行完毕,这里只是为了通知waitForAllDone 105 | unique_lock lock(_mutex); 106 | if(_atomic==0 && _tasks.empty()) 107 | _condition.notify_all(); 108 | } 109 | } 110 | } 111 | 112 | bool CPP_ThreadPool::waitForAllDone(int millsecond) 113 | { 114 | unique_lock lock(_mutex); 115 | if(_tasks.empty()) 116 | return true; 117 | if(millsecond<0) 118 | { 119 | _condition.wait(lock,[this]{ return _tasks.empty();}); 120 | return true; 121 | } 122 | else 123 | { 124 | return _condition.wait_for(lock,chrono::milliseconds(millsecond),[this]{ return _tasks.empty();}); 125 | } 126 | } 127 | 128 | int gettimeofday(struct timeval &tv) 129 | { 130 | #if WIN32 131 | time_t clock; 132 | struct tm tm; 133 | SYSTEMTIME wtm; 134 | GetLocalTime(&wtm); 135 | tm.tm_year = wtm.wYear - 1900; 136 | tm.tm_mon = wtm.wMonth - 1; 137 | tm.tm_mday = wtm.wDay; 138 | m.tm_hour = wtm.wHour; 139 | tm.tm_min = wtm.wMinute; 140 | tm.tm_sec = wtm.wSecond; 141 | tm. tm_isdst = -1; 142 | clock = mktime(&tm); 143 | tv.tv_sec = clock; 144 | tv.tv_usec = wtm.wMilliseconds * 1000; 145 | return 0; 146 | #else 147 | return ::gettimeofday(&tv, 0); 148 | #endif 149 | 150 | } 151 | 152 | void getNow(timeval *tv) 153 | { 154 | #if TARGET_PLATFORM_IOS || TARGET_PLATFORM_LINUX 155 | int idx = _buf_idx; 156 | *tv = _t[idx]; 157 | if(fabs(_cpu_cycle - 0) < 0.0001 && _use_tsc) 158 | { 159 | addTimeOffset(*tv, idx); 160 | } 161 | else 162 | { 163 | TC_Common::gettimeofday(*tv); 164 | } 165 | #else 166 | gettimeofday(*tv); 167 | #endif 168 | 169 | } 170 | 171 | int64_t getNowMs() 172 | { 173 | struct timeval tv; 174 | getNow(&tv); 175 | return tv.tv_sec * (int64_t)1000 + tv.tv_usec / 1000; 176 | } 177 | -------------------------------------------------------------------------------- /src/cppThreadPool.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPP_THREAD_POOL_H_ 2 | #define _CPP_THREAD_POOL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef WIN32 14 | #include 15 | #else 16 | #include 17 | #endif 18 | 19 | using namespace std; 20 | 21 | void getNow(timeval *tv); 22 | int64_t getNowMs(); 23 | 24 | #define TNOW getNow() 25 | #define TNOWMS getNowMs() 26 | 27 | class CPP_ThreadPool{ 28 | protected: 29 | struct TaskFunc{ 30 | TaskFunc(uint64_t expireTime):_expireTime(expireTime){} 31 | int64_t _expireTime=0;//超时的绝对时间 32 | function _func; 33 | }; 34 | typedef shared_ptr TaskFuncPtr; 35 | 36 | /* 37 | * @brief 获取任务 ** 38 | *@return TaskFuncPtr 39 | */ 40 | bool get(TaskFuncPtr& task); 41 | 42 | /* 43 | * @brief 线程池是否退出 44 | */ 45 | bool isTerminate() 46 | { 47 | return _bTerminate; 48 | } 49 | 50 | /* 51 | * @brief 线程运行态 52 | */ 53 | void run(); 54 | 55 | public: 56 | /* 57 | * @brief 构造函数 58 | */ 59 | CPP_ThreadPool(); 60 | 61 | /* 62 | * @brief 析构, 会停止所有线程 63 | */ 64 | virtual ~CPP_ThreadPool(); 65 | 66 | /* 67 | * * @brief 初始化. 68 | * * @param num 工作线程个数 69 | */ 70 | bool init(size_t num); 71 | 72 | /* 73 | * @brief 停止所有线程, 会等待所有线程结束 74 | */ 75 | void stop(); 76 | 77 | /* 78 | * @brief 启动所有线程 79 | */ 80 | bool start(); 81 | 82 | /* 83 | * @brief 等待当前任务队列中, 所有工作全部结束(队列无任务). 84 | * @param millsecond 等待的时间(ms), -1:永远等待 85 | * @return true, 所有工作都处理完毕 86 | * false,超时退出 87 | */ 88 | bool waitForAllDone(int millsecond=-1); 89 | 90 | /* 91 | * @brief 获取线程个数. 92 | * @return size_t 线程个数 93 | */ 94 | size_t getThreadNum() 95 | { 96 | unique_lock lock(_mutex); 97 | return _threads.size(); 98 | } 99 | 100 | /* 101 | * @brief 获取当前线程池的任务数 102 | * @return size_t 线程池的任务数 103 | */ 104 | size_t getJobNum() 105 | { 106 | unique_lock lock(_mutex); 107 | return _tasks.size(); 108 | } 109 | 110 | /* 111 | * @brief 用线程池启用任务(F是function, Args是参数) ** 112 | * @param ParentFunctor 113 | * @param tf 114 | * @return 返回任务的future对象, 可以通过这个对象来获取返回值 115 | */ 116 | template 117 | auto exec(F&& f, Args&&... args)->future 118 | { 119 | return exec(0,f,args...); 120 | } 121 | 122 | /* 123 | * unused. 124 | * 125 | * @brief 用线程池启用任务(F是function, Args是参数) 126 | * @param 超时时间 ,单位ms (为0时不做超时控制) ;若任务超时,此任务将被丢弃 127 | * @param bind function 128 | * @return 返回任务的future对象, 可以通过这个对象来获取返回值 129 | * 130 | * template 131 | * 它是c++里新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数、任意类型的参数 132 | * auto exec(F &&f, Args &&... args) -> std::future 133 | * std::future:返回future,调用者可以通过future获取返回值 134 | * 返回值后置 135 | */ 136 | template 137 | auto exec(int64_t timeoutMs,F&& f,Args&&... args) -> future 138 | { 139 | //获取现在时间 140 | int64_t expireTime=(timeoutMs==0)?0:TNOWMS+timeoutMs; 141 | // 定义返回值类型 142 | using retType=decltype(f(args...)); 143 | // 封装任务 144 | auto task=make_shared>(bind(forward(f),forward(args)...)); 145 | // 封装任务指针,设置过期时间 146 | TaskFuncPtr fPtr=make_shared(expireTime); 147 | fPtr->_func=[task](){ 148 | (*task)(); 149 | }; 150 | 151 | unique_lock lock(_mutex); 152 | // 插入任务 153 | _tasks.push(fPtr); 154 | // 唤醒阻塞的线程,可以考虑只有任务队列为空的情 况再去notify 155 | _condition.notify_one(); 156 | 157 | return task->get_future(); 158 | } 159 | 160 | protected: 161 | size_t _threadNum;//线程数量 162 | bool _bTerminate;//判定是否终止线程池 163 | mutex _mutex; //唯一锁 164 | vector _threads; //工作线程数组 165 | queue _tasks; //任务队列 166 | condition_variable _condition;//条件变量 167 | atomic _atomic{0};//原子变量 168 | }; 169 | 170 | 171 | #endif --------------------------------------------------------------------------------