46 : threadStacks{}, threadStackMutexes{}, fnQueue{}, queueMutex{} {}
50 std::this_thread::sleep_for(std::chrono::microseconds(30));
64 void queueFn(std::function<
void(
void *)> &&fn,
void *ud =
nullptr) {
65 std::lock_guard<std::mutex> lock(queueMutex);
66 fnQueue.emplace(std::make_tuple(fn, ud));
80 auto pointers = newStackEntry();
81 Internal::ThreadStackType *threadStack = std::get<0>(pointers);
82 std::mutex *threadStackMutex = std::get<1>(pointers);
83 std::atomic_uint *aCounter = std::get<2>(pointers);
84 for (
unsigned int i = 0; i < MAXSIZE; ++i) {
85 std::thread *newThread =
new std::thread(
86 [](Internal::ThreadStackType *threadStack,
87 std::mutex *threadStackMutex,
88 Internal::TPQueueType *fnQueue, std::mutex *queueMutex,
89 std::atomic_uint *initCount) {
92 std::lock_guard<std::mutex> lock(*threadStackMutex);
93 threadStack->push_back(
94 {Internal::ThreadPtr(
nullptr),
95 std::this_thread::get_id()});
102 std::list<Internal::TPTupleType> fnTuples;
104 bool fnFound =
false;
106 std::lock_guard<std::mutex> lock(*queueMutex);
107 if (!fnQueue->empty()) {
108 fnTuples.emplace_back(
109 std::move(fnQueue->front()));
115 std::get<0>(fnTuples.back())(
116 std::get<1>(fnTuples.back()));
124 std::this_thread::sleep_for(
125 std::chrono::microseconds(15));
126 if (initCount->load() != MAXSIZE) {
130 std::lock_guard<std::mutex> lock(
132 if (std::get<1>(threadStack->back()) ==
133 std::this_thread::get_id()) {
134 if (!std::get<0>(threadStack->back())) {
137 std::get<0>(threadStack->back())->detach();
138 threadStack->pop_back();
144 threadStack, threadStackMutex, &fnQueue, &queueMutex,
148 while (aCounter->load() != i + 1) {
149 std::this_thread::sleep_for(std::chrono::microseconds(15));
151 std::lock_guard<std::mutex> stackLock(*threadStackMutex);
152 std::get<0>(threadStack->at(i)).reset(newThread);
156 sequentiallyRunTasks();
158 return {
nullptr,
nullptr,
nullptr,
nullptr};
165 std::lock_guard<std::mutex> lock(queueMutex);
166 return fnQueue.empty();
184 std::this_thread::sleep_for(std::chrono::microseconds(30));
188 std::lock_guard<std::mutex> lock(queueMutex);
196 if (std::get<0>(pointers)) {
199 std::lock_guard<std::mutex> lock(
200 *std::get<1>(pointers));
201 if (std::get<0>(pointers)->empty()) {
202 std::get<3>(pointers)->store(
false);
206 std::this_thread::sleep_for(std::chrono::microseconds(15));
210 sequentiallyRunTasks();
219 std::lock_guard<std::mutex> lock(dequesMutex);
220 auto tIter = threadStacks.begin();
221 auto mIter = threadStackMutexes.begin();
222 while (tIter != threadStacks.end() &&
223 mIter != threadStackMutexes.end()) {
225 std::lock_guard<std::mutex> lock(*mIter);
226 if (!tIter->empty()) {
237 Internal::ThreadStacksType threadStacks;
238 Internal::ThreadStacksMutexesT threadStackMutexes;
239 Internal::TPQueueType fnQueue;
240 std::mutex queueMutex;
241 Internal::ThreadCountersT threadCounters;
242 Internal::PtrsHoldT ptrsHoldBools;
243 std::mutex dequesMutex;
245 void sequentiallyRunTasks() {
247 Internal::TPTupleType fnTuple;
251 std::lock_guard<std::mutex> lock(queueMutex);
252 if (!fnQueue.empty()) {
254 fnTuple = fnQueue.front();
261 std::get<0>(fnTuple)(std::get<1>(fnTuple));
267 std::lock_guard<std::mutex> lock(dequesMutex);
268 if (threadStacks.empty()) {
276 std::lock_guard<std::mutex> lock(threadStackMutexes.front());
277 if (ptrsHoldBools.front().load()) {
279 }
else if (threadStacks.front().empty()) {
280 threadStacks.pop_front();
281 threadCounters.pop_front();
282 ptrsHoldBools.pop_front();
287 threadStackMutexes.pop_front();
291 }
while (!threadStacks.empty() && !threadStackMutexes.empty() &&
292 !threadCounters.empty() && !ptrsHoldBools.empty());
295 Internal::PointersT newStackEntry() {
296 std::lock_guard<std::mutex> lock(dequesMutex);
297 threadStacks.emplace_back();
298 threadStackMutexes.emplace_back();
299 threadCounters.emplace_back();
300 threadCounters.back().store(0);
301 ptrsHoldBools.emplace_back();
302 ptrsHoldBools.back().store(
true);
304 return {&threadStacks.back(), &threadStackMutexes.back(),
305 &threadCounters.back(), &ptrsHoldBools.back()};
void queueFn(std::function< void(void *)> &&fn, void *ud=nullptr)
Queues a function to be called (doesn't start calling yet).
Definition ThreadPool.hpp:64