--- Coro/Coro/Semaphore.pm 2001/07/03 03:48:36 1.1 +++ Coro/Coro/Semaphore.pm 2001/07/25 19:28:00 1.11 @@ -6,7 +6,7 @@ use Coro::Semaphore; - $sig = new Coro::Semaphore [init]; + $sig = new Coro::Semaphore [initial value]; $sig->down; # wait for signal @@ -16,36 +16,76 @@ =head1 DESCRIPTION +This module implements counted semaphores. You can initialize a mutex +with any level of parallel users, that is, you can intialize a sempahore +that can be Ced more than once until it blocks. There is no owner +associated with semaphores, so one coroutine can C it while another +can C it. + +Counting semaphores are typically used to coordinate access to +resources, with the semaphore count initialized to the number of free +resources. Coroutines then increment the count when resources are added +and decrement the count when resources are removed. + =over 4 =cut package Coro::Semaphore; -use Coro::Process (); +use Coro (); + +$VERSION = 0.12; + +=item new [inital count, default one] -$VERSION = 0.01; +Creates a new sempahore object with the given initial lock count. The +default lock count is 1, which means it is unlocked by default. Zero (or +negative values) are also allowed, in which case the semaphore is locked +by default. + +=cut sub new { - bless [$_[1]], $_[0]; + bless [defined $_[1] ? $_[1] : 1], $_[0]; } +=item $sem->down + +Decrement the counter, therefore "locking" the semaphore. This method +waits until the semaphore is available if the counter is zero. + +=cut + sub down { my $self = shift; while ($self->[0] <= 0) { push @{$self->[1]}, $Coro::current; - Coro::Process::schedule; + Coro::schedule; } --$self->[0]; } +=item $sem->up + +Unlock the semaphore again. + +=cut + sub up { my $self = shift; - if (++@{$self->[1]} == 0) { + if (++$self->[0] > 0) { (shift @{$self->[1]})->ready if @{$self->[1]}; } } +=item $sem->try + +Try to C the semaphore. Returns true when this was possible, +otherwise return false and leave the semaphore unchanged. + +=cut + sub try { my $self = shift; if ($self->[0] > 0) {