ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/Semaphore.pm
Revision: 1.160
Committed: Thu Feb 20 18:42:14 2020 UTC (4 years, 3 months ago) by root
Branch: MAIN
CVS Tags: rel-6_56
Changes since 1.159: +1 -1 lines
Log Message:
6.56

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 root 1.110 use Coro;
8 root 1.1
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.152 with any level of parallel users, that is, you can initialize a sempahore
21 root 1.11 that can be C<down>ed more than once until it blocks. There is no owner
22 root 1.127 associated with semaphores, so one thread can C<down> it while another can
23     C<up> it (or vice versa), C<up> can be called before C<down> and so on:
24     the semaphore is really just an integer counter that optionally blocks
25     when it is 0.
26 root 1.11
27     Counting semaphores are typically used to coordinate access to
28     resources, with the semaphore count initialized to the number of free
29 root 1.95 resources. Threads then increment the count when resources are added
30 root 1.11 and decrement the count when resources are removed.
31    
32 root 1.127 You don't have to load C<Coro::Semaphore> manually, it will be loaded
33     automatically when you C<use Coro> and call the C<new> constructor.
34 root 1.109
35 root 1.1 =over 4
36    
37     =cut
38    
39     package Coro::Semaphore;
40    
41 root 1.102 use common::sense;
42 root 1.20
43 root 1.5 use Coro ();
44 root 1.1
45 root 1.160 our $VERSION = 6.56;
46 root 1.1
47 root 1.152 =item new [initial count]
48 root 1.3
49     Creates a new sempahore object with the given initial lock count. The
50 root 1.11 default lock count is 1, which means it is unlocked by default. Zero (or
51     negative values) are also allowed, in which case the semaphore is locked
52     by default.
53 root 1.3
54 root 1.55 =item $sem->count
55    
56 root 1.133 Returns the current semaphore count. The semaphore can be down'ed without
57     blocking when the count is strictly higher than C<0>.
58 root 1.55
59 root 1.56 =item $sem->adjust ($diff)
60    
61     Atomically adds the amount given to the current semaphore count. If the
62     count becomes positive, wakes up any waiters. Does not block if the count
63     becomes negative, however.
64    
65 root 1.3 =item $sem->down
66    
67     Decrement the counter, therefore "locking" the semaphore. This method
68 root 1.133 waits until the semaphore is available if the counter is zero or less.
69 root 1.3
70 root 1.81 =item $sem->wait
71    
72     Similar to C<down>, but does not actually decrement the counter. Instead,
73     when this function returns, a following call to C<down> or C<try> is
74 root 1.95 guaranteed to succeed without blocking, until the next thread switch
75 root 1.81 (C<cede> etc.).
76    
77     Note that using C<wait> is much less efficient than using C<down>, so try
78     to prefer C<down> whenever possible.
79    
80 root 1.82 =item $sem->wait ($callback)
81    
82     If you pass a callback argument to C<wait>, it will not wait, but
83     immediately return. The callback will be called as soon as the semaphore
84     becomes available (which might be instantly), and gets passed the
85     semaphore as first argument.
86    
87     The callback might C<down> the semaphore exactly once, might wake up other
88 root 1.95 threads, but is I<NOT> allowed to block (switch to other threads).
89 root 1.82
90 root 1.3 =cut
91    
92 root 1.80 #=item $status = $sem->timed_down ($timeout)
93     #
94     #Like C<down>, but returns false if semaphore couldn't be acquired within
95     #$timeout seconds, otherwise true.
96    
97     #sub timed_down {
98     # require Coro::Timer;
99     # my $timeout = Coro::Timer::timeout ($_[1]);
100     #
101     # while ($_[0][0] <= 0) {
102     # push @{$_[0][1]}, $Coro::current;
103     # &Coro::schedule;
104     # if ($timeout) {
105     # # ugly as hell. slow, too, btw!
106     # for (0..$#{$_[0][1]}) {
107     # if ($_[0][1][$_] == $Coro::current) {
108     # splice @{$_[0][1]}, $_, 1;
109     # return;
110     # }
111     # }
112     # die;
113     # }
114     # }
115     #
116     # --$_[0][0];
117     # return 1;
118     #}
119 root 1.1
120 root 1.3 =item $sem->up
121    
122     Unlock the semaphore again.
123    
124     =item $sem->try
125    
126     Try to C<down> the semaphore. Returns true when this was possible,
127     otherwise return false and leave the semaphore unchanged.
128    
129 root 1.15 =item $sem->waiters
130    
131 root 1.95 In scalar context, returns the number of threads waiting for this
132 root 1.128 semaphore. Might accidentally cause WW3 if called in other contexts, so
133     don't use these.
134 root 1.15
135 root 1.12 =item $guard = $sem->guard
136    
137     This method calls C<down> and then creates a guard object. When the guard
138     object is destroyed it automatically calls C<up>.
139    
140     =cut
141    
142     sub guard {
143 root 1.16 &down;
144 root 1.90 bless [$_[0]], Coro::Semaphore::guard::
145 root 1.25 }
146    
147 root 1.80 #=item $guard = $sem->timed_guard ($timeout)
148     #
149     #Like C<guard>, but returns undef if semaphore couldn't be acquired within
150     #$timeout seconds, otherwise the guard object.
151    
152     #sub timed_guard {
153     # &timed_down
154     # ? bless \\$_[0], Coro::Semaphore::guard::
155     # : ();
156     #}
157 root 1.12
158 root 1.25 sub Coro::Semaphore::guard::DESTROY {
159 root 1.90 &up($_[0][0]);
160 root 1.1 }
161    
162     =back
163    
164 root 1.141 =head1 AUTHOR/SUPPORT/CONTACT
165 root 1.1
166 root 1.141 Marc A. Lehmann <schmorp@schmorp.de>
167     http://software.schmorp.de/pkg/Coro.html
168 root 1.1
169     =cut
170    
171 root 1.51 1
172