Data-Pool-Shared
view release on metacpan or search on metacpan
* F64 â double slots
* I32 â int32_t slots with atomic CAS/add
* Str â fixed-length string slots (4-byte length prefix + data)
*/
#ifndef POOL_H
#define POOL_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <limits.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/syscall.h>
#include <linux/futex.h>
#include <sys/eventfd.h>
/* ================================================================
* Constants
* ================================================================ */
#define POOL_MAGIC 0x504F4C31U /* "POL1" */
#define POOL_VERSION 1
#define POOL_ERR_BUFLEN 256
#define POOL_VAR_RAW 0
#define POOL_VAR_I64 1
#define POOL_VAR_F64 2
#define POOL_VAR_I32 3
#define POOL_VAR_STR 4
#define POOL_ALIGN8(x) (((x) + 7) & ~(uint64_t)7)
/* ================================================================
* Header (128 bytes = 2 cache lines)
* ================================================================ */
typedef struct {
/* ---- Cache line 0 (0-63): immutable after create ---- */
uint32_t magic; /* 0 */
uint32_t version; /* 4 */
uint32_t elem_size; /* 8 */
uint32_t variant_id; /* 12 */
uint64_t capacity; /* 16: number of slots */
uint64_t total_size; /* 24: total mmap size */
uint64_t data_off; /* 32: offset to slot data */
uint64_t bitmap_off; /* 40: offset to allocation bitmap */
uint64_t owners_off; /* 48: offset to per-slot owner PIDs */
uint8_t _pad0[8]; /* 56-63 */
/* ---- Cache line 1 (64-127): mutable state ---- */
uint32_t used; /* 64: allocated count (futex word) */
uint32_t waiters; /* 68: blocked on alloc */
uint8_t _pad1[8]; /* 72-79 */
uint64_t stat_allocs; /* 80 */
uint64_t stat_frees; /* 88 */
uint64_t stat_waits; /* 96 */
uint64_t stat_timeouts; /* 104 */
uint64_t stat_recoveries;/* 112 */
uint8_t _pad2[8]; /* 120-127 */
} PoolHeader;
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(PoolHeader) == 128, "PoolHeader must be 128 bytes");
#endif
/* ================================================================
* Process-local handle
* ================================================================ */
typedef struct {
PoolHeader *hdr;
uint64_t *bitmap;
uint32_t *owners;
uint8_t *data;
size_t mmap_size;
uint32_t bitmap_words;
char *path;
int notify_fd;
int backing_fd;
uint32_t scan_hint;
} PoolHandle;
/* ================================================================
* Utility
* ================================================================ */
static inline int pool_pid_alive(uint32_t pid) {
if (pid == 0) return 1;
return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH);
}
static inline void pool_make_deadline(double timeout, struct timespec *deadline) {
clock_gettime(CLOCK_MONOTONIC, deadline);
deadline->tv_sec += (time_t)timeout;
deadline->tv_nsec += (long)((timeout - (double)(time_t)timeout) * 1e9);
if (deadline->tv_nsec >= 1000000000L) {
deadline->tv_sec++;
deadline->tv_nsec -= 1000000000L;
}
}
static inline int pool_remaining_time(const struct timespec *deadline,
struct timespec *remaining) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
remaining->tv_sec = deadline->tv_sec - now.tv_sec;
remaining->tv_nsec = deadline->tv_nsec - now.tv_nsec;
if (remaining->tv_nsec < 0) {
remaining->tv_sec--;
remaining->tv_nsec += 1000000000L;
}
return remaining->tv_sec >= 0;
( run in 0.557 second using v1.01-cache-2.11-cpan-e1769b4cff6 )