Data-Pool-Shared

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

        my $n  = $pool->eventfd_consume;   # drain counter

STATS
    stats() returns a hashref with diagnostic counters. All values are
    approximate under concurrency.

    "capacity" — total slot count (immutable)
    "elem_size" — bytes per slot (immutable)
    "used" — currently allocated slot count
    "available" — currently free slot count ("capacity - used")
    "waiters" — processes currently blocked on "alloc"
    "mmap_size" — total mmap region size in bytes
    "allocs" — cumulative successful allocations
    "frees" — cumulative frees (including stale recovery)
    "waits" — "alloc" calls that entered the retry loop
    "timeouts" — "alloc" calls that timed out
    "recoveries" — slots freed by "recover_stale"

SECURITY
    The shared memory region (mmap) is writable by all processes that open
    it. A malicious process with write access to the backing file or memfd

lib/Data/Pool/Shared.pm  view on Meta::CPAN

=over

=item C<capacity> — total slot count (immutable)

=item C<elem_size> — bytes per slot (immutable)

=item C<used> — currently allocated slot count

=item C<available> — currently free slot count (C<capacity - used>)

=item C<waiters> — processes currently blocked on C<alloc>

=item C<mmap_size> — total mmap region size in bytes

=item C<allocs> — cumulative successful allocations

=item C<frees> — cumulative frees (including stale recovery)

=item C<waits> — C<alloc> calls that entered the retry loop

=item C<timeouts> — C<alloc> calls that timed out

pool.h  view on Meta::CPAN

    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

t/02-multiprocess.t  view on Meta::CPAN

$pid = fork;
die "fork: $!" unless defined $pid;
if ($pid == 0) {
    my $c = Data::Pool::Shared::I64->new($path, 100);
    select(undef, undef, undef, 0.1);  # sleep 100ms
    $c->free($fill[0]);  # free one slot
    _exit(0);
}

# Parent blocks on alloc, should wake when child frees
my $blocked = $pool->alloc(2.0);
ok defined $blocked, 'blocking alloc succeeded after child freed';
waitpid($pid, 0);

$pool->reset;

# --- Timeout ---

for (1..100) { $pool->alloc }
my $t0 = time;
my $to = $pool->alloc(0.2);
ok !defined $to, 'alloc timed out';

xt/atomic_alignment.t  view on Meta::CPAN

use strict;
use warnings;
use Test::More;

# Alignment of atomic fields in the header. __atomic_* on
# non-naturally-aligned addresses falls back to locked paths (or
# crashes on some architectures). Verify the header layout keeps
# atomic fields at natural alignment.

use Data::Pool::Shared;

my $p = Data::Pool::Shared::I64->new_memfd("align", 16);

# PoolHeader layout, as documented in pool.h:
#   magic(u32, off 0) — non-atomic after init
#   version(u32, off 4) — non-atomic after init



( run in 1.605 second using v1.01-cache-2.11-cpan-e1769b4cff6 )