Closed nolankramer closed 7 months ago
According to https://stackoverflow.com/questions/43614634/stdthread-how-to-wait-join-for-any-of-the-given-threads-to-complete, it may be best practice to use a producer-consumer queue that operates on the return value of the functions.
Hi @nolankramer and thanks for the suggestion! If I understand correctly, when you say "wait for any task" you mean "wait until exactly one task finishes running"? Would you be able to provide an example of a use case for this? You mentioned dependency graphs, how exactly will that work in that context?
Also, I'm not sure your suggested implementation will work as expected, because the predicate doesn't account for spurious wake-ups. The predicate will need to check that a task has actually finished running, which makes the implementation a bit more complicated. Maybe this could be done using a global counter that keeps track of many tasks have executed so far, with the wait function checking that the counter has been incremented, but that means complicating the entire thread pool. On the other hand, this could allow waiting for any specific number of tasks to complete, rather than just 1, which may also be useful.
Regarding the implementation for multi_future
, I guess this could be implemented by blocking until ready_count()
increases. multi_future
is supposed to be independent of the thread pool, so the user can use it with their own futures independently if needed, so it can't be receiving any input from the thread pool itself.
If you tell me the exact use case you have in mind, I might be able to find a better solution. Thanks again!
Describe the new feature
It is sometimes useful (especially for dependency graphs), to wait on any task in a group or pool to complete. This allows running downstream logic iteratively, while periodically checking/waiting for more task completions without polling.
A useful implementation may be adding two functions:
thread_pool::wait_for_any()
, which waits until any task in the pool completes.multi_future::wait_any()
, which waits until any task in the the group completes.thread_pool::wait_for_any()
The implementation for this seems simpler, since
std::condition_variable
is already used for queue management. A possible implementation might be:multi_future::wait_any()
This implementation seems much harder to get right, simply because the existing iterations of the C++ standard don't include a
std::future::then(...)
implementation.A possible path forward may be to:
std::condition_variable
and associated synchronization primitives to themulti_future
membersmulti_future
a friend ofthread_pool
thread_pool::submitToMulti(...)
that accepts amulti_future
and submits the task to the pool, notifying themulti_future
'sstd::condition_variable
at the end.(although this certainly lacks grace in that adding futures directly to the
multi_future
won't trigger thestd::condition_variable
...)I've also seen some
std::future::then(...)
implementations floating around StackOverflow.Perhaps even exposing a helper function like
BS::create_future(...)
that accepts astd::condition_variable
would help mitigate some API headache.Perhaps the answer is to create an entirely new helper class...