P99
|
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...
#include <p99_futex.h>
Related Functions | |
(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... | |
#define | P99_FUTEX_MAX_WAITERS (INT_MAX+0U) |
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 int
.
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_cstart
, p00_clen
and p00_wmin
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_COMPARE_EXCHANGE is the most generic tool to operate on a p99_futex, since it is able to wait until the value is as expected, change it and then notify other threads about the change.
p99_futex is implemented more or less efficiently according to the features that the platform provides:
Definition at line 163 of file p99_futex.h.