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

Macros

#define cchainAttach(chain, func, ...)   _cchainAttach(chain, func, 0, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })
 
#define cchainAttachToken(chain, func, token, ...)   _cchainAttach(chain, func, token, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })
 
#define cchainCall(chain, ...)   _cchainCall(chain, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })
 
#define cchainCallOnce(chain, ...)   _cchainCallOnce(chain, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })
 

Functions

bool cchainDetach (cchain *chain, closureFunc func, intptr token)
 
bool cchainTransfer (cchain *dest, cchain *src)
 
bool cchainClone (cchain *dest, _In_ptr_opt_ cchain *src)
 
bool cchainReset (cchain *chain)
 
bool cchainClear (cchain *chain)
 
void cchainDestroy (cchain *chain)
 

Detailed Description

Thread-safe linked lists of closures for implementing multi-callback event systems.

Closure chains are the recommended way to implement event handlers that can have multiple subscribers. They provide thread-safe attachment and detachment of callbacks, with optional tokens for selective removal.

Key features:

The token, if provided, is automatically added as the last captured variable in each closure, after any variables passed to cchainAttach().

Basic usage:

cchain eventChain = NULL;
bool handler1(stvlist *cvars, stvlist *args) {
string event = stvlNextPtr(string, args);
// handle event...
return true;
}
bool handler2(stvlist *cvars, stvlist *args) {
int captured = stvlNextInt(cvars);
// handle event with captured data...
return true;
}
// Attach handlers
cchainAttach(&eventChain, handler1);
cchainAttach(&eventChain, handler2, stvar(int32, 42));
// Fire event - calls all handlers
cchainCall(&eventChain, stvar(string, _S"myEvent"));
// Cleanup
cchainDestroy(&eventChain);
#define cchainCall(chain,...)
Definition cchain.h:127
#define cchainAttach(chain, func,...)
Definition cchain.h:81
void cchainDestroy(cchain *chain)
#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

Using tokens for selective detachment:

intptr token = 12345;
cchainAttachToken(&chain, myHandler, token, stvar(int32, data));
// Later...
cchainDetach(&chain, myHandler, token); // Removes only this instance
#define cchainAttachToken(chain, func, token,...)
Definition cchain.h:96
bool cchainDetach(cchain *chain, closureFunc func, intptr token)

Macro Definition Documentation

◆ cchainAttach

#define cchainAttach (   chain,
  func,
  ... 
)    _cchainAttach(chain, func, 0, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })

bool cchainAttach(cchain *chain, closureFunc func, ...)

Attach a closure to the chain without a token.

Adds a new closure to the chain with the specified function and captured variables. Can fail if the chain has been consumed by cchainCallOnce().

Parameters
chainPointer to closure chain (may be NULL, will be initialized)
funcClosure function to attach
...Zero or more stvar arguments to capture
Returns
true on success, false if the chain is invalid

Definition at line 81 of file cchain.h.

◆ cchainAttachToken

#define cchainAttachToken (   chain,
  func,
  token,
  ... 
)    _cchainAttach(chain, func, token, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })

bool cchainAttachToken(cchain *chain, closureFunc func, intptr token, ...)

Attach a closure to the chain with an identifying token.

The token should be a nonzero value that can be used to selectively detach this specific closure instance using cchainDetach(). The token is automatically added as the last captured variable passed to the closure function.

Parameters
chainPointer to closure chain (may be NULL, will be initialized)
funcClosure function to attach
tokenNonzero identifier for this closure instance
...Zero or more stvar arguments to capture
Returns
true on success, false if the chain is invalid

Definition at line 96 of file cchain.h.

◆ cchainCall

#define cchainCall (   chain,
  ... 
)    _cchainCall(chain, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })

bool cchainCall(cchain *chain, ...)

Call all closures in the chain with the given arguments.

Invokes each closure in the chain, passing the provided arguments. Returns true only if all closures return true. The chain is cloned internally before calling, so callbacks can take arbitrary time without blocking other threads.

Note: Unlike closureCall(), this requires a pointer to the chain (not the chain itself) to perform atomic reads for thread safety.

Parameters
chainPointer to closure chain
...Zero or more stvar arguments to pass to each closure
Returns
true if all closures returned true, false otherwise or if chain is invalid

Definition at line 127 of file cchain.h.

◆ cchainCallOnce

#define cchainCallOnce (   chain,
  ... 
)    _cchainCallOnce(chain, count_macro_args(__VA_ARGS__), (stvar[]) { __VA_ARGS__ })

bool cchainCallOnce(cchain *chain, ...)

Call all closures in the chain once, then invalidate the chain.

Atomically calls all closures and marks the chain as invalid, preventing future attachments. This is useful for one-time events to avoid race conditions where callbacks might be added after the event has already fired.

Parameters
chainPointer to closure chain (will be invalidated)
...Zero or more stvar arguments to pass to each closure
Returns
true if all closures returned true, false otherwise or if chain was already invalid

Definition at line 142 of file cchain.h.

Function Documentation

◆ cchainClear()

bool cchainClear ( cchain *  chain)

Remove all closures from the chain

Clears all closures from the chain but leaves it in a valid state for future attachments. Unlike cchainDestroy(), the chain can be reused after calling this.

Parameters
chainPointer to closure chain
Returns
true on success, false if chain is invalid

◆ cchainClone()

bool cchainClone ( cchain *  dest,
_In_ptr_opt_ cchain *  src 
)

Clone a closure chain to a new location

Creates a copy of all closures in src and adds them to dest. Unlike transfer, the source chain remains valid and usable. Cloned closures are inserted before any existing closures in dest.

Parameters
destDestination chain pointer
srcSource chain pointer (remains valid)
Returns
true on success, false if dest is invalid

◆ cchainDestroy()

void cchainDestroy ( cchain *  chain)

Destroy a closure chain and all its closures

Frees all closures and invalidates the chain. The chain cannot be used after this call.

Parameters
chainPointer to closure chain

◆ cchainDetach()

bool cchainDetach ( cchain *  chain,
closureFunc  func,
intptr  token 
)

Detach a closure from the chain

Attempts to remove a previously attached closure from the chain. The function pointer and token must both match the values used when attaching (use 0 for token if none was specified).

Parameters
chainPointer to closure chain
funcClosure function to detach
tokenToken that was used when attaching (0 if none)
Returns
true if the closure was found and removed, false otherwise

◆ cchainReset()

bool cchainReset ( cchain *  chain)

Reset a previously invalidated closure chain

Resets a chain that was invalidated by cchainCallOnce() or cchainTransfer() so it can be reused. Only works on chains that are in the invalid state.

Parameters
chainPointer to invalidated closure chain
Returns
true if the chain was reset, false if it was not invalidated

◆ cchainTransfer()

bool cchainTransfer ( cchain *  dest,
cchain *  src 
)

Transfer a closure chain to a new location

Safely moves the chain from src to dest, invalidating the source. The transferred chain is inserted before any existing closures in dest. Future attach attempts to src will fail.

Parameters
destDestination chain pointer
srcSource chain pointer (will be invalidated)
Returns
true on success, false if dest is invalid