Acme-Parataxis

 view release on metacpan or  search on metacpan

lib/Acme/Parataxis/Sync/Mutex.pod  view on Meta::CPAN

        # acquired lock without parking
        $lock->unlock;
    } else {
        # held by another fiber
    }

Attempts to acquire the lock without parking:

=over

=item * If free: claims ownership and returns true.

=item * If held by another fiber: returns false immediately.

=item * If already held by the calling fiber: croaks with the re-entrancy error.

=back

=head2 C<unlock( )>

    $lock->unlock;

Releases the lock and hands ownership to the next live fiber queued in C<waiters>.

=over

=item * Croaks if the mutex is not currently locked.

=item * Croaks if called from a fiber other than the current owner.

=back

Returns true.

=head2 C<guard( )>

    {
        my $guard = $lock->guard;
        # critical section
    }

Acquires the lock via C<lock()> and returns an opaque L<Acme::Parataxis::Sync::Mutex::Guard> object. When the guard is
destroyed (via normal block exit, C<return>, or an exception), it invokes C<unlock()> automatically.

=head2 C<owner( )>

Returns the numeric fiber ID of the fiber currently holding the lock, or C<undef> if the lock is free.

=head2 C<waiters( )>

Returns the number of fibers currently parked waiting to acquire the lock. Note that when C<unlock()> is called,
ownership is transferred and the waiter is dequeued immediately, so C<waiters> decrements before the waking fiber
actually resumes execution.

=head1 Recipes

=head2 Scoped critical sections

Always prefer guards over manual C<lock()>/C<unlock()> pairs to ensure releases occur even during exceptions:

    sub update_shared_state ($mutex, $data) {
        my $guard = $mutex->guard;
        validate($data);    # if this dies, $guard->DESTROY safely unlocks!
        apply($data);
    }

=head2 Non-blocking skip

Use C<try_lock()> to perform work only when no contention exists:

    fiber {
        if ( $lock->try_lock ) {
            my $guard = Acme::Parataxis::Sync::Mutex::Guard->new( mutex => $lock );
            do_background_sync();
        } else {
            say "Lock busy; skipping this sync cycle";
        }
    };

=head1 Behavior Notes

=over

=item * Locks outlive fibers

If a fiber acquires a lock and terminates without unlocking (and without a guard), the mutex remains locked
permanently. Any subsequent fiber attempting to acquire the lock will park forever, eventually triggering a deadlock.
Always capture guards in a lexical variable within the acquiring fiber.

=item * Guards cannot cross fibers

Guards verify ownership upon destruction. If you create a guard in fiber A and pass the guard object to fiber B, fiber
B's destructor will croak with C<Mutex release from a fiber that is not the owner>, stranding the lock.

=item * Atomic hand-off safety

If a release occurs and ownership is transferred to a parked fiber at the exact instant that fiber's C<with_timeout>
deadline fires, the cleanup logic detects the collision, resets the owner, and passes the lock on to the next live
waiter in the queue.

=back

=head1 SEE ALSO

L<Acme::Parataxis::Sync>, L<Acme::Parataxis::Sync::RwLock>, L<Acme::Parataxis::Semaphore>

=head1 AUTHOR

Sanko Robinson L<https://github.com/sanko>

=head1 LICENSE

Copyright (C) Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms found in the Artistic License
2.

=cut



( run in 0.965 second using v1.01-cache-2.11-cpan-145b269f2f3 )