Data-Queue-Shared
view release on metacpan or search on metacpan
# String queue (mutex-protected, circular arena)
my $sq = Data::Queue::Shared::Str->new('/tmp/strq.shm', 1024);
$sq->push("hello world");
my $msg = $sq->pop;
# With explicit arena size (default: capacity * 256)
my $sq = Data::Queue::Shared::Str->new('/tmp/strq.shm', 1024, 1048576);
# Multiprocess
if (fork() == 0) {
my $child = Data::Queue::Shared::Int->new('/tmp/myq.shm', 1024);
$child->push(99);
exit;
}
wait;
print $q->pop; # 99
DESCRIPTION
Data::Queue::Shared provides bounded MPMC (multi-producer,
multi-consumer) queues stored in file-backed shared memory
(mmap(MAP_SHARED)), enabling efficient multiprocess data sharing on
Linux.
Linux-only. Requires 64-bit Perl.
Variants
Data::Queue::Shared::Int - int64 values, lock-free (16 bytes/slot)
Uses the Vyukov bounded MPMC algorithm. Push and pop are lock-free
(CAS-based). Optimal for integer job IDs, counters, indices.
Data::Queue::Shared::Int32 - int32 values, lock-free (8 bytes/slot)
Data::Queue::Shared::Int16 - int16 values, lock-free (8 bytes/slot)
Compact variants with 32-bit Vyukov sequence numbers. Half the
memory footprint per slot = double the cache density. Same lock-free
algorithm. Same API as Int. Values outside the type range are
silently truncated (standard C cast semantics).
Data::Queue::Shared::Str - byte string values, mutex-protected
Uses a futex-based mutex with a circular arena for variable-length
string storage. Supports UTF-8 flag preservation. Optimal for
messages, serialized data, filenames.
Memory-efficient for mixed lengths (short + occasional long strings
share the arena), but throughput degrades under heavy multi-producer
contention because all pushes serialize on one mutex.
For fixed-length FIFO workloads that need maximum throughput: use
Data::Deque::Shared::Str with only "push_back" / "pop_front". It's
fixed-slot-per-entry (memory use = capacity à max_len), uses a
per-slot publication state machine instead of a shared mutex, and
measures 1.3x-4.7x faster than Queue::Str depending on contention (1
vs 8 writers, 32-byte payloads, single box). Use that if your
messages share an upper bound and you want lock-free-style scaling.
Features
* File-backed mmap for cross-process sharing
* Lock-free MPMC for integer queues (Vyukov algorithm)
* Futex-based blocking wait with timeout (no busy-spin)
* PID-based stale lock recovery (dead process detection)
* Batch push/pop operations
* Circular arena for zero-fragmentation string storage
* Optional keyword API via XS::Parse::Keyword (zero method-dispatch
overhead)
Constructor
# Int queue
my $q = Data::Queue::Shared::Int->new($path, $capacity);
# Str queue
my $q = Data::Queue::Shared::Str->new($path, $capacity);
my $q = Data::Queue::Shared::Str->new($path, $capacity, $arena_bytes);
Creates or opens a shared queue backed by file $path. $capacity is
rounded up to the next power of 2. When opening an existing file,
parameters are read from the stored header. Multiple processes can open
the same file simultaneously.
Pass "undef" for $path to create an anonymous queue using
"MAP_SHARED|MAP_ANONYMOUS". Anonymous queues are shared with child
processes via fork() but cannot be opened by unrelated processes.
memfd Constructor
my $q = Data::Queue::Shared::Int->new_memfd($name, $capacity);
my $q = Data::Queue::Shared::Str->new_memfd($name, $capacity);
my $q = Data::Queue::Shared::Str->new_memfd($name, $cap, $arena);
Creates a queue backed by memfd_create(2). No filesystem path â the
backing memory is identified by a file descriptor. Use memfd() to
retrieve the fd and pass it to other processes via "SCM_RIGHTS" (Unix
domain socket fd passing) or fork() inheritance.
my $q2 = Data::Queue::Shared::Int->new_from_fd($fd);
my $q2 = Data::Queue::Shared::Str->new_from_fd($fd);
Opens a queue from a received memfd. The fd is dup'd internally.
my $fd = $q->memfd; # backing fd (-1 if file-backed/anonymous)
For Str queues, $arena_bytes sets the string storage arena size
(default: "$capacity * 256", minimum 4096, maximum 4GB). Strings are
stored in a circular arena; total stored string bytes cannot exceed the
arena capacity. Individual strings are limited to ~2GB.
API
Core operations
my $ok = $q->push($value); # non-blocking, false if full
my $val = $q->pop; # non-blocking, undef if empty
my $ok = $q->push_wait($value); # blocking, infinite wait
my $ok = $q->push_wait($value, $secs); # blocking with timeout
my $val = $q->pop_wait; # blocking, infinite wait
my $val = $q->pop_wait($secs); # blocking with timeout
my $val = $q->peek; # read front without consuming
"peek" returns the front element without removing it ("undef" if empty).
( run in 0.547 second using v1.01-cache-2.11-cpan-39bf76dae61 )