WSF
WsfThreadPool.hpp
Go to the documentation of this file.
1// ****************************************************************************
2// CUI
3//
4// The Advanced Framework for Simulation, Integration, and Modeling (AFSIM)
5//
6// Copyright 2003-2015 The Boeing Company. All rights reserved.
7//
8// The use, dissemination or disclosure of data in this file is subject to
9// limitation or restriction. See accompanying README and LICENSE for details.
10// ****************************************************************************
11
12#ifndef WSFTHREADPOOL_HPP
13#define WSFTHREADPOOL_HPP
14
15#include "UtSleep.hpp"
16#include "WsfThread.hpp"
17#include <chrono>
18// template <typename T>
19// class Singleton
20//{
21// static T& Instance();
22// };
23//
24// template <typename T>
25// T& Singleton<T>::Instance()
26//{
27// static T mt;
28// return mt;
29// }
30
31template<typename T>
33{
34 T* operator()() const { return new T; }
35};
36
37// ============================================================================
38template<class Worker, class WorkerFactory = WsfThreadPool_DefaultWorkerFactor<Worker>>
40{
41public:
42 typedef std::vector<Worker*> WorkerThreads;
43
44 WsfThreadPool(const WorkerFactory& aFactory = WorkerFactory());
46
47 void Start(unsigned int aNumThreads);
48 void Stop();
49
51 bool AssignWork(size_t aNumTasks = 0u);
52 Worker* FindAvailableThread(double aSleepTime = 0.001);
54
56 bool TryWaitUntilAllWorkDone(double aSecsToWait);
57
58private:
59 WorkerFactory mFactory;
60 WorkerThreads mThread_vector;
61};
62
63template<class Worker, class WorkerFactory>
65 : mFactory(aFactory)
66{
67}
68
69template<class Worker, class WorkerFactory>
71{
72 // Shut down the thread pool
73 Stop();
74
75 // delete threads and clear the thread pool
76 for (unsigned int index = 0; index < mThread_vector.size(); ++index)
77 {
78 delete mThread_vector[index];
79 }
80 mThread_vector.clear();
81}
82
83template<class Worker, class WorkerFactory>
84void WsfThreadPool<Worker, WorkerFactory>::Start(unsigned int aNumThreads)
85{
86 // Check to see if the threads have already been created
87 if (mThread_vector.empty())
88 {
89 // Create the threads and start them running
90 mThread_vector.reserve(aNumThreads);
91 for (unsigned int count = 1; count <= aNumThreads; ++count)
92 {
93 Worker* workerPtr = mFactory();
94 workerPtr->Start();
95 mThread_vector.push_back(workerPtr);
96 }
97 }
98}
99
100template<class Worker, class WorkerFactory>
102{
103 // Stop the work
104 UtThread::UtThreads tempThreads;
105 for (unsigned int index = 0; index < mThread_vector.size(); ++index)
106 {
107 mThread_vector[index]->StopWork();
108 mThread_vector[index]->EndThread();
109 tempThreads.push_back(mThread_vector[index]);
110 }
111
112 // Wait for threads to die
113 if (!tempThreads.empty())
114 {
115 UtThread::JoinAll(tempThreads);
116 }
117}
118
119template<class Worker, class WorkerFactory>
121{
122 // Loop through the vector of thread and find the first available
123 bool startedWork(false);
124 for (auto* threadPtr : mThread_vector)
125 {
126 if (threadPtr->AssignWork())
127 {
128 startedWork = true;
129 --aNumTasks;
130 if (aNumTasks == 0)
131 {
132 break;
133 }
134 }
135 }
136 return startedWork;
137}
138
139template<class Worker, class WorkerFactory>
141{
142 // Loop through the vector of thread and find the first available
143 Worker* availableThreadPtr = 0;
144 unsigned int threadPoolSize(mThread_vector.size());
145 for (unsigned int index = 0; index < threadPoolSize; ++index)
146 {
147 if (mThread_vector[index]->GetFunction() == WsfThread::AVAILABLE)
148 {
149 availableThreadPtr = mThread_vector[index];
150 break;
151 }
152 }
153
154 // All threads are busy; sleep a little bit
155 if (availableThreadPtr == 0)
156 {
157 UtSleep::Sleep(aSleepTime);
158 }
159
160 return availableThreadPtr;
161}
162
163template<class Worker, class WorkerFactory>
165{
166 bool atLeastOneStillWorking(false);
167 size_t threadPoolSize(mThread_vector.size());
168 for (size_t index = 0; index < threadPoolSize; ++index)
169 {
170 if (mThread_vector[index]->GetFunction() != WsfThread::AVAILABLE)
171 {
172 atLeastOneStillWorking = true;
173 break;
174 }
175 }
176 return (!atLeastOneStillWorking);
177}
178
179template<class Worker, class WorkerFactory>
181{
182 for (auto threadPtr : mThread_vector)
183 {
184 threadPtr->WaitUntilWorkDone();
185 }
186}
187
188template<class Worker, class WorkerFactory>
190{
191 auto start = std::chrono::system_clock::now();
192 for (auto threadPtr : mThread_vector)
193 {
194 if (!threadPtr->TryWaitUntilWorkDone(aSecsToWait))
195 {
196 return false;
197 }
198 auto now = std::chrono::system_clock::now();
199 using secs_t = std::chrono::duration<double>;
200 aSecsToWait -= secs_t{now - start}.count();
201 start = now;
202 }
203 return true;
204}
205
206#endif // WSFTHREADPOOL_HPP
void Stop()
Definition WsfThreadPool.hpp:101
void Start(unsigned int aNumThreads)
Definition WsfThreadPool.hpp:84
bool AssignWork(size_t aNumTasks=0u)
Definition WsfThreadPool.hpp:120
WsfThreadPool(const WorkerFactory &aFactory=WorkerFactory())
Definition WsfThreadPool.hpp:64
void WaitUntilAllWorkDone()
Definition WsfThreadPool.hpp:180
std::vector< Worker * > WorkerThreads
Definition WsfThreadPool.hpp:42
bool TryWaitUntilAllWorkDone(double aSecsToWait)
Definition WsfThreadPool.hpp:189
~WsfThreadPool()
Definition WsfThreadPool.hpp:70
bool AllWorkDone()
Definition WsfThreadPool.hpp:164
Worker * FindAvailableThread(double aSleepTime=0.001)
Definition WsfThreadPool.hpp:140
@ AVAILABLE
Definition WsfThread.hpp:28
Definition WsfThreadPool.hpp:33
T * operator()() const
Definition WsfThreadPool.hpp:34
Copyrights Multiple, All Rights Reserved