Tickets with target threads is as simple as dropping in circular_buffer[ticket_number % buffer_size] = my_thread_id before checking if you have the lock or you have to sleep instead. The exiting thread can remove its thread id slot and wake the next thread if there happens to be one registered.
Just to follow up on that, sleeping-waking code is a caveat. Something as simple as:
Code:
if (needs_to_sleep)
{
sleep();
}
(...)
wake_thread_if_sleeping();
Is a race condition, if the wake is performed between the if and the sleep. Instead you can modify wake to prevent the next sleep() call from occurring if the thread is running, or you can do something else/more complicated. It's actually a more fundamental primitive than setting up mutexes.
One question though: what about if we're interrupted after getting the ticket, but before placing our thread ID into the circular_buffer?