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