ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Semaphore.pm
Revision: 1.98
Committed: Mon Jul 20 23:46:28 2009 UTC (14 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-5_16
Changes since 1.97: +1 -1 lines
Log Message:
5.16

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3 root 1.84 Coro::Semaphore - counting semaphores
4 root 1.1
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 root 1.95 associated with semaphores, so one thread can C<down> it while another
23 root 1.11 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 root 1.95 resources. Threads then increment the count when resources are added
28 root 1.11 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.98 $VERSION = 5.16;
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 root 1.95 guaranteed to succeed without blocking, until the next thread switch
69 root 1.81 (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 root 1.95 threads, but is I<NOT> allowed to block (switch to other threads).
83 root 1.82
84 root 1.3 =cut
85    
86 root 1.80 #=item $status = $sem->timed_down ($timeout)
87     #
88     #Like C<down>, but returns false if semaphore couldn't be acquired within
89     #$timeout seconds, otherwise true.
90    
91     #sub timed_down {
92     # require Coro::Timer;
93     # my $timeout = Coro::Timer::timeout ($_[1]);
94     #
95     # while ($_[0][0] <= 0) {
96     # push @{$_[0][1]}, $Coro::current;
97     # &Coro::schedule;
98     # if ($timeout) {
99     # # ugly as hell. slow, too, btw!
100     # for (0..$#{$_[0][1]}) {
101     # if ($_[0][1][$_] == $Coro::current) {
102     # splice @{$_[0][1]}, $_, 1;
103     # return;
104     # }
105     # }
106     # die;
107     # }
108     # }
109     #
110     # --$_[0][0];
111     # return 1;
112     #}
113 root 1.1
114 root 1.3 =item $sem->up
115    
116     Unlock the semaphore again.
117    
118     =item $sem->try
119    
120     Try to C<down> the semaphore. Returns true when this was possible,
121     otherwise return false and leave the semaphore unchanged.
122    
123 root 1.15 =item $sem->waiters
124    
125 root 1.95 In scalar context, returns the number of threads waiting for this
126 root 1.15 semaphore.
127    
128 root 1.12 =item $guard = $sem->guard
129    
130     This method calls C<down> and then creates a guard object. When the guard
131     object is destroyed it automatically calls C<up>.
132    
133     =cut
134    
135     sub guard {
136 root 1.16 &down;
137 root 1.90 bless [$_[0]], Coro::Semaphore::guard::
138 root 1.25 }
139    
140 root 1.80 #=item $guard = $sem->timed_guard ($timeout)
141     #
142     #Like C<guard>, but returns undef if semaphore couldn't be acquired within
143     #$timeout seconds, otherwise the guard object.
144    
145     #sub timed_guard {
146     # &timed_down
147     # ? bless \\$_[0], Coro::Semaphore::guard::
148     # : ();
149     #}
150 root 1.12
151 root 1.25 sub Coro::Semaphore::guard::DESTROY {
152 root 1.90 &up($_[0][0]);
153 root 1.1 }
154    
155     =back
156    
157     =head1 AUTHOR
158    
159 root 1.44 Marc Lehmann <schmorp@schmorp.de>
160 root 1.42 http://home.schmorp.de/
161 root 1.1
162     =cut
163    
164 root 1.51 1
165