ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/SemaphoreSet.pm
Revision: 1.67
Committed: Mon Nov 17 08:25:06 2008 UTC (15 years, 6 months ago) by root
Branch: MAIN
Changes since 1.66: +5 -4 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Coro::SemaphoreSet - hash of 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 no warnings;
34
35 use Coro ();
36
37 $VERSION = 5.0;
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 $sem->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 =item $status = $sem->timed_down ($id, $timeout)
56
57 Like C<down>, but returns false if semaphore couldn't be acquired within
58 $timeout seconds, otherwise true.
59
60 =cut
61
62 sub down {
63 # Coro::Semaphore::down ($_[0][1]{$_[1]} ||= Coro::Semaphore::new undef, $_[0][0]);
64 while () {
65 my $sem = ($_[0][1]{$_[1]} ||= [$_[0][0]]);
66
67 if ($sem->[0] > 0) {
68 --$sem->[0];
69 return 1;
70 }
71
72 push @{$sem->[1]}, $Coro::current;
73 &Coro::schedule;
74 }
75 }
76
77 sub timed_down {
78 require Coro::Timer;
79 my $timeout = Coro::Timer::timeout ($_[2]);
80
81 while () {
82 my $sem = ($_[0][1]{$_[1]} ||= [$_[0][0]]);
83
84 if ($sem->[0] > 0) {
85 --$sem->[0];
86 return 1;
87 }
88
89 if ($timeout) {
90 # ugly as hell.
91 for (0..$#{$sem->[1]}) {
92 if ($sem->[1][$_] == $Coro::current) {
93 splice @{$sem->[1]}, $_, 1;
94 return 0;
95 }
96 }
97 die;
98 }
99
100 push @{$sem->[1]}, $Coro::current;
101 &Coro::schedule;
102 }
103 }
104
105 =item $sem->up ($id)
106
107 Unlock the semaphore again.
108
109 =cut
110
111 sub up {
112 my $sem = $_[0][1]{$_[1]};
113
114 if (++$sem->[0] > 0) {
115 (shift @{$sem->[1]})->ready if @{$sem->[1]};
116 }
117
118 delete $_[0][1]{$_[1]} if $sem->[0] == $_[0][0] && !@{$sem->[1] || []};
119 }
120
121 =item $sem->try
122
123 Try to C<down> the semaphore. Returns true when this was possible,
124 otherwise return false and leave the semaphore unchanged.
125
126 =cut
127
128 sub try {
129 my $sem = ($_[0][1]{$_[1]} ||= [$_[0][0]]);
130 if ($sem->[0] > 0) {
131 --$sem->[0];
132 return 1;
133 } else {
134 return 0;
135 }
136 }
137
138 =item $sem->waiters ($id)
139
140 In scalar context, returns the number of coroutines waiting for this
141 semaphore.
142
143 =cut
144
145 sub waiters {
146 my $sem = $_[0][1]{$_[1]}
147 or return;
148 @{ $_[0][1]{$_[1]}[1] || []}
149 }
150
151 =item $guard = $sem->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 =item $guard = $sem->timed_guard ($id, $timeout)
157
158 Like C<guard>, but returns undef if semaphore couldn't be acquired within
159 $timeout seconds, otherwise the guard object.
160
161 =cut
162
163 sub guard {
164 &down;
165 bless [@_], Coro::SemaphoreSet::guard::;
166 }
167
168 sub timed_guard {
169 &timed_down
170 ? bless [$_[0], $_[1]], Coro::SemaphoreSet::guard::
171 : ();
172 }
173
174 sub Coro::SemaphoreSet::guard::DESTROY {
175 &up(@{$_[0]});
176 }
177
178 1;
179
180 =back
181
182 =head1 AUTHOR
183
184 Marc Lehmann <schmorp@schmorp.de>
185 http://home.schmorp.de/
186
187 =cut
188