Data-Pool-Shared
view release on metacpan or search on metacpan
lib/Data/Pool/Shared.pm view on Meta::CPAN
=head2 Status
my $ok = $pool->is_allocated($idx);
my $cap = $pool->capacity;
my $esz = $pool->elem_size;
my $n = $pool->used; # allocated count
my $n = $pool->available; # free count
my $pid = $pool->owner($idx); # PID of allocator
=head2 Recovery
my $n = $pool->recover_stale; # free slots owned by dead PIDs
$pool->reset; # free all slots (exclusive access only)
=head2 Guards
my ($idx, $guard) = $pool->alloc_guard; # auto-free on scope exit
my ($idx, $guard) = $pool->alloc_guard($timeout);
my ($idx, $guard) = $pool->try_alloc_guard; # non-blocking
=head2 Convenience
my $idx = $pool->alloc_set($val); # alloc + set
my $idx = $pool->alloc_set($val, $timeout); # with timeout
my $idx = $pool->try_alloc_set($val); # non-blocking
$pool->each_allocated(sub { my $idx = shift; ... });
=head2 Common Methods
my $p = $pool->path; # backing file (undef if anon)
my $fd = $pool->memfd; # memfd fd (-1 if not memfd)
$pool->sync; # msync to disk
$pool->unlink; # remove backing file
my $s = $pool->stats; # diagnostic hashref
=head3 eventfd Integration
my $fd = $pool->eventfd; # create eventfd
$pool->eventfd_set($fd); # use existing fd
my $fd = $pool->fileno; # current eventfd (-1 if none)
$pool->notify; # signal eventfd
my $n = $pool->eventfd_consume; # drain counter
=head1 STATS
C<stats()> returns a hashref with diagnostic counters. All values are
approximate under concurrency.
=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
=item C<recoveries> â slots freed by C<recover_stale>
=back
=head1 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
can corrupt header fields (bitmap, counters, slot data) and cause other
processes to crash, spin, or return incorrect data. Do not share backing
files with untrusted processes. Use anonymous mode or memfd with
restricted fd passing for isolation.
=head1 PERFORMANCE
=over
=item * Allocation scans a bitmap of C<ceil(capacity/64)> words.
O(capacity/64) worst case, O(1) amortized with scan_hint.
=item * Each allocation is a single CAS on one bitmap word.
Under contention, CAS retries on the same word are ~10ns each.
=item * When pool is full, C<alloc> blocks on a futex (zero CPU).
Woken by a single C<FUTEX_WAKE> syscall on C<free>.
=item * C<free_n> batches N frees into a single C<used> decrement
and a single C<FUTEX_WAKE> syscall â faster than N individual frees.
=item * C<slot_sv> provides zero-copy access to slot data, avoiding
C<memcpy> overhead for large slots.
=item * Typed variants (I64, I32) use atomic load/store/CAS/add
directly on the mmap'd memory â no locking overhead.
=back
=head1 BENCHMARKS
Measured on a single-socket x86_64 Linux system, Perl 5.40.
Single process (1M ops):
I64 alloc + free 3.3M/s
I64 get/set ~10M/s
I64 add/incr ~10M/s
I64 cas 9.8M/s
Str set (48B) ~10M/s
Str get (48B) 7.5M/s
alloc_set + free 1.9M/s
( run in 0.889 second using v1.01-cache-2.11-cpan-e1769b4cff6 )