26 #include <condition_variable>
34 #include <type_traits>
40 template<
class F,
class... Args>
41 auto enqueue(F&& f, Args&&... args)
42 -> std::future<
typename std::invoke_result<F,Args...>::type>;
68 #if _MSC_VER >= 1200 && MSC_VER <= 1910
70 GetSystemInfo(&sysinfo);
71 ret = sysinfo.dwNumberOfProcessors;
74 ret = std::thread::hardware_concurrency();
82 std::queue< std::function<void()> >
tasks;
89 std::map<std::thread::id, int>
id_map;
100 : stop(false), m_num_threads(threads)
105 for(
size_t i = 0;i<threads;++i)
111 std::function<void()> task;
114 std::unique_lock<std::mutex> lock(this->queue_mutex);
115 this->condition.wait(lock,
116 [this]{ return this->stop || !this->tasks.empty(); });
117 if(this->stop && this->tasks.empty())
119 task = std::move(this->tasks.front());
127 int thread_count = 0;
128 for(std::thread &worker: workers){
129 id_map[worker.get_id()] = thread_count;
137 CPU_SET(thread_count, &cpuset);
138 int rc = pthread_setaffinity_np(worker.native_handle(),
139 sizeof(cpu_set_t), &cpuset);
141 std::cerr <<
"Error calling pthread_setaffinity_np: " << rc <<
"\n";
150 template<
class F,
class... Args>
152 -> std::future<
typename std::invoke_result<F,Args...>::type>
154 assert(m_num_threads > 1);
155 using return_type =
typename std::invoke_result<F,Args...>::type;
157 auto task = std::make_shared< std::packaged_task<return_type()> >(
158 std::bind(std::forward<F>(f), std::forward<Args>(args)...)
161 std::future<return_type> res = task->get_future();
163 std::unique_lock<std::mutex> lock(queue_mutex);
167 throw std::runtime_error(
"enqueue on stopped ThreadPool");
169 tasks.emplace([task](){ (*task)(); });
171 condition.notify_one();
183 for(std::thread &worker:
workers)