Data-Sync-Shared

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

        $cv->lock;
        $cv->try_lock;       # non-blocking
        $cv->wait;           # atomically unlock + wait + re-lock
        $cv->wait(2.0);      # with timeout
        $cv->signal;         # wake one waiter
        $cv->broadcast;      # wake all waiters
        $cv->wait_while(sub { !$ready }, 5.0);  # predicate loop
        $cv->unlock;

        # Once — one-time initialization gate
        my $once = Data::Sync::Shared::Once->new('/tmp/once.shm');
        if ($once->enter) {          # or enter($timeout)
            do_init();
            $once->done;
        }

        # All primitives support anonymous (fork-inherited) mode:
        my $sem = Data::Sync::Shared::Semaphore->new(undef, 4);

        # And memfd mode (fd-passable):
        my $sem = Data::Sync::Shared::Semaphore->new_memfd("my_sem", 4);
        my $fd = $sem->memfd;

DESCRIPTION
    Data::Sync::Shared provides five cross-process synchronization
    primitives stored in file-backed shared memory (mmap(MAP_SHARED)), using
    Linux futex for efficient blocking.

    Linux-only. Requires 64-bit Perl.

  Primitives
    Data::Sync::Shared::Semaphore - bounded counter
        CAS-based counting semaphore. "acquire" decrements (blocks at 0),
        "release" increments (capped at max). Useful for cross-process
        resource limiting (connection pools, worker slots).

    Data::Sync::Shared::Barrier - rendezvous point
        N processes call "wait"; all block until the last one arrives, then
        all proceed. Returns true for one "leader" process. Generation
        counter tracks how many times the barrier has tripped.

    Data::Sync::Shared::RWLock - reader-writer lock
        Multiple concurrent readers or one exclusive writer. Readers use
        "rdlock"/"rdunlock", writers use "wrlock"/"wrunlock". Non-blocking
        "try_rdlock"/"try_wrlock" variants available.

    Data::Sync::Shared::Condvar - condition variable
        Includes a built-in mutex. "lock"/"unlock" protect the predicate.
        "wait" atomically releases the mutex and sleeps; on wakeup it
        re-acquires the mutex. "signal" wakes one waiter, "broadcast" wakes
        all.

    Data::Sync::Shared::Once - one-time init gate
        "enter" returns true for exactly one process (the initializer); all
        others block until "done" is called. If the initializer dies,
        waiters detect the stale PID and a new initializer is elected.

  Features
    *   File-backed mmap for cross-process sharing

    *   Futex-based blocking (no busy-spin, no pthread)

    *   PID-based stale lock recovery (dead process detection)

    *   Anonymous and memfd modes

    *   Timeouts on all blocking operations

    *   eventfd integration for event-loop wakeup

  Crash Safety
    All primitives encode the holder's PID in the lock word. If a process
    dies while holding a lock, other processes detect the stale lock within
    2 seconds via "kill(pid, 0)" and automatically recover.

  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 (lock words, counters, parameters) and cause
    other processes to deadlock, spin, or behave incorrectly. Do not share
    backing files with untrusted processes. Use anonymous mode or memfd with
    restricted fd passing for isolation.

  Guard Objects
    All locking primitives provide scope-based guards that auto-release on
    scope exit (including exceptions):

        {
            my $g = $rw->rdlock_guard;
            # ... read operations ...
        }  # rdunlock called automatically

        {
            my $g = $sem->acquire_guard(3);  # acquire 3 permits
            # ... use resource ...
        }  # release(3) called automatically

        {
            my $g = $cv->lock_guard;
            $cv->wait_while(sub { !$ready }, 5.0);
        }  # unlock called automatically

PRIMITIVES
  Data::Sync::Shared::Semaphore
   Constructors
        my $sem = Data::Sync::Shared::Semaphore->new($path, $max);
        my $sem = Data::Sync::Shared::Semaphore->new($path, $max, $initial);
        my $sem = Data::Sync::Shared::Semaphore->new(undef, $max);
        my $sem = Data::Sync::Shared::Semaphore->new_memfd($name, $max);
        my $sem = Data::Sync::Shared::Semaphore->new_memfd($name, $max, $initial);
        my $sem = Data::Sync::Shared::Semaphore->new_from_fd($fd);

    $max is the maximum permit count. $initial defaults to $max (fully
    available); set to 0 to start with no available permits.

   Operations
        my $ok  = $sem->acquire;              # block until available (infinite)
        my $ok  = $sem->acquire($timeout);    # block with timeout (seconds)
        my $ok  = $sem->try_acquire;          # non-blocking, false if unavailable
        my $ok  = $sem->acquire_n($n);        # acquire N permits atomically
        my $ok  = $sem->acquire_n($n, $timeout);



( run in 1.912 second using v1.01-cache-2.11-cpan-39bf76dae61 )