#ifndef RAY_ENC_ONCE_H
#define RAY_ENC_ONCE_H
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <rayforce.h>
typedef struct {
char code[8];
char msg[256];
bool is_transient;
} ray_enc_snap_t;
enum { RAY_ENC_ONCE_IDLE = 0, RAY_ENC_ONCE_RUNNING, RAY_ENC_ONCE_DONE,
RAY_ENC_ONCE_FAILED, RAY_ENC_ONCE_DRAINING };
typedef struct {
_Atomic(uint32_t) lock;
_Atomic(uint32_t) state;
uint32_t waiters;
uint64_t attempt;
ray_enc_snap_t snap;
} ray_enc_once_t;
typedef ray_t* (*ray_enc_once_fn)(void* ctx, ray_enc_snap_t* fail);
void ray_enc_once_init(ray_enc_once_t* o);
ray_t* ray_enc_once_get(ray_enc_once_t* o, ray_t** slot, ray_enc_once_fn fn, void* ctx);
uint32_t ray_enc_once_waiters(ray_enc_once_t* o);
bool ray_enc_code_transient(const char* code);
void ray_enc_snap_take(ray_enc_snap_t* s, ray_t* err);
void ray_enc_snap_set(ray_enc_snap_t* s, const char* code, const char* fmt, ...);
ray_t* ray_enc_snap_error(const ray_enc_snap_t* s);
void ray_enc_yield(void);
void ray_enc_once_test_drain(ray_enc_once_t* o, const ray_enc_snap_t* snap, uint32_t waiters);
void ray_enc_once_test_waiter_done(ray_enc_once_t* o, ray_enc_snap_t* out);
#endif