-2

There's a ton of questions and answers already (Exhibit A) about how to wake up a sleeping thread from another thread or how to have a thread sleep until it receives an instruction (same thing but described from another direction), but my question is more specifically about what is actually happening under the hood.

Is the only way to do this for the thread to itself choose to sleep and then check its queue, or some variable somewhere when it wakes, then sleep again?

Another method that I've seen mentioned is to use a mutex. Have the thread try to lock a locked mutex and it'll sleep then magically wake up when the mutex is unlocked by its original locker. But isn't that just doing the same thing under the hood? I.e. going to sleep for x period of time then waking up at intervals to check if its still locked?

Is there any kind of wake functionality that doesn't require sleeping for set intervals? Like some kind of OS-level push? For example, the OS must be keeping track of when it needs to wake the sleeping thread, right? So in theory if you could change that number to 0 or 1 then it would wake up sooner. That makes sense.

The reason why I ask is because there's a tradeoff between how long it takes to wake up, and the amount of resources its using. The longer it sleeps between checks, the slower it is to respond, and the shorter it waits the more cycles it wastes checking something that another part of the application already knows has not changed. Seems inefficient.

Alasdair
  • 13,348
  • 18
  • 82
  • 138
  • You're not mentioning platform, so I don't know what sync primitives you have at your disposal, but on Windows I typically use an `event` for this scenario. You can wait on an event with a timeout. If the event isn't signaled this is like `Sleep`, but you can wake it up at any time by setting it. – 500 - Internal Server Error Mar 22 '21 at 12:33
  • Exactly how the different approaches work under the hood will depends on the OS and the implementation. You need to be more specific. – super Mar 22 '21 at 12:34
  • 1
    C++20 has `std::latch` that might potentially be useful here, but honestly, don't know what it does under the hood. – alagner Mar 22 '21 at 12:39
  • Classic solution: semaphore. – Martin James Mar 23 '21 at 01:12
  • 'going to sleep for x period of time then waking up at intervals to check if its still locked?' no, that is not how blocked threads get unblocked! – Martin James Mar 23 '21 at 01:14
  • A thread blocked on an OS synchro like an event, semaphore or condvar does not need to periodically wake up and check annything. Typically, the thread descriptor, (pointer, ref, whatever), is stored in a container, (queue, list), that belongs to the synchro. When the synchro is signaled, the waiting thread is dequeued and made ready/running. There is no need for latency-ridden wasteful polling. – Martin James Mar 23 '21 at 01:20

1 Answers1

0

You are misunderstanding condition variables. The thread in the first example in this answer will wake up after 1000 seconds or when the condition variable is notified. There is no tradeoff.

Likewise, a thread that waits for a mutex with a 1000-second timeout will wake up after 1000 seconds, or when the mutex is available and the thread acquires it.

You don't have to set low timeouts to get fast wakeups.

But isn't that just doing the same thing under the hood? I.e. going to sleep for x period of time then waking up at intervals to check if its still locked?

No, it isn't. It tells the OS to wake it up whenever it's unlocked or after 1000 seconds.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • OK. *How* does it tell the OS to wake it up? – Alasdair Mar 22 '21 at 12:41
  • 2
    @Alasdair on Windows? By calling [WaitForSingleObject](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject), probably. On Linux, by calling [futex](https://man7.org/linux/man-pages/man2/futex.2.html), probably. – user253751 Mar 22 '21 at 14:43
  • 1
    @Alasdair Waking up a "sleeping" thread usually requires some kernel mechanism, since it is basically a matter of a scheduler. This is, for example, the reason why you cannot implement a mutex in the user space (but spin lock you can). – Daniel Langr Apr 14 '21 at 10:09