CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches

Data Structures

struct  Event
 
struct  SharedEvent
 

Macros

#define eventInit(e, ...)   _eventInit(e, opt_flags(__VA_ARGS__))
 
#define eventSignal(e)   eventSignalMany(e, 1)
 

Typedefs

typedef struct Event Event
 
typedef struct SharedEvent SharedEvent
 

Enumerations

enum  EVENTINITFUNC_FLAGS { EV_Spin = 1 , EV_UIEvent = 2 }
 Event initialization flags. More...
 

Functions

bool eventSignalMany (Event *e, int32 count)
 
bool eventSignalAll (Event *e)
 
bool eventWaitTimeout (Event *e, uint64 timeout)
 
void eventWait (Event *e)
 
bool eventSignalLock (Event *e)
 
bool eventReset (Event *e)
 
void eventDestroy (Event *e)
 
SharedEventsheventCreate (uint32 flags)
 
SharedEventsheventAcquire (SharedEvent *ev)
 
void sheventRelease (SharedEvent **pev)
 

Detailed Description

Events for thread signaling and synchronization.

Event is similar to auto-reset events on Windows - essentially a semaphore with a maximum value of 1, plus additional features like releasing multiple waiters at once and locking in a signaled state (manual-reset mode).

Events are designed for occasional signaling between threads. By default, they do NOT use adaptive spinning and go straight to kernel waits, assuming the signal is unlikely to arrive immediately. Use the EV_Spin flag for high-performance scenarios where signals are expected to arrive quickly (e.g., very busy work queues).

Basic usage:

Event ev;
eventInit(&ev);
// Thread 1: Wait for signal
eventWait(&ev);
// ... do work after being signaled
// Thread 2: Send signal
void eventWait(Event *e)
Definition event.h:160
#define eventInit(e,...)
Definition event.h:117
void eventDestroy(Event *e)
#define eventSignal(e)
Definition event.h:125
Definition event.h:53

Locking in signaled state (manual-reset mode):

eventSignalLock(&ev); // All subsequent waits return immediately
bool eventSignalLock(Event *e)

Macro Definition Documentation

◆ eventInit

#define eventInit (   e,
  ... 
)    _eventInit(e, opt_flags(__VA_ARGS__))

void eventInit(Event *e, [flags])

Initialize an event for use.

Events normally do NOT use adaptive spinning. This is because events are assumed to be used for occasional signaling between threads where the wait is likely to need kernel sleep. It would waste CPU to spin waiting for a signal unlikely to arrive soon.

For events used by high-performance queues or scenarios where work is usually ready, initialize with the EV_Spin flag to enable adaptive spinning.

Parameters
ePointer to uninitialized event structure
...(flags) Optional EVENTINITFUNC_FLAGS (e.g., EV_Spin, EV_UIEvent)

Definition at line 117 of file event.h.

◆ eventSignal

#define eventSignal (   e)    eventSignalMany(e, 1)

Signal the event, waking one waiting thread

Releases one waiting thread (if any) and sets the event to signaled state if no threads are waiting. This is the standard auto-reset behavior.

Parameters
eEvent to signal
Returns
true if a thread was woken or the event was signaled

Definition at line 125 of file event.h.

Typedef Documentation

◆ Event

typedef struct Event Event

Event synchronization primitive

Internal structure using futex-based signaling with optional adaptive spinning. Futex values: 0=not signaled, 1=signaled, >1=signaled for multiple waiters, -1=locked (manual-reset)

◆ SharedEvent

typedef struct SharedEvent SharedEvent

Reference-counted event for shared ownership between threads

A common pattern is an event shared between two threads where one signals the other when something is complete. This makes managing the event's lifetime difficult, as it's not safe for it to live on the stack or for one thread to free it.

SharedEvent provides a reference-counted wrapper that can be safely cleaned up when both threads are done with it using sheventAcquire() and sheventRelease().

Example:

int workerThread(Thread *self) {
SharedEvent *ev = stvlNextPtr(SharedEvent, self->args);
// do work...
eventSignal(&ev->ev);
sheventRelease(&ev); // worker releases its reference
return 0;
}
// Main thread creates shared event and passes to worker
SharedEvent *completion = sheventCreate(0);
Thread *worker = thrCreate(workerThread, _S"worker",
stvar(ptr, sheventAcquire(completion)));
// Wait for worker to complete
eventWait(&completion->ev);
// Clean up
sheventRelease(&completion); // main thread releases its reference
thrRelease(&worker);
#define _S
Creates a static ASCII string from a string literal.
Definition strbase.h:392
#define stvar(typen, val)
Definition stvar.h:153
#define stvlNextPtr(list)
Definition stvar.h:537
#define thrRelease(pthread)
Definition thread.h:164
SharedEvent * sheventCreate(uint32 flags)
void sheventRelease(SharedEvent **pev)
SharedEvent * sheventAcquire(SharedEvent *ev)
Event ev
Underlying event.
Definition event.h:98

Enumeration Type Documentation

◆ EVENTINITFUNC_FLAGS

Event initialization flags.

Enumerator
EV_Spin 

Use adaptive spinning instead of going straight to kernel wait.

EV_UIEvent 

May be woken up early by platform-specific UI events.

Definition at line 61 of file event.h.

Function Documentation

◆ eventDestroy()

void eventDestroy ( Event e)

Destroy an event and release its resources

Cleans up the event after use. The event must not have waiting threads when destroyed. After destruction, the event must be reinitialized before it can be used again.

Parameters
eEvent to destroy

◆ eventReset()

bool eventReset ( Event e)

Manually reset the event to unsignaled state

Clears the signaled state, causing subsequent waits to block until the event is signaled again. This can also unlock an event that was locked with eventSignalLock().

Parameters
eEvent to reset
Returns
true if the event was signaled, false if already unsignaled

◆ eventSignalAll()

bool eventSignalAll ( Event e)

Signal the event, waking all waiting threads

Broadcast signal that releases all threads currently waiting on the event. This is a one-time broadcast; threads that wait after this call will block normally.

Parameters
eEvent to signal
Returns
true on success

◆ eventSignalLock()

bool eventSignalLock ( Event e)

Signal the event and lock it in the signaled state

Sets the event to permanently signaled (manual-reset mode). All subsequent waits return immediately without blocking. This is useful for thread shutdown where you want to ensure no races without repeatedly signaling.

Parameters
eEvent to signal and lock
Returns
true on success

◆ eventSignalMany()

bool eventSignalMany ( Event e,
int32  count 
)

Signal the event, waking up to a specified number of waiting threads

Releases up to 'count' waiting threads. If fewer threads are waiting, all are released. The event remains signaled if no threads are waiting.

Parameters
eEvent to signal
countMaximum number of threads to wake
Returns
true if any threads were woken or the event was signaled

◆ eventWait()

void eventWait ( Event e)
inline

Wait for an event to be signaled indefinitely

Blocks until the event is signaled. Equivalent to eventWaitTimeout() with timeForever.

Parameters
eEvent to wait on

Definition at line 160 of file event.h.

References eventWaitTimeout(), and timeForever.

◆ eventWaitTimeout()

bool eventWaitTimeout ( Event e,
uint64  timeout 
)

Wait for an event to be signaled with a timeout

Blocks until the event is signaled or the timeout expires. When signaled, the event auto-resets to unsignaled state (unless locked with eventSignalLock()).

Note
May produce spurious wakeups if multiple threads call eventWaitTimeout() with timeouts simultaneously.
Parameters
eEvent to wait on
timeoutMaximum time to wait in nanoseconds (use timeForever for infinite)
Returns
true if the event was signaled, false if timeout expired

Referenced by eventWait().

◆ sheventAcquire()

SharedEvent * sheventAcquire ( SharedEvent ev)

Acquire a reference to a shared event

Increments the reference count. Each call to sheventAcquire() must be paired with a corresponding sheventRelease().

Parameters
evSharedEvent to acquire
Returns
The same SharedEvent pointer

◆ sheventCreate()

SharedEvent * sheventCreate ( uint32  flags)

Create a new reference-counted shared event

Allocates and initializes a SharedEvent with a reference count of 1. Use sheventAcquire() to add references and sheventRelease() to release them.

Parameters
flagsOptional EVENTINITFUNC_FLAGS (e.g., EV_Spin, EV_UIEvent)
Returns
Newly allocated SharedEvent

◆ sheventRelease()

void sheventRelease ( SharedEvent **  pev)

Release a reference to a shared event

Decrements the reference count and destroys the SharedEvent when it reaches zero. Sets the pointer to NULL after release.

Parameters
pevPointer to SharedEvent pointer