So you can create a std::future
that does no work until .get()
is called:
auto f_deferred = std::async( std::launch::deferred, []{ std::cout << "I ran\n"; } );
You can also write a std::future
that is waitable, and can be made ready at any point by code in any thread:
std::packaged_task<void()> p( []( std::cout << "I also ran\n"; } );
auto f_waitable = p.get_future();
If you call f_deferred.wait_for(1ms)
, it won't bother waiting. If you call f_deferred.get()
, a lambda of your choice (in this case, one that prints "I ran\n"
executes.
If you call f_waitable.get()
, there is no way for code managing the tasks to be aware that someone is waiting on the future. But if you call f_deferred.wait(1ms);
, you simply get future_status::deferred
immediately.
Is there any way I can combine these two?
A concrete use case is a thread pool returning futures when people queue tasks. If an unqueued future is .get()
'd, I want to use the thread that is blocked to execute the task rather than having it idle. On the other hand, I want people with the returned futures to be able to determine if the task is finished, and even wait a bounded amount of time for the task to be finished. (in the case where you are waiting, I'm ok with your thread being idle during your wait)
Failing that, are there solutions in upcoming proposals that would solve this problem better than having my thread pool return a future with all of its limitations? I've heard that there is no future in futures and better solutions exist to the problem futures solve.
Taskflow implements a work stealing scheduler.
tf::Executor::corun waits for the child taskflow to finish but it doesn't block the worker thread. The worker thread that is running waiting task then starts stealing jobs from other workers. This happens inside the corun method itself.
https://taskflow.github.io/
The below code creates 1000 tasks which themselves wait on 1000 other tasks to complete. At the same time there are on 2 threads working and there is no deadlock.