A blocking call works however it is that the OS and implementation want them to work.
doesn't there have to be a busy wait somewhere in order to determine when the wait condition is fulfilled?
That depends on how you define "busy wait".
If you were to, for example, check the value of an atomic
in a loop to see if a thread should proceed, that is typically what is referred to as a "busy wait". Your thread is just sitting there until it can proceed. Wouldn't it be great if the thread of execution would, instead of sitting in a loop, just stop executing until that atomic
value gets changed?
If that could happen, then that means CPU computational resources (and possibly battery life) wouldn't be wasted sitting there doing nothing. The CPU computational time could be spent on a thread that's actually doing something, or maybe the CPU could under-clock itself so as not to waste power on a task that isn't doing much. Or whatever.
But the OS doesn't know that it could just stop executing your thread. To the OS, a thread that's sitting in a loop is no different from a thread that is doing useful work. The OS can't tell, so it will treat your busy-wait just like any other task.
If you want to surrender your computational resources to the OS so it can find something useful to do, you must do it in a way the OS recognizes as a waiting operation. OS synchronization primitives like mutex locks are places where the OS can recognize not just that your thread is waiting, but it can also recognize what it is waiting on. This allows the OS to halt your thread of execution when you wait and wake it up ASAP once that mutex is released. There are other OS primitives that can do that too.
What's going on behind the scenes in future::wait
is something like that. The shared state of a promise/future pair have some kind of OS-recognized synchronization primitive. To wait
on the future
means to block on that primitive, thus surrendering your thread's execution in a way the OS recognizes as waiting on a particular thing. Once the promise
is fulfilled, the synchronization primitive is released and your thread can proceed.
You could call that a "busy wait", but that's not how the term is typically used.
.wait()
, is also considered a "blocking call." – Robert Harvey Jun 17 '21 at 21:46.wait()
call could merely be considered an ordinary method call, in this context. What is it waiting for? The result of the promise/future to arrive. – Robert Harvey Jun 17 '21 at 21:47std::future
is here, if you're so inclined. – Robert Harvey Jun 17 '21 at 21:53#include <mutex>
at line 38, which is the first mechanism I thought of that might accomplish this. – Robert Harvey Jun 17 '21 at 21:57async
systems, like the one in C#, sign on the remainder of the method as a continuation running on the same thread. See here for an explanation. – Robert Harvey Jun 17 '21 at 22:13