ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/SemaphoreSet.pm
Revision: 1.101
Committed: Wed Feb 23 07:14:22 2011 UTC (13 years, 3 months ago) by root
Branch: MAIN
CVS Tags: rel-5_372
Changes since 1.100: +1 -1 lines
Log Message:
5.372

File Contents

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