ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Semaphore.pm
Revision: 1.82
Committed: Wed Nov 19 11:11:10 2008 UTC (15 years, 6 months ago) by root
Branch: MAIN
Changes since 1.81: +13 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     Coro::Semaphore - non-binary semaphores
4    
5     =head1 SYNOPSIS
6    
7     use Coro::Semaphore;
8    
9 root 1.3 $sig = new Coro::Semaphore [initial value];
10 root 1.1
11     $sig->down; # wait for signal
12    
13     # ... some other "thread"
14    
15     $sig->up;
16    
17     =head1 DESCRIPTION
18    
19 root 1.16 This module implements counting semaphores. You can initialize a mutex
20 root 1.11 with any level of parallel users, that is, you can intialize a sempahore
21     that can be C<down>ed more than once until it blocks. There is no owner
22     associated with semaphores, so one coroutine can C<down> it while another
23     can C<up> it.
24    
25     Counting semaphores are typically used to coordinate access to
26     resources, with the semaphore count initialized to the number of free
27     resources. Coroutines then increment the count when resources are added
28     and decrement the count when resources are removed.
29    
30 root 1.1 =over 4
31    
32     =cut
33    
34     package Coro::Semaphore;
35    
36 root 1.61 no warnings;
37 root 1.20
38 root 1.5 use Coro ();
39 root 1.1
40 root 1.79 $VERSION = 5.0;
41 root 1.1
42 root 1.16 =item new [inital count]
43 root 1.3
44     Creates a new sempahore object with the given initial lock count. The
45 root 1.11 default lock count is 1, which means it is unlocked by default. Zero (or
46     negative values) are also allowed, in which case the semaphore is locked
47     by default.
48 root 1.3
49 root 1.55 =item $sem->count
50    
51     Returns the current semaphore count.
52    
53 root 1.56 =item $sem->adjust ($diff)
54    
55     Atomically adds the amount given to the current semaphore count. If the
56     count becomes positive, wakes up any waiters. Does not block if the count
57     becomes negative, however.
58    
59 root 1.3 =item $sem->down
60    
61     Decrement the counter, therefore "locking" the semaphore. This method
62     waits until the semaphore is available if the counter is zero.
63    
64 root 1.81 =item $sem->wait
65    
66     Similar to C<down>, but does not actually decrement the counter. Instead,
67     when this function returns, a following call to C<down> or C<try> is
68     guaranteed to succeed without blocking, until the next coroutine switch
69     (C<cede> etc.).
70    
71     Note that using C<wait> is much less efficient than using C<down>, so try
72     to prefer C<down> whenever possible.
73    
74 root 1.82 =item $sem->wait ($callback)
75    
76     If you pass a callback argument to C<wait>, it will not wait, but
77     immediately return. The callback will be called as soon as the semaphore
78     becomes available (which might be instantly), and gets passed the
79     semaphore as first argument.
80    
81     The callback might C<down> the semaphore exactly once, might wake up other
82     coroutines, but is I<NOT> allowed to block (switch to other coroutines).
83    
84     This is considered a rather experimental interface, and is subject to
85     change.
86    
87 root 1.3 =cut
88    
89 root 1.80 #=item $status = $sem->timed_down ($timeout)
90     #
91     #Like C<down>, but returns false if semaphore couldn't be acquired within
92     #$timeout seconds, otherwise true.
93    
94     #sub timed_down {
95     # require Coro::Timer;
96     # my $timeout = Coro::Timer::timeout ($_[1]);
97     #
98     # while ($_[0][0] <= 0) {
99     # push @{$_[0][1]}, $Coro::current;
100     # &Coro::schedule;
101     # if ($timeout) {
102     # # ugly as hell. slow, too, btw!
103     # for (0..$#{$_[0][1]}) {
104     # if ($_[0][1][$_] == $Coro::current) {
105     # splice @{$_[0][1]}, $_, 1;
106     # return;
107     # }
108     # }
109     # die;
110     # }
111     # }
112     #
113     # --$_[0][0];
114     # return 1;
115     #}
116 root 1.1
117 root 1.3 =item $sem->up
118    
119     Unlock the semaphore again.
120    
121     =item $sem->try
122    
123     Try to C<down> the semaphore. Returns true when this was possible,
124     otherwise return false and leave the semaphore unchanged.
125    
126 root 1.15 =item $sem->waiters
127    
128     In scalar context, returns the number of coroutines waiting for this
129     semaphore.
130    
131 root 1.12 =item $guard = $sem->guard
132    
133     This method calls C<down> and then creates a guard object. When the guard
134     object is destroyed it automatically calls C<up>.
135    
136     =cut
137    
138     sub guard {
139 root 1.16 &down;
140 root 1.13 # double indirection because bless works on the referenced
141     # object, not (only) on the reference itself.
142 root 1.26 bless \\$_[0], Coro::Semaphore::guard::;
143 root 1.25 }
144    
145 root 1.80 #=item $guard = $sem->timed_guard ($timeout)
146     #
147     #Like C<guard>, but returns undef if semaphore couldn't be acquired within
148     #$timeout seconds, otherwise the guard object.
149    
150     #sub timed_guard {
151     # &timed_down
152     # ? bless \\$_[0], Coro::Semaphore::guard::
153     # : ();
154     #}
155 root 1.12
156 root 1.25 sub Coro::Semaphore::guard::DESTROY {
157 root 1.16 &up(${${$_[0]}});
158 root 1.1 }
159    
160     =back
161    
162     =head1 AUTHOR
163    
164 root 1.44 Marc Lehmann <schmorp@schmorp.de>
165 root 1.42 http://home.schmorp.de/
166 root 1.1
167     =cut
168    
169 root 1.51 1
170