NAME
Data::Deque::Shared - Shared-memory double-ended queue for Linux
SYNOPSIS
use Data::Deque::Shared;
my $dq = Data::Deque::Shared::Int->new(undef, 100);
$dq->push_back(1);
$dq->push_back(2);
$dq->push_front(0);
say $dq->pop_front; # 0
say $dq->pop_back; # 2
# String variant (fixed max_len per entry)
my $sq = Data::Deque::Shared::Str->new(undef, 100, 64);
$sq->push_back("hello");
say $sq->pop_front; # hello
# blocking with timeout
$dq->push_back_wait(42, 5.0);
my $v = $dq->pop_front_wait(5.0);
# file-backed / memfd
$dq = Data::Deque::Shared::Int->new('/tmp/dq.shm', 100);
$dq = Data::Deque::Shared::Int->new_memfd("my_dq", 100);
my $fd = $dq->memfd;
$dq = Data::Deque::Shared::Int->new_from_fd($fd);
DESCRIPTION
Double-ended queue (deque) in shared memory. Ring buffer with CAS-based push/pop at both ends. Futex blocking when empty or full.
Linux-only. Requires 64-bit Perl. Capacity must be <= 2^31.
Used only as a FIFO (push_back + pop_front), it's effectively a fixed-slot lock-free string queue: 1.3x-4.7x faster than Data::Queue::Shared::Str under multi-producer contention, at the cost of per-slot fixed memory (capacity × max_len).
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 empty → writing → filled, and a popper transitions it through filled → reading → empty with the generation bumped on completion. A consumer that claims position n via the head/tail CAS therefore always observes the publication transition of the corresponding push before reading the value.
drain is safe under concurrent push/pop, but it will spin-wait on any slot whose pusher is mid-publish; if that pusher has crashed between winning its position CAS and publishing the slot value, drain will block indefinitely on that slot. Use drain for orderly draining, not as a crash-recovery primitive.
Compatibility
File format bumped to v2 in this release (per-slot control array added for MPMC safety). Opening a v1 file (magic DEQ1) created by Data::Deque::Shared <= 0.02 will croak on header validation. Re-create the deque with the new version; anonymous and memfd-backed usage is unaffected.
METHODS
Push / Pop
$dq->push_back($val); $dq->push_front($val);
$dq->push_back_wait($val, $t); $dq->push_front_wait($val, $t);
my $v = $dq->pop_front; my $v = $dq->pop_back;
my $v = $dq->pop_front_wait($t); my $v = $dq->pop_back_wait($t);
Status
$dq->size; $dq->capacity; $dq->is_empty; $dq->is_full;
$dq->clear; # NOT concurrency-safe
my $n = $dq->drain; # concurrency-safe, returns count drained
$dq->stats; # {size, capacity, pushes, pops, waits, timeouts, mmap_size}
Common
$dq->path; $dq->memfd; $dq->sync; $dq->unlink;
eventfd
$dq->eventfd; $dq->notify; $dq->eventfd_consume;
$dq->eventfd_set($fd); $dq->fileno;
STATS
stats() returns: size, capacity, pushes, pops, waits, timeouts, mmap_size.
SECURITY
The mmap region is writable by all processes that open it. Do not share backing files with untrusted processes.
BENCHMARKS
Single-process (1M ops, x86_64 Linux, Perl 5.40):
push_back + pop_front (FIFO) 6.5M/s
push_back + pop_back (LIFO) 6.3M/s
push_front + pop_front (LIFO) 6.4M/s
push_front + pop_back (FIFO) 6.5M/s
Multi-process (8 workers, 200K ops each):
cap=16 5.7M/s aggregate
cap=64 5.9M/s aggregate
cap=256 5.8M/s aggregate
SEE ALSO
Data::Stack::Shared - LIFO stack
Data::Queue::Shared - FIFO queue
Data::ReqRep::Shared - request-reply
Data::Pool::Shared - fixed-size object pool
Data::Log::Shared - append-only log (WAL)
Data::Buffer::Shared - typed shared array
Data::Sync::Shared - synchronization primitives
Data::HashMap::Shared - concurrent hash table
Data::PubSub::Shared - publish-subscribe ring
Data::Heap::Shared - priority queue
Data::Graph::Shared - directed weighted graph
Data::BitSet::Shared - shared bitset (lock-free per-bit ops)
Data::RingBuffer::Shared - fixed-size overwriting ring buffer
AUTHOR
vividsnow
LICENSE
This is free software; you can redistribute it and/or modify it under the same terms as Perl itself.