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 )