carb::thread::futex
Defined in carb/thread/Futex.h
- 
struct futex
- Futex namespace. - FUTEX stands for Fast Userspace muTEX. Put simply, it’s a way of efficiently blocking threads by waiting on an address as long as the value at that address matches the expected value. Atomically the value at the address is checked and if it matches the expected value, the thread enters a wait-state (until notified). If the value does not match expectation, the thread does not enter a wait-state. This low-level system is the foundation for many synchronization primitives. - On Windows, this functionality is achieved through APIs - WaitOnAddress,- WakeByAddressSingleand- WakeByAddressAlland support values of 1, 2, 4 or 8 bytes. Much of the functionality is implemented without requiring system calls, so attempting to wait when the value is different, or notifying without any waiting threads are very efficient—only a few nanoseconds each. Calls which wait or notify waiting threads will enter the kernel and be on the order of microseconds.- The Linux kernel provides a - futexsyscall for this functionality, with two downsides. First, a- futexcan be only four bytes (32-bit), and second due to being a syscall even calls with no work can take nearly a microsecond. macOS has a similar feature in the undocumented- __ulock_waitand- __ulock_wakecalls.- For Linux and macOS, the Carbonite futex system has a user-space layer called - ParkingLotthat supports values of 1, 2, 4 or 8 bytes and eliminates most syscalls unless work must actually be done. This causes no-op work to be on the order of just a few nanoseconds with worst-case timing being comparable to syscall times.- Linux information: http://man7.org/linux/man-pages/man2/futex.2.html - Windows information: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress - Warning - Futex is a very low-level system; generally its use should be avoided. There are plenty of higher level synchronization primitives built on top of Futex that should be used instead, such as - carb::cpp::atomic.- Public Static Functions - 
template<class T>
 static inline void wait(const std::atomic<T> &val, T compare) noexcept
- Waits on a value until woken. - The value at - valis atomically compared with- compare. If the values are not equal, this function returns immediately. Otherwise, if the values are equal, this function sleeps the current thread. Waking is not automatic when the value changes. The thread that changes the value must then call wake() to wake the waiting threads.- Note - Futexes are prone to spurious wakeups. It is the responsibility of the caller to determine whether a return from wait() is spurious or valid. - Parameters
- val – The value that is read atomically. If this matches - compare, the thread sleeps.
- compare – The expected value. 
 
 
 - 
template<class T, class Rep, class Period>
 static inline bool wait_for(const std::atomic<T> &val, T compare, std::chrono::duration<Rep, Period> duration)
- Waits on a value until woken or timed out. - The value at - valis atomically compared with- compare. If the values are not equal, this function returns immediately. Otherwise, if the values are equal, this function sleeps the current thread. Waking is not automatic when the value changes. The thread that changes the value must then call wake() to wake the waiting threads.- Note - Futexes are prone to spurious wakeups. It is the responsibility of the caller to determine whether a return from wait() is spurious or valid. - Note - On Linux, interruptions by signals are treated as spurious wakeups. - Parameters
- val – The value that is read atomically. If this matches - compare, the thread sleeps.
- compare – The expected value. 
- duration – The relative time to wait. 
 
- Returns
- trueif woken legitimately or spuriously;- falseif timed out.
 
 - 
template<class T, class Clock, class Duration>
 static inline bool wait_until(const std::atomic<T> &val, T compare, std::chrono::time_point<Clock, Duration> time_point)
- Waits on a value until woken or timed out. - The value at - valis atomically compared with- compare. If the values are not equal, this function returns immediately. Otherwise, if the values are equal, this function sleeps the current thread. Waking is not automatic when the value changes. The thread that changes the value must then call wake() to wake the waiting threads.- Note - Futexes are prone to spurious wakeups. It is the responsibility of the caller to determine whether a return from wait() is spurious or valid. - Parameters
- val – The value that is read atomically. If this matches - compare, the thread sleeps.
- compare – The expected value. 
- time_point – The absolute time point to wait until. 
 
- Returns
- trueif woken legitimately or spuriously;- falseif timed out.
 
 - 
template<class T>
 static inline void notify(std::atomic<T> &val, unsigned count, unsigned maxCount = unsigned(INT_MAX)) noexcept
- Wakes threads that are waiting in one of the - futexwait functions.- Note - To wake all threads waiting on - val, use wake_all().- Parameters
- val – The same value that was passed to wait(), wait_for() or wait_until(). 
- count – The number of threads to wake. To wake all threads, use wake_all(). 
- maxCount – An optimization for Windows that specifies the total number of threads that are waiting on - addr. If- countis greater-than-or-equal-to- maxCountthen a specific API call that wakes all threads is used. Ignored on Linux.
 
 
 - 
template<class T>
 static inline void wake(std::atomic<T> &val, unsigned count, unsigned maxCount = unsigned(INT_MAX)) noexcept
- Wakes threads that are waiting in one of the - futexwait functions.- Note - To wake all threads waiting on - val, use wake_all().- Parameters
- val – The same value that was passed to wait(), wait_for() or wait_until(). 
- count – The number of threads to wake. To wake all threads, use wake_all(). 
- maxCount – An optimization for Windows that specifies the total number of threads that are waiting on - addr. If- countis greater-than-or-equal-to- maxCountthen a specific API call that wakes all threads is used. Ignored on Linux.
 
 
 - 
template<class T>
 static inline void notify_one(std::atomic<T> &val) noexcept
- Wakes one thread that is waiting in one of the - futexwait functions.- Parameters
- val – The same value that was passed to wait(), wait_for() or wait_until(). 
 
 - 
template<class T>
 static inline void wake_one(std::atomic<T> &val) noexcept
- Wakes one thread that is waiting in one of the - futexwait functions.- Parameters
- val – The same value that was passed to wait(), wait_for() or wait_until(). 
 
 - 
template<class T>
 static inline void notify_all(std::atomic<T> &val) noexcept
- Wakes all threads that are waiting in one of the - futexwait functions.- Parameters
- val – The same value that was passed to wait(), wait_for() or wait_until(). 
 
 - 
template<class T>
 static inline void wake_all(std::atomic<T> &val) noexcept
- Wakes all threads that are waiting in one of the - futexwait functions.- Parameters
- val – The same value that was passed to wait(), wait_for() or wait_until(). 
 
 
- 
template<class T>