Closed wkjarosz closed 8 months ago
Detaching tasks using detach_X()
is always safe to do from within another task, because that won't block, as long as you don't use pool.wait()
. However, using submit_X()
and waiting for the submitted tasks may cause a deadlock, since the waiting task will block until all the waited for tasks are done, and if the number of waiting tasks is equal to the total number of available threads, the waited for tasks will never get to execute.
To be safe, I recommend either submitting all tasks from the main thread, or creating two thread pools where one pool's tasks only submit tasks for the other pool.
Thanks for the info and suggested workarounds. Unfortunately, this probably means BS::thread_pool is not the right design for my needs, so i'll likely go in a different direction. Thanks again.
No worries, but I don't think any other thread pool library will allow you to do what you want, because the very definition of a thread pool means one task cannot wait for other tasks in the same pool. You might want to look into C++20 coroutines or other methods of asynchronous executing instead.
There are threadpool designs that can avoid issues with recursive tasks or one task depending on the completion of another in the same pool. You can check out the following two resources:
https://maxliani.wordpress.com/2022/07/27/anatomy-of-a-task-scheduler/ https://github.com/mitsuba-renderer/nanothread
One way to enable this is to ensure that wait-type functions don't just wait, but have the calling thread step into and execute tasks from the thread pool (incidentally, this also allows the thread pool to have a size of zero where no additional threads are ever launched).
Thanks, I will take a look.
I did not see this mentioned in the documentation (sorry if I missed it).
Does this library support nested or recursive tasks without deadlock/thread starvation?
For instance, I need to perform 10 tasks, which can be done independently, but within each tasks, I might have several loops that I would like to parallelize as well. If I use
submit_loop
or similar within each of these 10 tasks, do I run the risk of the inner loops never making progress because all threads in the pool are already allocated to the outer set of 10 tasks?My understanding is that with this library, the calling thread never steps in to make progress on a task or loop if the threadpool is full, which means deadlock could indeed happen with the above type of workload structure.
Thanks