13#if defined(_WIN32) || defined(_WIN64) || defined(__unix__) || defined(__APPLE__) || (defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HAS_GTHREADS) || defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
14#include <condition_variable>
17#ifndef CORIUM_HAS_STD_MUTEX
18#define CORIUM_HAS_STD_MUTEX 1
21#ifndef CORIUM_HAS_STD_MUTEX
22#define CORIUM_HAS_STD_MUTEX 0
28#include <sys/eventfd.h>
49 fn = [](
void* context) {
50 reinterpret_cast<SimpleFn>(context)();
52 arg =
reinterpret_cast<void*
>(simpleFn);
57 :
fn(contextFn),
arg(contextArg)
66 explicit operator bool() const noexcept {
77 template <
typename Rep,
typename Period>
78 void wait_for(
const std::chrono::duration<Rep, Period>&)
noexcept
80#if defined(__arm__) || defined(__aarch64__)
81 asm volatile(
"yield");
82#elif defined(__x86_64__)
83 __builtin_ia32_pause();
95#if CORIUM_HAS_STD_MUTEX
96 std::lock_guard<std::mutex> lock(_mutex);
103#if CORIUM_HAS_STD_MUTEX
104 std::lock_guard<std::mutex> lock(_mutex);
115 template <
typename Rep,
typename Period>
116 void wait_for(
const std::chrono::duration<Rep, Period>& timeout)
118#if CORIUM_HAS_STD_MUTEX
119 std::unique_lock<std::mutex> lock(_mutex);
120 _cv.wait_for(lock, timeout, [
this]() {
return _hasEvents; });
124#if defined(__arm__) || defined(__aarch64__)
125 asm volatile(
"yield");
133#if CORIUM_HAS_STD_MUTEX
135 std::condition_variable _cv;
137 bool _hasEvents =
false;
145 _userCallback = callback;
150 _flag.store(
true, std::memory_order_release);
151#if defined(__cpp_lib_atomic_wait) && __cpp_lib_atomic_wait >= 201907L
159 template <
typename Rep,
typename Period>
160 void wait_for(
const std::chrono::duration<Rep, Period>& timeout)
162 if (_flag.load(std::memory_order_acquire)) {
163 _flag.store(
false, std::memory_order_relaxed);
166 auto deadline = std::chrono::steady_clock::now() + timeout;
167 while (!_flag.load(std::memory_order_acquire)) {
168 if (std::chrono::steady_clock::now() >= deadline) {
171#if CORIUM_HAS_STD_MUTEX
172 std::this_thread::yield();
173#elif defined(__arm__) || defined(__aarch64__)
174 asm volatile(
"yield");
177 _flag.store(
false, std::memory_order_relaxed);
181 std::atomic<bool> _flag{
false};
182 StaticCallback _userCallback;
187class EventFdSignalPolicy {
189 EventFdSignalPolicy()
191 _fd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
194 ~EventFdSignalPolicy()
201 EventFdSignalPolicy(
const EventFdSignalPolicy&) =
delete;
202 EventFdSignalPolicy& operator=(
const EventFdSignalPolicy&) =
delete;
204 EventFdSignalPolicy(EventFdSignalPolicy&& rhs) noexcept : _fd(rhs._fd)
209 EventFdSignalPolicy& operator=(EventFdSignalPolicy&& rhs)
noexcept
212 if (_fd >= 0) ::close(_fd);
219 void setOnQueueNonEmpty(StaticCallback callback)
221 _userCallback = callback;
227 [[maybe_unused]]
auto res = ::write(_fd, &val,
sizeof(val));
233 template <
typename Rep,
typename Period>
234 void wait_for(
const std::chrono::duration<Rep, Period>& timeout)
240 int timeoutMs =
static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count());
241 int res = ::poll(&pfd, 1, timeoutMs);
242 if (res > 0 && (pfd.revents & POLLIN)) {
244 [[maybe_unused]]
auto bytes = ::read(_fd, &val,
sizeof(val));
248 [[nodiscard]]
int nativeHandle() const noexcept
255 StaticCallback _userCallback;
Signal Policy using C++20 std::atomic::wait() / notify_one() for zero-mutex futex signaling.
Definition SignalPolicies.hpp:141
void setOnQueueNonEmpty(StaticCallback callback)
Definition SignalPolicies.hpp:143
void signal()
Definition SignalPolicies.hpp:148
void wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition SignalPolicies.hpp:160
Signal Policy invoking an edge-triggered callback on 0->1 transition when queue becomes non-empty.
Definition SignalPolicies.hpp:91
void setOnQueueNonEmpty(StaticCallback callback)
Definition SignalPolicies.hpp:93
void signal()
Definition SignalPolicies.hpp:101
void wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition SignalPolicies.hpp:116
Signal Policy for busy-spin / polling event loops (sub-microsecond latency, zero signaling cost).
Definition SignalPolicies.hpp:72
void signal() noexcept
Definition SignalPolicies.hpp:75
void wait_for(const std::chrono::duration< Rep, Period > &) noexcept
Definition SignalPolicies.hpp:78
void setOnQueueNonEmpty(StaticCallback cb) noexcept
Definition SignalPolicies.hpp:74
Definition Application.hpp:16
Lightweight non-allocating static callback wrapper (function pointer + optional context argument).
Definition SignalPolicies.hpp:35
StaticCallback(ContextFn contextFn, void *contextArg)
Definition SignalPolicies.hpp:56
void(*)() SimpleFn
Definition SignalPolicies.hpp:36
void(*)(void *arg) ContextFn
Definition SignalPolicies.hpp:37
void operator()() const
Definition SignalPolicies.hpp:60
StaticCallback(SimpleFn simpleFn)
Definition SignalPolicies.hpp:44
ContextFn fn
Definition SignalPolicies.hpp:39
void * arg
Definition SignalPolicies.hpp:40