#include #include #include #include #include namespace { const int NUM_ITERATIONS = 100000; static int DID_RUN = 0; int workload() { DID_RUN++; return rand(); } } namespace plain { void run() { for (int i = 0; i < NUM_ITERATIONS; ++i) { std::thread thread(&workload); thread.join(); } } } // code based on: http://progsch.net/wordpress/?p=81 namespace reusable { class ReusableThread; // our worker thread objects class Worker { public: Worker(ReusableThread *thread) : thread(thread) { } void operator()(); private: ReusableThread *thread; }; // the actual thread pool class ReusableThread { public: ReusableThread(); ~ReusableThread(); template void run(F f); void join(); private: friend class Worker; // need to keep track of thread so we can join it std::thread worker; // the task std::function task; // synchronization std::mutex mutex; std::condition_variable condition; bool stop; }; // the constructor just launches some amount of workers ReusableThread::ReusableThread() : worker(std::thread(Worker(this))) , stop(false) { } // the destructor joins all threads ReusableThread::~ReusableThread() { // stop worker and join it stop = true; condition.notify_all(); worker.join(); } // add new work item to the pool template void ReusableThread::run(F f) { { std::unique_lock lock(mutex); assert(!task); // add the task task = {f}; } // release lock // wake up the worker condition.notify_one(); } void ReusableThread::join() { std::unique_lock lock(mutex); while (task) { condition.wait(lock); } } void Worker::operator()() { while(true) { { // acquire mutex and keep it to ensure no new task is enqueued while the worker is running std::unique_lock lock(thread->mutex); // look for a work item while (!thread->stop && !thread->task) { // if there are none wait for notification thread->condition.wait(lock); } if (thread->stop) // exit if the pool is stopped return; // execute the task thread->task(); // reset it thread->task = {}; } // notify other thread that we finished thread->condition.notify_one(); } } void run() { ReusableThread thread; for (int i = 0; i < NUM_ITERATIONS; ++i) { thread.run(&workload); thread.join(); } } } int main(int argc, char** argv) { if (argc == 2) { reusable::run(); } else { plain::run(); } std::cout << DID_RUN << std::endl; return 0; }