Data-Stack-Shared
view release on metacpan or search on metacpan
lib/Data/Stack/Shared.pm view on Meta::CPAN
1;
__END__
=encoding utf-8
=head1 NAME
Data::Stack::Shared - Shared-memory LIFO stack for Linux
=head1 SYNOPSIS
use Data::Stack::Shared;
my $stk = Data::Stack::Shared::Int->new(undef, 100);
$stk->push(42);
$stk->push(99);
say $stk->pop; # 99 (LIFO)
say $stk->peek; # 42
say $stk->size; # 1
# blocking with timeout
$stk->push_wait(42, 5.0);
my $val = $stk->pop_wait(5.0);
# string variant
my $ss = Data::Stack::Shared::Str->new(undef, 50, 256);
$ss->push("hello");
say $ss->pop;
# anonymous / memfd / file-backed
my $s = Data::Stack::Shared::Int->new('/tmp/stk.shm', 100);
$s = Data::Stack::Shared::Int->new(undef, 100);
$s = Data::Stack::Shared::Int->new_memfd("my_stk", 100);
my $fd = $s->memfd;
$s = Data::Stack::Shared::Int->new_from_fd($fd);
=head1 DESCRIPTION
LIFO stack in shared memory. CAS-based position handout on an atomic
top index, paired with a per-slot publication state machine (see
L</Concurrency>). Futex blocking when empty or full.
B<Linux-only>. Requires 64-bit Perl.
=head2 Concurrency
Push and pop are safe under multi-producer / multi-consumer workloads.
Each slot carries a 64-bit control word (state + generation) that acts
as a publication gate: a pusher atomically transitions the slot through
C<empty â writing â filled>, and a popper transitions it through
C<filled â reading â empty> with the generation bumped on completion.
A consumer that claims position C<t-1> via the C<top> CAS therefore
always observes the matching pusher's transition to C<filled> before
reading the value. C<peek> is a seqlock-style read: it retries if the
slot transitions during the read and returns false if the top changes
concurrently beyond the retry budget.
C<drain> is safe under concurrent C<push>/C<pop>, but it spin-waits on
slots whose pusher is mid-publish; a pusher crash between its position
CAS and the publish leaves drain blocked on that slot. Use C<drain> for
orderly draining, not as a crash-recovery primitive.
=head2 Compatibility
File format bumped to v2 in this release (per-slot control array added
for MPMC safety). Opening a v1 file (magic C<STK1>) created by
Data::Stack::Shared C<E<lt>= 0.02> will croak on header validation.
Re-create the stack with the new version; anonymous and memfd-backed
usage is unaffected.
=head2 Variants
=over
=item C<Data::Stack::Shared::Int> - int64_t values
=item C<Data::Stack::Shared::Str> - fixed-length strings
=back
=head1 METHODS
=head2 Push / Pop
my $ok = $stk->push($val); # non-blocking
$ok = $stk->push_wait($val); # blocking (infinite)
$ok = $stk->push_wait($val, $timeout); # blocking with timeout
my $val = $stk->pop; # non-blocking, undef if empty
$val = $stk->pop_wait; # blocking (infinite)
$val = $stk->pop_wait($timeout); # blocking with timeout
$val = $stk->peek; # read top without removing
=head2 Status
my $n = $stk->size;
my $cap = $stk->capacity;
my $ok = $stk->is_empty;
my $ok = $stk->is_full;
$stk->clear; # empty (NOT concurrency-safe)
my $n = $stk->drain; # empty (concurrency-safe, returns count)
=head2 Common
my $p = $stk->path;
my $fd = $stk->memfd;
$stk->sync;
$stk->unlink;
my $s = $stk->stats;
=head2 eventfd
my $fd = $stk->eventfd;
$stk->eventfd_set($fd);
my $fd = $stk->fileno;
$stk->notify;
my $n = $stk->eventfd_consume;
=head1 STATS
( run in 0.525 second using v1.01-cache-2.11-cpan-39bf76dae61 )