#ifndef CPR_THREAD_POOL_H #define CPR_THREAD_POOL_H #include #include #include #include #include #include #include #include #include #include #include #define CPR_DEFAULT_THREAD_POOL_MAX_THREAD_NUM std::thread::hardware_concurrency() constexpr size_t CPR_DEFAULT_THREAD_POOL_MIN_THREAD_NUM = 1; constexpr std::chrono::milliseconds CPR_DEFAULT_THREAD_POOL_MAX_IDLE_TIME{60000}; namespace cpr { class ThreadPool { public: using Task = std::function; explicit ThreadPool(size_t min_threads = CPR_DEFAULT_THREAD_POOL_MIN_THREAD_NUM, size_t max_threads = CPR_DEFAULT_THREAD_POOL_MAX_THREAD_NUM, std::chrono::milliseconds max_idle_ms = CPR_DEFAULT_THREAD_POOL_MAX_IDLE_TIME); virtual ~ThreadPool(); void SetMinThreadNum(size_t min_threads) { min_thread_num = min_threads; } void SetMaxThreadNum(size_t max_threads) { max_thread_num = max_threads; } void SetMaxIdleTime(std::chrono::milliseconds ms) { max_idle_time = ms; } size_t GetCurrentThreadNum() { return cur_thread_num; } size_t GetIdleThreadNum() { return idle_thread_num; } bool IsStarted() { return status != STOP; } bool IsStopped() { return status == STOP; } int Start(size_t start_threads = 0); int Stop(); int Pause(); int Resume(); int Wait(); /** * Return a future, calling future.get() will wait task done and return RetType. * Submit(fn, args...) * Submit(std::bind(&Class::mem_fn, &obj)) * Submit(std::mem_fn(&Class::mem_fn, &obj)) **/ template auto Submit(Fn&& fn, Args&&... args) { if (status == STOP) { Start(); } if (idle_thread_num <= 0 && cur_thread_num < max_thread_num) { CreateThread(); } using RetType = decltype(fn(args...)); auto task = std::make_shared >(std::bind(std::forward(fn), std::forward(args)...)); std::future future = task->get_future(); { std::lock_guard locker(task_mutex); tasks.emplace([task] { (*task)(); }); } task_cond.notify_one(); return future; } private: bool CreateThread(); void AddThread(std::thread* thread); void DelThread(std::thread::id id); public: size_t min_thread_num; size_t max_thread_num; std::chrono::milliseconds max_idle_time; private: enum Status { STOP, RUNNING, PAUSE, }; struct ThreadData { std::shared_ptr thread; std::thread::id id; Status status; time_t start_time; time_t stop_time; }; std::atomic status; std::atomic cur_thread_num; std::atomic idle_thread_num; std::list threads; std::mutex thread_mutex; std::queue tasks; std::mutex task_mutex; std::condition_variable task_cond; }; } // namespace cpr #endif