@@ -81,13 +81,11 @@ class Task {
8181 class ThreadPool FINAL {
8282 public:
8383 ThreadPool (int threads = 8 );
84+
8485 template <class F , class ... Args>
85- #if __cplusplus >= 201703L // result_of deprecated from C++17
86- std::future<typename std::invoke_result_t <F, Args...>> schedule (F&& f, Args&&... args);
87- #else
88- std::future<typename std::result_of<F(Args...)>::type> schedule (F&& f, Args&&... args);
89- #endif
90- ~ThreadPool ();
86+ auto schedule (F&& f, Args&&... args);
87+
88+ ~ThreadPool () noexcept ;
9189
9290 private:
9391 std::vector<std::thread> _workers;
@@ -101,7 +99,7 @@ class Task {
10199 inline ThreadPool::ThreadPool (int threads)
102100 : _stop(false )
103101 {
104- if ((threads = = 0 ) || (threads > 1024 ))
102+ if ((threads < = 0 ) || (threads > 1024 ))
105103 throw std::invalid_argument (" The number of threads must be in [1..1024]" );
106104
107105 // Start and run threads
@@ -116,9 +114,9 @@ class Task {
116114 {
117115 std::unique_lock<std::mutex> lock (_mutex);
118116 _condition.wait (lock,
119- [this ] { return ( _stop == true ) || ( _tasks.size () > 0 ); });
117+ [this ] { return _stop || ! _tasks.empty ( ); });
120118
121- if (_stop == true )
119+ if (_stop && _tasks. empty () )
122120 return ;
123121
124122 task = std::move (_tasks.front ());
@@ -133,26 +131,24 @@ class Task {
133131
134132
135133 template <class F , class ... Args>
136- #if __cplusplus >= 201703L // result_of deprecated from C++17
137- std::future<typename std::invoke_result_t <F, Args...> > ThreadPool::schedule (F&& f, Args&&... args)
134+ auto ThreadPool::schedule (F&& f, Args&&... args)
138135 {
139- using return_type = typename std::invoke_result<F, Args...>::type;
140- #else
141- std::future<typename std::result_of<F (Args...)>::type> ThreadPool::schedule (F&& f, Args&&... args)
142- {
143- using return_type = typename std::result_of<F (Args...)>::type;
144- #endif
136+ using return_type = std::invoke_result_t <F, Args...>;
145137
146- auto task = std::make_shared< std::packaged_task<return_type ()> >(
147- std::bind (std::forward<F>(f), std::forward<Args>(args)...)
148- );
138+ auto task = std::make_shared<std::packaged_task<return_type ()>>(
139+ [fn = std::forward<F>(f),
140+ tup = std::make_tuple (std::forward<Args>(args)...)]() mutable
141+ {
142+ return std::apply (std::move (fn), std::move (tup));
143+ }
144+ );
149145
150146 std::future<return_type> res = task->get_future ();
151147
152148 {
153149 std::unique_lock<std::mutex> lock (_mutex);
154150
155- if (_stop == true )
151+ if (_stop)
156152 throw std::runtime_error (" ThreadPool stopped" );
157153
158154 _tasks.emplace ([task](){ (*task)(); });
@@ -164,7 +160,7 @@ class Task {
164160
165161
166162 // the destructor joins all threads
167- inline ThreadPool::~ThreadPool ()
163+ inline ThreadPool::~ThreadPool () noexcept
168164 {
169165 {
170166 std::unique_lock<std::mutex> lock (_mutex);
0 commit comments