| 216 | { |
| 217 | break; // all tasks have completed (including the task being waited) |
| 218 | } |
| 219 | } |
| 220 | return ResultThreading(true); |
| 221 | } |
| 222 | |
| 223 | SC::ResultThreading SC::ThreadPool::queueTask(Task& task) |
| 224 | { |
| 225 | if (numWorkerThreads == 0) |
| 226 | return ResultThreading(ThreadingError::ThreadPoolNotCreated); |
| 227 | |
| 228 | // Function is entirely protected by the mutex |
| 229 | poolMutex.lock(); |
| 230 | auto deferUnlock = MakeDeferred([this] { poolMutex.unlock(); }); |
| 231 | |
| 232 | if (task.threadPool == this) |
| 233 | return ResultThreading(ThreadingError::TaskAlreadyQueued); |
| 234 | if (task.threadPool != nullptr) |
| 235 | return ResultThreading(ThreadingError::TaskInUseByAnotherThreadPool); |
| 236 | |
| 237 | task.threadPool = this; |
| 238 | if (taskHead == nullptr) |
| 239 | { |
| 240 | // FIFO was empty, replace head and tail with the task |
| 241 | taskHead = &task; |
| 242 | taskTail = taskHead; |
| 243 | } |
| 244 | else |
| 245 | { |
| 246 | // FIFO was not empty, append task to the tail |
| 247 | taskTail->next = &task; |