ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/SemaphoreSet.pm
Revision: 1.92
Committed: Wed Apr 14 01:56:03 2010 UTC (14 years, 2 months ago) by root
Branch: MAIN
CVS Tags: rel-5_22
Changes since 1.91: +1 -1 lines
Log Message:
5.22

File Contents

# Content
1 =head1 NAME
2
3 Coro::SemaphoreSet - efficient set of counting semaphores
4
5 =head1 SYNOPSIS
6
7 use Coro::SemaphoreSet;
8
9 $sig = new Coro::SemaphoreSet [initial value];
10
11 $sig->down ("semaphoreid"); # wait for signal
12
13 # ... some other "thread"
14
15 $sig->up ("semaphoreid");
16
17 =head1 DESCRIPTION
18
19 This module implements sets of counting semaphores (see
20 L<Coro::Semaphore>). It is nothing more than a hash with normal semaphores
21 as members, but is more efficiently managed.
22
23 This is useful if you want to allow parallel tasks to run in parallel but
24 not on the same problem. Just use a SemaphoreSet and lock on the problem
25 identifier.
26
27 =over 4
28
29 =cut
30
31 package Coro::SemaphoreSet;
32
33 use common::sense;
34
35 our $VERSION = 5.22;
36
37 use Coro::Semaphore ();
38
39 =item new [inital count]
40
41 Creates a new semaphore set with the given initial lock count for each
42 individual semaphore. See L<Coro::Semaphore>.
43
44 =cut
45
46 sub new {
47 bless [defined $_[1] ? $_[1] : 1], $_[0]
48 }
49
50 =item $semset->down ($id)
51
52 Decrement the counter, therefore "locking" the named semaphore. This
53 method waits until the semaphore is available if the counter is zero.
54
55 =cut
56
57 sub down {
58 # Coro::Semaphore::down increases the refcount, which we check in _may_delete
59 Coro::Semaphore::down ($_[0][1]{$_[1]} ||= Coro::Semaphore::_alloc $_[0][0]);
60 }
61
62 #ub timed_down {
63 # require Coro::Timer;
64 # my $timeout = Coro::Timer::timeout ($_[2]);
65 #
66 # while () {
67 # my $sem = ($_[0][1]{$_[1]} ||= [$_[0][0]]);
68 #
69 # if ($sem->[0] > 0) {
70 # --$sem->[0];
71 # return 1;
72 # }
73 #
74 # if ($timeout) {
75 # # ugly as hell.
76 # for (0..$#{$sem->[1]}) {
77 # if ($sem->[1][$_] == $Coro::current) {
78 # splice @{$sem->[1]}, $_, 1;
79 # return 0;
80 # }
81 # }
82 # die;
83 # }
84 #
85 # push @{$sem->[1]}, $Coro::current;
86 # &Coro::schedule;
87 # }
88 #
89
90 =item $semset->up ($id)
91
92 Unlock the semaphore again. If the semaphore reaches the default count for
93 this set and has no waiters, the space allocated for it will be freed.
94
95 =cut
96
97 sub up {
98 my ($self, $id) = @_;
99
100 my $sem = $self->[1]{$id} ||= Coro::Semaphore::_alloc $self->[0];
101
102 Coro::Semaphore::up $sem;
103
104 delete $self->[1]{$id}
105 if _may_delete $sem, $self->[0], 1;
106 }
107
108 =item $semset->try ($id)
109
110 Try to C<down> the semaphore. Returns true when this was possible,
111 otherwise return false and leave the semaphore unchanged.
112
113 =cut
114
115 sub try {
116 Coro::Semaphore::try ($_[0][1]{$_[1]} || return $_[0][0] > 0)
117 }
118
119 =item $semset->count ($id)
120
121 Return the current semaphore count for the specified semaphore.
122
123 =cut
124
125 sub count {
126 Coro::Semaphore::count ($_[0][1]{$_[1]} || return $_[0][0]);
127 }
128
129 =item $semset->waiters ($id)
130
131 Returns the number (in scalar context) or list (in list context) of
132 waiters waiting on the specified semaphore.
133
134 =cut
135
136 sub waiters {
137 Coro::Semaphore::waiters ($_[0][1]{$_[1]} || return);
138 }
139
140 =item $semset->wait ($id)
141
142 Same as Coro::Semaphore::wait on the specified semaphore.
143
144 =cut
145
146 sub wait {
147 Coro::Semaphore::wait ($_[0][1]{$_[1]} || return);
148 }
149
150 =item $guard = $semset->guard ($id)
151
152 This method calls C<down> and then creates a guard object. When the guard
153 object is destroyed it automatically calls C<up>.
154
155 =cut
156
157 sub guard {
158 &down;
159 bless [@_], Coro::SemaphoreSet::guard::
160 }
161
162 #ub timed_guard {
163 # &timed_down
164 # ? bless [$_[0], $_[1]], Coro::SemaphoreSet::guard::
165 # : ();
166 #
167
168 sub Coro::SemaphoreSet::guard::DESTROY {
169 up @{$_[0]};
170 }
171
172 =item $semaphore = $semset->sem ($id)
173
174 This SemaphoreSet version is based on Coro::Semaphore's. This function
175 creates (if necessary) the underlying Coro::Semaphore object and returns
176 it. You may legally call any Coro::Semaphore method on it, but note that
177 calling C<< $semset->up >> can invalidate the returned semaphore.
178
179 =cut
180
181 sub sem {
182 bless +($_[0][1]{$_[1]} ||= Coro::Semaphore::_alloc $_[0][0]),
183 Coro::Semaphore::;
184 }
185
186 1;
187
188 =back
189
190 =head1 AUTHOR
191
192 Marc Lehmann <schmorp@schmorp.de>
193 http://home.schmorp.de/
194
195 =cut
196