11#pragma once
22
3+ #include < thread_pool/fixed_function.hpp>
4+ #include < thread_pool/mpsc_bounded_queue.hpp>
5+ #include < thread_pool/thread_pool_options.hpp>
36#include < thread_pool/worker.hpp>
47
58#include < atomic>
1013namespace tp
1114{
1215
13- /* *
14- * @brief The ThreadPoolOptions struct provides construction options for
15- * ThreadPool.
16- */
17- struct ThreadPoolOptions
18- {
19- enum
20- {
21- AUTODETECT = 0
22- };
23-
24- size_t threads_count = AUTODETECT;
25- size_t worker_queue_size = 1024 ;
26- };
16+ template <typename Task, template <typename > class Queue >
17+ class ThreadPoolImpl ;
18+ using ThreadPool = ThreadPoolImpl<FixedFunction<void (), 128 >,
19+ MPMCBoundedQueue>;
2720
2821/* *
2922 * @brief The ThreadPool class implements thread pool pattern.
@@ -33,7 +26,7 @@ struct ThreadPoolOptions
3326 * startegies.
3427 * It implements cooperative scheduling strategy for tasks.
3528 */
36- template <size_t TASK_SIZE >
29+ template <typename Task, template < typename > class Queue >
3730class ThreadPoolImpl {
3831public:
3932 /* *
@@ -79,66 +72,52 @@ class ThreadPoolImpl {
7972 void post (Handler&& handler);
8073
8174private:
82- Worker<TASK_SIZE >& getWorker ();
75+ Worker<Task, Queue >& getWorker ();
8376
84- std::vector<std::unique_ptr<Worker<TASK_SIZE >>> m_workers;
77+ std::vector<std::unique_ptr<Worker<Task, Queue >>> m_workers;
8578 std::atomic<size_t > m_next_worker;
8679};
8780
88- using ThreadPool = ThreadPoolImpl<128 >;
89-
9081
9182// / Implementation
9283
93- template <size_t TASK_SIZE >
94- inline ThreadPoolImpl<TASK_SIZE >::ThreadPoolImpl(
84+ template <typename Task, template < typename > class Queue >
85+ inline ThreadPoolImpl<Task, Queue >::ThreadPoolImpl(
9586 const ThreadPoolOptions& options)
96- : m_next_worker(0 )
87+ : m_workers(options.threadCount())
88+ , m_next_worker(0 )
9789{
98- size_t workers_count = options.threads_count ;
99-
100- if (ThreadPoolOptions::AUTODETECT == options.threads_count )
101- {
102- workers_count = std::thread::hardware_concurrency ();
103- }
104-
105- if (0 == workers_count)
106- {
107- workers_count = 1 ;
108- }
109-
110- m_workers.resize (workers_count);
11190 for (auto & worker_ptr : m_workers)
11291 {
113- worker_ptr.reset (new Worker<TASK_SIZE >(options.worker_queue_size ));
92+ worker_ptr.reset (new Worker<Task, Queue >(options.queueSize () ));
11493 }
11594
11695 for (size_t i = 0 ; i < m_workers.size (); ++i)
11796 {
118- Worker<TASK_SIZE >* steal_donor =
97+ Worker<Task, Queue >* steal_donor =
11998 m_workers[(i + 1 ) % m_workers.size ()].get ();
12099 m_workers[i]->start (i, steal_donor);
121100 }
122101}
123102
124- template <size_t TASK_SIZE >
125- inline ThreadPoolImpl<TASK_SIZE >::ThreadPoolImpl(ThreadPoolImpl<TASK_SIZE >&& rhs) noexcept
103+ template <typename Task, template < typename > class Queue >
104+ inline ThreadPoolImpl<Task, Queue >::ThreadPoolImpl(ThreadPoolImpl<Task, Queue >&& rhs) noexcept
126105{
127106 *this = rhs;
128107}
129108
130- template <size_t TASK_SIZE >
131- inline ThreadPoolImpl<TASK_SIZE >::~ThreadPoolImpl ()
109+ template <typename Task, template < typename > class Queue >
110+ inline ThreadPoolImpl<Task, Queue >::~ThreadPoolImpl ()
132111{
133112 for (auto & worker_ptr : m_workers)
134113 {
135114 worker_ptr->stop ();
136115 }
137116}
138117
139- template <size_t TASK_SIZE >
140- inline ThreadPoolImpl<TASK_SIZE >&
141- ThreadPoolImpl<TASK_SIZE >::operator =(ThreadPoolImpl<TASK_SIZE >&& rhs) noexcept
118+ template <typename Task, template < typename > class Queue >
119+ inline ThreadPoolImpl<Task, Queue >&
120+ ThreadPoolImpl<Task, Queue >::operator =(ThreadPoolImpl<Task, Queue >&& rhs) noexcept
142121{
143122 if (this != &rhs)
144123 {
@@ -148,16 +127,16 @@ ThreadPoolImpl<TASK_SIZE>::operator=(ThreadPoolImpl<TASK_SIZE>&& rhs) noexcept
148127 return *this ;
149128}
150129
151- template <size_t TASK_SIZE >
130+ template <typename Task, template < typename > class Queue >
152131template <typename Handler>
153- inline bool ThreadPoolImpl<TASK_SIZE >::tryPost(Handler&& handler)
132+ inline bool ThreadPoolImpl<Task, Queue >::tryPost(Handler&& handler)
154133{
155134 return getWorker ().post (std::forward<Handler>(handler));
156135}
157136
158- template <size_t TASK_SIZE >
137+ template <typename Task, template < typename > class Queue >
159138template <typename Handler>
160- inline void ThreadPoolImpl<TASK_SIZE >::post (Handler&& handler)
139+ inline void ThreadPoolImpl<Task, Queue >::post (Handler&& handler)
161140{
162141 const auto ok = tryPost (std::forward<Handler>(handler));
163142 if (!ok)
@@ -166,10 +145,10 @@ inline void ThreadPoolImpl<TASK_SIZE>::post(Handler&& handler)
166145 }
167146}
168147
169- template <size_t TASK_SIZE >
170- inline Worker<TASK_SIZE >& ThreadPoolImpl<TASK_SIZE >::getWorker()
148+ template <typename Task, template < typename > class Queue >
149+ inline Worker<Task, Queue >& ThreadPoolImpl<Task, Queue >::getWorker()
171150{
172- auto id = Worker<TASK_SIZE >::getWorkerIdForCurrentThread ();
151+ auto id = Worker<Task, Queue >::getWorkerIdForCurrentThread ();
173152
174153 if (id > m_workers.size ())
175154 {
0 commit comments