Thread::Semaphore 2.07
[p5sagit/p5-mst-13.2.git] / lib / Thread / Semaphore.pm
1 package Thread::Semaphore;
2
3 use strict;
4 use warnings;
5
6 our $VERSION = '2.07';
7
8 use threads::shared;
9 use Scalar::Util 1.10 qw(looks_like_number);
10
11 # Create a new semaphore optionally with specified count (count defaults to 1)
12 sub new {
13     my $class = shift;
14     my $val :shared = @_ ? shift : 1;
15     if (! looks_like_number($val) || (int($val) != $val)) {
16         require Carp;
17         $val = 'undef' if (! defined($val));
18         Carp::croak("Semaphore initializer is not an integer: $val");
19     }
20     return bless(\$val, $class);
21 }
22
23 # Decrement a semaphore's count (decrement amount defaults to 1)
24 sub down {
25     my $sema = shift;
26     lock($$sema);
27     my $dec = @_ ? shift : 1;
28     if (! looks_like_number($dec) || (int($dec) != $dec) || ($dec < 1)) {
29         require Carp;
30         $dec = 'undef' if (! defined($dec));
31         Carp::croak("Semaphore decrement is not a positive integer: $dec");
32     }
33     cond_wait($$sema) until ($$sema >= $dec);
34     $$sema -= $dec;
35 }
36
37 # Increment a semaphore's count (increment amount defaults to 1)
38 sub up {
39     my $sema = shift;
40     lock($$sema);
41     my $inc = @_ ? shift : 1;
42     if (! looks_like_number($inc) || (int($inc) != $inc) || ($inc < 1)) {
43         require Carp;
44         $inc = 'undef' if (! defined($inc));
45         Carp::croak("Semaphore increment is not a positive integer: $inc");
46     }
47     ($$sema += $inc) > 0 and cond_broadcast($$sema);
48 }
49
50 1;
51
52 =head1 NAME
53
54 Thread::Semaphore - Thread-safe semaphores
55
56 =head1 VERSION
57
58 This document describes Thread::Semaphore version 2.07
59
60 =head1 SYNOPSIS
61
62     use Thread::Semaphore;
63     my $s = Thread::Semaphore->new();
64     $s->down();   # Also known as the semaphore P operation.
65     # The guarded section is here
66     $s->up();     # Also known as the semaphore V operation.
67
68     # The default semaphore value is 1
69     my $s = Thread::Semaphore-new($initial_value);
70     $s->down($down_value);
71     $s->up($up_value);
72
73 =head1 DESCRIPTION
74
75 Semaphores provide a mechanism to regulate access to resources.  Unlike
76 locks, semaphores aren't tied to particular scalars, and so may be used to
77 control access to anything you care to use them for.
78
79 Semaphores don't limit their values to zero and one, so they can be used to
80 control access to some resource that there may be more than one of (e.g.,
81 filehandles).  Increment and decrement amounts aren't fixed at one either,
82 so threads can reserve or return multiple resources at once.
83
84 =head1 METHODS
85
86 =over 8
87
88 =item ->new()
89
90 =item ->new(NUMBER)
91
92 C<new> creates a new semaphore, and initializes its count to the specified
93 number (which must be an integer).  If no number is specified, the
94 semaphore's count defaults to 1.
95
96 =item ->down()
97
98 =item ->down(NUMBER)
99
100 The C<down> method decreases the semaphore's count by the specified number
101 (which must be an integer >= 1), or by one if no number is specified.
102
103 If the semaphore's count would drop below zero, this method will block
104 until such time as the semaphore's count is greater than or equal to the
105 amount you're C<down>ing the semaphore's count by.
106
107 This is the semaphore "P operation" (the name derives from the Dutch
108 word "pak", which means "capture" -- the semaphore operations were
109 named by the late Dijkstra, who was Dutch).
110
111 =item ->up()
112
113 =item ->up(NUMBER)
114
115 The C<up> method increases the semaphore's count by the number specified
116 (which must be an integer >= 1), or by one if no number is specified.
117
118 This will unblock any thread that is blocked trying to C<down> the
119 semaphore if the C<up> raises the semaphore's count above the amount that
120 the C<down> is trying to decrement it by.  For example, if three threads
121 are blocked trying to C<down> a semaphore by one, and another thread C<up>s
122 the semaphore by two, then two of the blocked threads (which two is
123 indeterminate) will become unblocked.
124
125 This is the semaphore "V operation" (the name derives from the Dutch
126 word "vrij", which means "release").
127
128 =back
129
130 =head1 NOTES
131
132 Semaphores created by L<Thread::Semaphore> can be used in both threaded and
133 non-threaded applications.  This allows you to write modules and packages
134 that potentially make use of semaphores, and that will function in either
135 environment.
136
137 =head1 SEE ALSO
138
139 Thread::Semaphore Discussion Forum on CPAN:
140 L<http://www.cpanforum.com/dist/Thread-Semaphore>
141
142 Annotated POD for Thread::Semaphore:
143 L<http://annocpan.org/~JDHEDDEN/Thread-Semaphore-2.07/lib/Thread/Semaphore.pm>
144
145 Source repository:
146 L<http://code.google.com/p/thread-semaphore/>
147
148 L<threads>, L<threads::shared>
149
150 =head1 MAINTAINER
151
152 Jerry D. Hedden, S<E<lt>jdhedden AT cpan DOT orgE<gt>>
153
154 =head1 LICENSE
155
156 This program is free software; you can redistribute it and/or modify it under
157 the same terms as Perl itself.
158
159 =cut