ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/SemaphoreSet.pm
Revision: 1.88
Committed: Sat Aug 22 22:36:23 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
CVS Tags: rel-5_17
Changes since 1.87: +1 -1 lines
Log Message:
5.17

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