[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/dabbertorres/ThreadPool/master/ThreadPool.cpp [Back]  [Original]

#include "ThreadPool.hpp"

#include 
#include 

namespace dbr
{
    namespace cc
    {
        ThreadPool::ThreadPool(std::size_t threadCount)
            : threadsWaiting(0),
            terminate(false),
            paused(false)
        {
            if (threadCount==0)
                threadCount = std::thread::hardware_concurrency();
            // prevent potential reallocation, thereby screwing up all our hopes and dreams
            threads.reserve(threadCount);
            std::generate_n(std::back_inserter(threads), threadCount, [this]() { return std::thread{ threadTask, this }; });
        }

        ThreadPool::~ThreadPool()
        {
            clear();

            // tell threads to stop when they can
            terminate = true;
            jobsAvailable.notify_all();

            // wait for all threads to finish
            for (auto& t : threads)
            {
                if (t.joinable())
                    t.join();
            }
        }

        std::size_t ThreadPool::threadCount() const
        {
            return threads.size();
        }

        std::size_t ThreadPool::waitingJobs() const
        {
            std::lock_guard jobLock(jobsMutex);
            return jobs.size();
        }

        ThreadPool::Ids ThreadPool::ids() const
        {
            Ids ret(threads.size());

            std::transform(threads.begin(), threads.end(), ret.begin(), [](auto& t) { return t.get_id(); });

            return ret;
        }

        void ThreadPool::clear()
        {
            std::lock_guard lock{ jobsMutex };

            while (!jobs.empty())
                jobs.pop();
        }

        void ThreadPool::pause(bool state)
        {
            paused = state;

            if (!paused)
                jobsAvailable.notify_all();
        }

        void ThreadPool::wait()
        {
            // we're done waiting once all threads are waiting
            while (threadsWaiting != threads.size());
        }

        void ThreadPool::threadTask(ThreadPool* pool)
        {
            // loop until we break (to keep thread alive)
            while (true)
            {
                // if we need to finish, let's do it before we get into
                // all the expensive synchronization stuff
                if (pool->terminate)
                    break;

                std::unique_lock jobsLock{ pool->jobsMutex };

                // if there are no more jobs, or we're paused, go into waiting mode
                if (pool->jobs.empty() || pool->paused)
                {
                    ++pool->threadsWaiting;
                    pool->jobsAvailable.wait(jobsLock, [&]()
                    {
                        return pool->terminate || !(pool->jobs.empty() || pool->paused);
                    });
                    --pool->threadsWaiting;
                }

                // check once more before grabbing a job, since we want to stop ASAP
                if (pool->terminate)
                    break;

                // take next job
                auto job = std::move(pool->jobs.front());
                pool->jobs.pop();

                jobsLock.unlock();

                job();
            }
        }
    }
}

Web Proxy Viewer  |  New URL  |  Original Page