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
    Backing files are created securely: the path is opened with
    O_CREAT|O_EXCL|O_NOFOLLOW (a pre-existing symlink at the path is
    rejected, and an existing regular file is attached rather than
    truncated) and the new file is created mode 0600 (owner-only) by
    default, so a segment is not world-writable unless you opt in. To share
    a file with a peer group, pass an explicit octal mode as the last
    argument to new():

        my $sem = Data::Sync::Shared::Semaphore->new($path, $max, $initial, 0660);
        my $rw  = Data::Sync::Shared::RWLock->new($path, 0660);

    The mode is still subject to the caller's umask, exactly like open().
    Offsets read back from an attached segment are bounds-checked before
    use, so a poisoned reader-slot offset cannot steer a pointer outside the
    mapping.

  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);



( run in 1.259 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )