A counter similar to a conditional variable that allows atomic increment and decrement and to wait for the atomic compare and exchange for a specific value. More...
(Note that these are not member functions.)
|unsigned||p99_futex_add (p99_futex volatile *p00_fut, unsigned p00_hmuch, unsigned p00_cstart, unsigned p00_clen, unsigned p00_wmin, unsigned p00_wmax)|
|increment the counter of p00_fut atomically by p00_hmuch. More...|
|#define||P99_FUTEX_COMPARE_EXCHANGE(FUTEX, ACT, EXPECTED, DESIRED, WAKEMIN, WAKEMAX)|
|a catch all macro to operate on p99_futex More...|
|void||p99_futex_destroy (p99_futex *p00_c)|
|Destroy an p99_futex object. More...|
|unsigned||p99_futex_exchange (p99_futex volatile *p00_fut, unsigned p00_desired, unsigned p00_cstart, unsigned p00_clen, unsigned p00_wmin, unsigned p00_wmax)|
|Unconditionally and atomically set the futex p00_fut to value p00_desired. More...|
|p99_futex *||p99_futex_init (p99_futex *p00_c, unsigned p00_ini)|
|Initialize an p99_futex object. More...|
|unsigned||p99_futex_load (p99_futex volatile *p00_fut)|
|Obtain the value of futex p00_fut atomically. More...|
|the maximum number of waiters that an p99_futex may have More...|
|void||p99_futex_wait (p99_futex volatile *p00_fut)|
|Unconditionally wait for futex p00_fut. More...|
|void||p99_futex_wakeup (p99_futex volatile *p00_fut, unsigned p00_wmin, unsigned p00_wmax)|
|Wake up threads that are waiting for a futex. More...|
A counter similar to a conditional variable that allows atomic increment and decrement and to wait for the atomic compare and exchange for a specific value.
This data structure is inspired by the linux system call
futex, thus the name. Linux futex (Fast User muTEX) allows to have a full fledged control structure on just one
int. The contents of the
int is taken to reflect the state of the structure and its address and value can be used to block the calling thread until a certain value is reached. That feature transparently uses the kernel address of the
int, so the waiting can be organized even between different processes that don't share their address space.
p99_futex are build around this only that for ideological reasons the base type is an
unsigned, instead of an
There are several operations that work on that value similar to their atomic analogues:
The last three may also be used to wakeup threads that are waiting on the futex, the very last, a macro, may also put the calling thread to a blocking or waiting state.
There is only p99_futex_add operation and no subtraction. That operation is simply not needed, because adding a negative value in
unsigned arithmetic will magically do the right thing, here.
If the value of the futex isn't as expected, a thread may wait (p99_futex_wait) until another thread notifies it (p99_futex_wakeup) about a change of the value. That wait is not (or scarcely) using resources. Such a waiting thread will only be awoken if another thread wants so. Either by calling an explicit p99_futex_wakeup, or implicitly by changing the value through p99_futex_exchange, p99_futex_add or P99_FUTEX_COMPARE_EXCHANGE.
:p99_futex_exchange and p99_futex_add wake up waiters if the value reaches a certain interval. Therefore they have additional arguments
p00_wmax that give two ranges. One of the conditional values and one of a range of waiters that should be woken up.
p99_futex is implemented more or less efficiently according to the features that the platform provides: