// calogHandle.h -- thread-safe, typed integer handle table for calog libraries.
//
// calog library natives (DB, network) are registered INLINE, so they run on whatever
// context thread called them -- many at once. A resource (a connection, a socket) is
// therefore handed to a script as an opaque int64 handle backed by this table, which is
// mutex-guarded and tags every entry with a type so a DB handle can never be used where a
// socket is expected. Handles are monotonic and never reused, so a stale handle from a
// closed resource reliably fails to resolve rather than aliasing a live one.

#ifndef CALOG_HANDLE_H
#define CALOG_HANDLE_H

#include <stdbool.h>
#include <stdint.h>

typedef struct CalogHandleTableT CalogHandleTableT;

// Invoked for each still-open entry at table destroy, to release the resource.
typedef void (*CalogHandleCloserT)(uint32_t type, void *resource);

// Add returns a positive handle, or 0 on out-of-memory. Get/Remove return the resource
// only when the handle exists AND its type matches; otherwise NULL. Remove also frees the
// slot. Destroy closes every remaining entry through the closer (may be NULL) and frees
// the table.
CalogHandleTableT *calogHandleTableCreate(void);
void               calogHandleTableDestroy(CalogHandleTableT *table, CalogHandleCloserT closer);
int64_t            calogHandleAdd(CalogHandleTableT *table, uint32_t type, void *resource);
void              *calogHandleGet(CalogHandleTableT *table, int64_t handle, uint32_t type);
void              *calogHandleRemove(CalogHandleTableT *table, int64_t handle, uint32_t type);

// GetAny/RemoveAny resolve a handle of UNKNOWN type in a single locked scan, returning the
// resource and writing its type to *typeOut (0 when the handle is absent). For a table whose
// entries are all one library's own resources, this replaces a fan of type-specific probes.
void              *calogHandleGetAny(CalogHandleTableT *table, int64_t handle, uint32_t *typeOut);
void              *calogHandleRemoveAny(CalogHandleTableT *table, int64_t handle, uint32_t *typeOut);

// Number of live entries of the given type currently in the table.
int32_t            calogHandleCount(CalogHandleTableT *table, uint32_t type);

// Atomically remove and return the first live entry of `type` whose resource satisfies pred
// (called under the table lock), or NULL if none. Lets an owner sweep entries by a runtime
// property (e.g. a task whose context thread has finished) in one locked pass.
void              *calogHandleTakeIf(CalogHandleTableT *table, uint32_t type, bool (*pred)(void *resource, void *userData), void *userData);

#endif
