One-time atomic tokens
include/sync/once_token.h View source View on GitHubMacros
Section titled “Macros”ONCE_TOKEN_DEFINE
Section titled “ONCE_TOKEN_DEFINE”#define ONCE_TOKEN_DEFINE(type, name) source Expansion
#define ONCE_TOKEN_DEFINE(type, name) \
struct { \
atomic(type) state; \
} name ONCE_TOKEN_INIT
Section titled “ONCE_TOKEN_INIT”#define ONCE_TOKEN_INIT(val) source Expansion
#define ONCE_TOKEN_INIT(val) {.state = ATOMIC_VAR_INIT(val)} once_token_typecheck_internal
Section titled “once_token_typecheck_internal”#define once_token_typecheck_internal(tok) source Expansion
#define once_token_typecheck_internal(tok) ((void) sizeof((tok)->state)) once_token_typecheck_internal_type
Section titled “once_token_typecheck_internal_type”#define once_token_typecheck_internal_type(tok, type) source Expansion
#define once_token_typecheck_internal_type(tok, type) \
ct_typecheck(type, atomic_load_rlx(&(tok)->state)) once_token_typecheck_internal_bool
Section titled “once_token_typecheck_internal_bool”#define once_token_typecheck_internal_bool(tok) source Expansion
#define once_token_typecheck_internal_bool(tok) \
once_token_typecheck_internal_type(tok, bool) once_token_typecheck_internal_same
Section titled “once_token_typecheck_internal_same”#define once_token_typecheck_internal_same(tok1, tok2) source Expansion
#define once_token_typecheck_internal_same(tok1, tok2) \
ct_typecheck_same(atomic_load_rlx(&(tok1)->state), \
atomic_load_rlx(&(tok2)->state)) once_token_init_1
Section titled “once_token_init_1”#define once_token_init_1(tok) source Expansion
#define once_token_init_1(tok) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal_bool(__ot_tok); \
static_assert(cc_generic((__ot_tok->state), bool : 1, default : 0), \
"once_token_init_1 requires a boolean token"); \
atomic_init(&__ot_tok->state, false); \
}) once_token_init_2
Section titled “once_token_init_2”#define once_token_init_2(tok, val) source Expansion
#define once_token_init_2(tok, val) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal(__ot_tok); \
typeof(atomic_load_rlx(&__ot_tok->state)) __ot_val = (val); \
atomic_init(&__ot_tok->state, __ot_val); \
}) once_token_init
Section titled “once_token_init”#define once_token_init(...) source Expansion
#define once_token_init(...) PP_CALL(once_token_init, __VA_ARGS__) once_token_claim_4
Section titled “once_token_claim_4”#define once_token_claim_4(tok, from, to, out) source The 2 and 4 argument versions return what was actually there, which can be used to inspect whether something unexpected happened
Expansion
#define once_token_claim_4(tok, from, to, out) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal(__ot_tok); \
ct_typecheck_same(from, to); \
typeof(atomic_load_rlx(&__ot_tok->state)) __ot_exp = (from); \
typeof(__ot_exp) __ot_to = (to); \
__auto_type __ot_out = (out); \
static_assert(ct_is_type(typeof(__ot_exp) *, out) || \
(ct_is_const(out) && (out) == NULL), \
"once_token_claim out must point to the token state " \
"type or be NULL"); \
bool ret = atomic_cas_strong(&__ot_tok->state, &__ot_exp, __ot_to, \
mo_acq_rel, mo_acquire); \
if (__ot_out) \
*((typeof(__ot_exp) *) __ot_out) = __ot_exp; \
ret; \
}) once_token_claim_3
Section titled “once_token_claim_3”#define once_token_claim_3(tok, from, to) source Expansion
#define once_token_claim_3(tok, from, to) \
once_token_claim_4(tok, from, to, NULL) once_token_claim_2
Section titled “once_token_claim_2”#define once_token_claim_2(tok, out) source Expansion
#define once_token_claim_2(tok, out) \
({ \
once_token_typecheck_internal_bool(tok); \
static_assert(cc_generic(((tok)->state), bool : 1, default : 0), \
"once_token_claim_1 argument requires a boolean token"); \
once_token_claim_4(tok, false, true, out); \
}) once_token_claim_1
Section titled “once_token_claim_1”#define once_token_claim_1(tok) source Expansion
#define once_token_claim_1(tok) once_token_claim_2(tok, NULL) once_token_claim
Section titled “once_token_claim”#define once_token_claim(...) source Expansion
#define once_token_claim(...) PP_CALL(once_token_claim, __VA_ARGS__) once_token_claimed_1
Section titled “once_token_claimed_1”#define once_token_claimed_1(tok) source Expansion
#define once_token_claimed_1(tok) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal_bool(__ot_tok); \
static_assert(cc_generic((__ot_tok->state), bool : 1, default : 0), \
"once_token_claimed_1 requires a boolean token"); \
\
atomic_load_acq(&__ot_tok->state); \
}) once_token_claimed_2
Section titled “once_token_claimed_2”#define once_token_claimed_2(tok, val) source Expansion
#define once_token_claimed_2(tok, val) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal(__ot_tok); \
typeof(atomic_load_rlx(&__ot_tok->state)) __ot_val = (val); \
\
atomic_load_acq(&__ot_tok->state) == __ot_val; \
}) once_token_claimed
Section titled “once_token_claimed”#define once_token_claimed(...) source Expansion
#define once_token_claimed(...) PP_CALL(once_token_claimed, __VA_ARGS__) once_token_reset_1
Section titled “once_token_reset_1”#define once_token_reset_1(tok) source Expansion
#define once_token_reset_1(tok) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal_bool(__ot_tok); \
static_assert(cc_generic((__ot_tok->state), bool : 1, default : 0), \
"once_token_reset_1 requires a boolean token"); \
atomic_store_release(&__ot_tok->state, false); \
}) once_token_reset_2
Section titled “once_token_reset_2”#define once_token_reset_2(tok, val) source Expansion
#define once_token_reset_2(tok, val) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal(__ot_tok); \
typeof(atomic_load_rlx(&__ot_tok->state)) __ot_val = (val); \
atomic_store_release(&__ot_tok->state, __ot_val); \
}) once_token_reset
Section titled “once_token_reset”#define once_token_reset(...) source Expansion
#define once_token_reset(...) PP_CALL(once_token_reset, __VA_ARGS__) once_token_read
Section titled “once_token_read”#define once_token_read(tok) source Expansion
#define once_token_read(tok) \
({ \
__auto_type __ot_tok = (tok); \
once_token_typecheck_internal(__ot_tok); \
atomic_load_acq(&__ot_tok->state); \
})