threadPool.cpp
· 1.4 KiB · C++
Raw
#include "threadPool.h"
ThreadPool::ThreadPool()
: m_busyThreads{ 0 }
, m_threads{std::vector<std::thread>(std::thread::hardware_concurrency())}
, m_stopRequested{ false }
{
for (size_t i = 0; i < std::thread::hardware_concurrency(); ++i)
{
m_threads[i] = std::thread(ThreadWorker(this));
}
}
ThreadPool::~ThreadPool()
{
{
std::lock_guard<std::mutex> lock(m_mutex);
m_stopRequested = true;
m_condition_task.notify_all();
}
for (size_t i = 0; i < m_threads.size(); ++i)
{
if (m_threads[i].joinable())
{
m_threads[i].join();
}
}
}
void ThreadPool::wait()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_condition_finish.wait(lock, [this] {
return m_tasks.empty() && m_busyThreads == 0;
});
lock.unlock();
}
ThreadWorker::ThreadWorker(ThreadPool* pool)
: m_pool(pool)
{}
ThreadWorker::~ThreadWorker()
{}
void ThreadWorker::operator()()
{
std::unique_lock<std::mutex> lock(m_pool->m_mutex);
while (!m_pool->m_stopRequested || (m_pool->m_stopRequested && !m_pool->m_tasks.empty()))
{
m_pool->m_condition_task.wait(lock, [this] {
return m_pool->m_stopRequested || !m_pool->m_tasks.empty();
});
if (!m_pool->m_tasks.empty())
{
m_pool->m_busyThreads++;
auto task = m_pool->m_tasks.front();
m_pool->m_tasks.pop();
lock.unlock();
task();
lock.lock();
m_pool->m_busyThreads--;
m_pool->m_condition_finish.notify_one();
}
}
}
| 1 | |
| 2 | #include "threadPool.h" |
| 3 | |
| 4 | ThreadPool::ThreadPool() |
| 5 | : m_busyThreads{ 0 } |
| 6 | , m_threads{std::vector<std::thread>(std::thread::hardware_concurrency())} |
| 7 | , m_stopRequested{ false } |
| 8 | { |
| 9 | for (size_t i = 0; i < std::thread::hardware_concurrency(); ++i) |
| 10 | { |
| 11 | m_threads[i] = std::thread(ThreadWorker(this)); |
| 12 | } |
| 13 | } |
| 14 | |
| 15 | ThreadPool::~ThreadPool() |
| 16 | { |
| 17 | { |
| 18 | std::lock_guard<std::mutex> lock(m_mutex); |
| 19 | m_stopRequested = true; |
| 20 | m_condition_task.notify_all(); |
| 21 | } |
| 22 | |
| 23 | for (size_t i = 0; i < m_threads.size(); ++i) |
| 24 | { |
| 25 | if (m_threads[i].joinable()) |
| 26 | { |
| 27 | m_threads[i].join(); |
| 28 | } |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | void ThreadPool::wait() |
| 33 | { |
| 34 | std::unique_lock<std::mutex> lock(m_mutex); |
| 35 | m_condition_finish.wait(lock, [this] { |
| 36 | return m_tasks.empty() && m_busyThreads == 0; |
| 37 | }); |
| 38 | lock.unlock(); |
| 39 | } |
| 40 | |
| 41 | ThreadWorker::ThreadWorker(ThreadPool* pool) |
| 42 | : m_pool(pool) |
| 43 | {} |
| 44 | |
| 45 | ThreadWorker::~ThreadWorker() |
| 46 | {} |
| 47 | |
| 48 | void ThreadWorker::operator()() |
| 49 | { |
| 50 | std::unique_lock<std::mutex> lock(m_pool->m_mutex); |
| 51 | while (!m_pool->m_stopRequested || (m_pool->m_stopRequested && !m_pool->m_tasks.empty())) |
| 52 | { |
| 53 | m_pool->m_condition_task.wait(lock, [this] { |
| 54 | return m_pool->m_stopRequested || !m_pool->m_tasks.empty(); |
| 55 | }); |
| 56 | |
| 57 | if (!m_pool->m_tasks.empty()) |
| 58 | { |
| 59 | m_pool->m_busyThreads++; |
| 60 | |
| 61 | auto task = m_pool->m_tasks.front(); |
| 62 | m_pool->m_tasks.pop(); |
| 63 | lock.unlock(); |
| 64 | task(); |
| 65 | lock.lock(); |
| 66 | |
| 67 | m_pool->m_busyThreads--; |
| 68 | m_pool->m_condition_finish.notify_one(); |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | |
| 73 |
threadPool.h
· 1.4 KiB · C
Raw
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>
#include <queue>
#include <vector>
#include <memory>
#include <condition_variable>
class ThreadPool
{
public:
ThreadPool();
~ThreadPool();
ThreadPool(const ThreadPool&) = delete;
ThreadPool(ThreadPool&&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
ThreadPool& operator=(ThreadPool&&) = delete;
template<typename F, typename... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
{
auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
auto taskPtr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(task);
auto wrapper = [taskPtr]() {
(*taskPtr)();
};
{
std::lock_guard<std::mutex> lock(m_mutex);
m_tasks.push(wrapper);
m_condition_task.notify_one();
}
return taskPtr->get_future();
}
void wait();
private:
mutable std::mutex m_mutex;
std::condition_variable m_condition_task;
std::condition_variable m_condition_finish;
unsigned int m_busyThreads;
std::vector<std::thread> m_threads;
bool m_stopRequested;
std::queue<std::function<void()>> m_tasks;
friend class ThreadWorker;
};
class ThreadWorker
{
public:
ThreadWorker(ThreadPool* pool);
~ThreadWorker();
void operator()();
private:
ThreadPool* m_pool;
};
#endif // !THREAD_POOL_H
| 1 | #ifndef THREAD_POOL_H |
| 2 | #define THREAD_POOL_H |
| 3 | |
| 4 | #include <thread> |
| 5 | #include <mutex> |
| 6 | #include <condition_variable> |
| 7 | #include <functional> |
| 8 | #include <future> |
| 9 | #include <queue> |
| 10 | #include <vector> |
| 11 | #include <memory> |
| 12 | #include <condition_variable> |
| 13 | |
| 14 | class ThreadPool |
| 15 | { |
| 16 | public: |
| 17 | ThreadPool(); |
| 18 | ~ThreadPool(); |
| 19 | |
| 20 | ThreadPool(const ThreadPool&) = delete; |
| 21 | ThreadPool(ThreadPool&&) = delete; |
| 22 | ThreadPool& operator=(const ThreadPool&) = delete; |
| 23 | ThreadPool& operator=(ThreadPool&&) = delete; |
| 24 | |
| 25 | template<typename F, typename... Args> |
| 26 | auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> |
| 27 | { |
| 28 | auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...); |
| 29 | auto taskPtr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(task); |
| 30 | auto wrapper = [taskPtr]() { |
| 31 | (*taskPtr)(); |
| 32 | }; |
| 33 | |
| 34 | { |
| 35 | std::lock_guard<std::mutex> lock(m_mutex); |
| 36 | m_tasks.push(wrapper); |
| 37 | m_condition_task.notify_one(); |
| 38 | } |
| 39 | |
| 40 | return taskPtr->get_future(); |
| 41 | } |
| 42 | void wait(); |
| 43 | |
| 44 | private: |
| 45 | mutable std::mutex m_mutex; |
| 46 | std::condition_variable m_condition_task; |
| 47 | std::condition_variable m_condition_finish; |
| 48 | unsigned int m_busyThreads; |
| 49 | |
| 50 | std::vector<std::thread> m_threads; |
| 51 | bool m_stopRequested; |
| 52 | |
| 53 | std::queue<std::function<void()>> m_tasks; |
| 54 | |
| 55 | friend class ThreadWorker; |
| 56 | }; |
| 57 | |
| 58 | |
| 59 | class ThreadWorker |
| 60 | { |
| 61 | public: |
| 62 | ThreadWorker(ThreadPool* pool); |
| 63 | ~ThreadWorker(); |
| 64 | |
| 65 | void operator()(); |
| 66 | |
| 67 | private: |
| 68 | ThreadPool* m_pool; |
| 69 | }; |
| 70 | |
| 71 | #endif // !THREAD_POOL_H |