1 #ifndef OPENPOSE_THREAD_THREAD_MANAGER_HPP
2 #define OPENPOSE_THREAD_THREAD_MANAGER_HPP
15 template<
typename TDatums,
typename TWorker = std::shared_ptr<Worker<TDatums>>,
typename TQueue = Queue<TDatums>>
26 void add(
const unsigned long long threadId,
const std::vector<TWorker>& tWorkers,
const unsigned long long queueInId,
27 const unsigned long long queueOutId);
29 void add(
const unsigned long long threadId,
const TWorker& tWorker,
const unsigned long long queueInId,
30 const unsigned long long queueOutId);
54 bool tryPush(
const TDatums& tDatums);
58 bool tryPop(TDatums& tDatums);
64 std::shared_ptr<std::atomic<bool>> spIsRunning;
65 long long mDefaultMaxSizeQueues;
66 std::multiset<std::tuple<unsigned long long, std::vector<TWorker>,
unsigned long long,
unsigned long long>> mThreadWorkerQueues;
67 std::vector<std::shared_ptr<Thread<TDatums, TWorker>>> mThreads;
68 std::vector<std::shared_ptr<TQueue>> mTQueues;
70 void add(
const std::vector<std::tuple<
unsigned long long, std::vector<TWorker>,
unsigned long long,
unsigned long long>>& threadWorkerQueues);
72 void add(
const std::vector<std::tuple<unsigned long long, TWorker, unsigned long long, unsigned long long>>& threadWorkerQueues);
74 void multisetToThreads();
76 void checkAndCreateEmptyThreads();
78 void checkAndCreateQueues();
98 template<
typename TDatums,
typename TWorker,
typename TQueue>
100 mThreadManagerMode{threadManagerMode},
101 spIsRunning{std::make_shared<std::atomic<bool>>(
false)},
102 mDefaultMaxSizeQueues{-1ll}
106 template<
typename TDatums,
typename TWorker,
typename TQueue>
111 template<
typename TDatums,
typename TWorker,
typename TQueue>
116 mDefaultMaxSizeQueues = {defaultMaxSizeQueues};
118 catch (
const std::exception& e)
120 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
124 template<
typename TDatums,
typename TWorker,
typename TQueue>
126 const std::vector<TWorker>& tWorkers,
127 const unsigned long long queueInId,
128 const unsigned long long queueOutId)
132 add({std::make_tuple(threadId, tWorkers, queueInId, queueOutId)});
134 catch (
const std::exception& e)
136 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
140 template<
typename TDatums,
typename TWorker,
typename TQueue>
142 const TWorker& tWorker,
143 const unsigned long long queueInId,
144 const unsigned long long queueOutId)
148 add({std::make_tuple(threadId, std::vector<TWorker>{tWorker}, queueInId, queueOutId)});
150 catch (
const std::exception& e)
152 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
156 template<
typename TDatums,
typename TWorker,
typename TQueue>
161 mThreadWorkerQueues.clear();
165 catch (
const std::exception& e)
167 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
171 template<
typename TDatums,
typename TWorker,
typename TQueue>
179 if (!mThreads.empty())
183 for (
auto i = 0u; i < mThreads.size() - 1; i++)
184 mThreads.at(i)->startInThread();
185 (*mThreads.rbegin())->exec(spIsRunning);
191 catch (
const std::exception& e)
193 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
197 template<
typename TDatums,
typename TWorker,
typename TQueue>
206 for (
auto& thread : mThreads)
207 thread->startInThread();
210 catch (
const std::exception& e)
212 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
216 template<
typename TDatums,
typename TWorker,
typename TQueue>
222 for (
auto& tQueue : mTQueues)
225 *spIsRunning =
false;
226 for (
auto& thread : mThreads)
227 thread->stopAndJoin();
230 catch (
const std::exception& e)
232 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
236 template<
typename TDatums,
typename TWorker,
typename TQueue>
243 error(
"Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__);
244 if (mTQueues.empty())
245 error(
"ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__);
246 return mTQueues[0]->tryEmplace(tDatums);
248 catch (
const std::exception& e)
250 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
255 template<
typename TDatums,
typename TWorker,
typename TQueue>
262 error(
"Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__);
263 if (mTQueues.empty())
264 error(
"ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__);
265 return mTQueues[0]->waitAndEmplace(tDatums);
267 catch (
const std::exception& e)
269 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
274 template<
typename TDatums,
typename TWorker,
typename TQueue>
281 error(
"Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__);
282 if (mTQueues.empty())
283 error(
"ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__);
284 return mTQueues[0]->tryPush(tDatums);
286 catch (
const std::exception& e)
288 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
293 template<
typename TDatums,
typename TWorker,
typename TQueue>
300 error(
"Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__);
301 if (mTQueues.empty())
302 error(
"ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__);
303 return mTQueues[0]->waitAndPush(tDatums);
305 catch (
const std::exception& e)
307 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
312 template<
typename TDatums,
typename TWorker,
typename TQueue>
319 error(
"Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__);
320 if (mTQueues.empty())
321 error(
"ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__);
322 return (*mTQueues.rbegin())->tryPop(tDatums);
324 catch (
const std::exception& e)
326 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
331 template<
typename TDatums,
typename TWorker,
typename TQueue>
338 error(
"Not available for this ThreadManagerMode.", __LINE__, __FUNCTION__, __FILE__);
339 if (mTQueues.empty())
340 error(
"ThreadManager already stopped or not started yet.", __LINE__, __FUNCTION__, __FILE__);
341 return (*mTQueues.rbegin())->waitAndPop(tDatums);
343 catch (
const std::exception& e)
345 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
350 template<
typename TDatums,
typename TWorker,
typename TQueue>
352 unsigned long long,
unsigned long long>>& threadWorkerQueues)
356 for (
const auto& threadWorkerQueue : threadWorkerQueues)
357 mThreadWorkerQueues.insert(threadWorkerQueue);
359 catch (
const std::exception& e)
361 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
365 template<
typename TDatums,
typename TWorker,
typename TQueue>
367 unsigned long long>>& threadWorkerQueues)
371 for (
const auto& threadWorkerQueue : threadWorkerQueues)
372 add({std::make_tuple(std::get<0>(threadWorkerQueue),
373 std::vector<TWorker>{std::get<1>(threadWorkerQueue)},
374 std::get<2>(threadWorkerQueue),
375 std::get<3>(threadWorkerQueue))});
377 catch (
const std::exception& e)
379 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
383 template<
typename TDatums,
typename TWorker,
typename TQueue>
384 void ThreadManager<TDatums, TWorker, TQueue>::multisetToThreads()
388 if (!mThreadWorkerQueues.empty())
391 checkAndCreateEmptyThreads();
394 checkAndCreateQueues();
397 const auto maxQueueIdSynchronous = mTQueues.size()+1;
400 for (
const auto& threadWorkerQueue : mThreadWorkerQueues)
402 auto& thread = mThreads[std::get<0>(threadWorkerQueue)];
403 const auto& tWorkers = std::get<1>(threadWorkerQueue);
404 const auto queueIn = std::get<2>(threadWorkerQueue);
405 const auto queueOut = std::get<3>(threadWorkerQueue);
406 std::shared_ptr<SubThread<TDatums, TWorker>> subThread;
412 && queueOut == mTQueues.size())
413 subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(
414 tWorkers, mTQueues.at(queueIn))};
416 subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(
417 tWorkers, mTQueues.at(queueIn), mTQueues.at(queueOut))};
420 else if (queueOut != maxQueueIdSynchronous
425 subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(
426 tWorkers, mTQueues.at(queueIn-1), mTQueues.at(queueOut-1))};
429 subThread = {std::make_shared<SubThreadQueueOut<TDatums, TWorker, TQueue>>(
430 tWorkers, mTQueues.at(queueOut-1))};
433 else if (queueIn != 0)
434 subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(
435 tWorkers, mTQueues.at(queueIn-1))};
438 subThread = {std::make_shared<SubThreadNoQueue<TDatums, TWorker>>(tWorkers)};
439 thread->add(subThread);
443 error(
"Empty, no TWorker(s) added.", __LINE__);
445 catch (
const std::exception& e)
447 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
451 template<
typename TDatums,
typename TWorker,
typename TQueue>
452 void ThreadManager<TDatums, TWorker, TQueue>::checkAndCreateEmptyThreads()
457 const auto maxThreadId = std::get<0>(*mThreadWorkerQueues.crbegin());
458 auto previousThreadId = std::get<0>(*mThreadWorkerQueues.cbegin());
459 for (
const auto& threadWorkerQueue : mThreadWorkerQueues)
461 const auto currentThreadId = std::get<0>(threadWorkerQueue);
462 if (currentThreadId - previousThreadId > 1)
463 error(
"Missing thread id " + std::to_string(currentThreadId) +
" of "
464 + std::to_string(maxThreadId) +
".", __LINE__, __FUNCTION__, __FILE__);
465 previousThreadId = currentThreadId;
470 mThreads.resize(maxThreadId);
471 for (
auto& thread : mThreads)
472 thread = std::make_shared<Thread<TDatums, TWorker>>();
473 mThreads.emplace_back(std::make_shared<Thread<TDatums, TWorker>>(spIsRunning));
475 catch (
const std::exception& e)
477 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
481 template<
typename TDatums,
typename TWorker,
typename TQueue>
482 void ThreadManager<TDatums, TWorker, TQueue>::checkAndCreateQueues()
486 if (!mThreadWorkerQueues.empty())
489 auto maxQueueId = std::get<3>(*mThreadWorkerQueues.cbegin());
490 for (
const auto& threadWorkerQueue : mThreadWorkerQueues)
492 maxQueueId,
fastMax(std::get<2>(threadWorkerQueue), std::get<3>(threadWorkerQueue)));
496 std::vector<std::pair<bool, bool>> usedQueueIds(maxQueueId+1, {
false,
false});
497 for (
const auto& threadWorkerQueue : mThreadWorkerQueues)
499 usedQueueIds.at(std::get<2>(threadWorkerQueue)).first =
true;
500 usedQueueIds.at(std::get<3>(threadWorkerQueue)).second =
true;
503 usedQueueIds.begin()->second =
true;
505 usedQueueIds.rbegin()->first =
true;
507 for (
auto i = 0ull ; i < usedQueueIds.size() ; i++)
509 if (!usedQueueIds[i].first)
510 error(
"Missing queue id " + std::to_string(i) +
" (of "
511 + std::to_string(maxQueueId) +
") as input.", __LINE__, __FUNCTION__, __FILE__);
512 if (!usedQueueIds[i].second)
513 error(
"Missing queue id " + std::to_string(i) +
" (of "
514 + std::to_string(maxQueueId) +
") as output.", __LINE__, __FUNCTION__, __FILE__);
519 mTQueues.resize(maxQueueId+1);
521 mTQueues.resize(maxQueueId-1);
524 mTQueues.resize(maxQueueId);
526 error(
"Unknown ThreadManagerMode", __LINE__, __FUNCTION__, __FILE__);
527 for (
auto& tQueue : mTQueues)
528 tQueue = std::make_shared<TQueue>(mDefaultMaxSizeQueues);
531 catch (
const std::exception& e)
533 error(e.what(), __LINE__, __FUNCTION__, __FILE__);
540 #endif // OPENPOSE_THREAD_THREAD_MANAGER_HPP
virtual ~ThreadManager()
Definition: threadManager.hpp:107
ThreadManager(const ThreadManagerMode threadManagerMode=ThreadManagerMode::Synchronous)
Definition: threadManager.hpp:99
void stop()
Definition: threadManager.hpp:217
bool isRunning() const
Definition: threadManager.hpp:45
void start()
Definition: threadManager.hpp:198
void setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues=-1)
Definition: threadManager.hpp:112
bool waitAndEmplace(TDatums &tDatums)
Definition: threadManager.hpp:256
std::shared_ptr< std::atomic< bool > > getIsRunningSharedPtr()
Definition: threadManager.hpp:40
T fastMax(const T a, const T b)
Definition: fastMath.hpp:70
bool tryPop(TDatums &tDatums)
Definition: threadManager.hpp:313
void add(const unsigned long long threadId, const std::vector< TWorker > &tWorkers, const unsigned long long queueInId, const unsigned long long queueOutId)
Definition: threadManager.hpp:125
void reset()
Definition: threadManager.hpp:157
OP_API void error(const std::string &message, const int line=-1, const std::string &function="", const std::string &file="")
bool waitAndPop(TDatums &tDatums)
Definition: threadManager.hpp:332
bool tryEmplace(TDatums &tDatums)
Definition: threadManager.hpp:237
Definition: threadManager.hpp:16
void exec()
Definition: threadManager.hpp:172
OP_API void log(const std::string &message, const Priority priority=Priority::Max, const int line=-1, const std::string &function="", const std::string &file="")
ThreadManagerMode
Definition: enumClasses.hpp:9
COMPILE_TEMPLATE_DATUM(WPoseTriangulation)
std::vector< T, Alloc > vector
Definition: cl2.hpp:567
bool waitAndPush(const TDatums &tDatums)
Definition: threadManager.hpp:294
bool tryPush(const TDatums &tDatums)
Definition: threadManager.hpp:275