File Coverage

blib/lib/POE/Component/ResourcePool/Resource/Semaphore.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package POE::Component::ResourcePool::Resource::Semaphore;
4 2     2   28590 use Moose;
  0            
  0            
5              
6             with qw(POE::Component::ResourcePool::Resource);
7              
8             has initial_value => (
9             isa => "Num",
10             is => "ro",
11             required => 1,
12             );
13              
14             has value => (
15             isa => "Num",
16             is => "rw",
17             writer => "_value",
18             init_arg => undef,
19             );
20              
21             sub BUILD {
22             my $self = shift;
23             $self->_value( $self->initial_value );
24             }
25              
26             sub could_allocate {
27             my ( $self, $pool, $request, $value ) = @_;
28              
29             return ( $value <= $self->initial_value );
30             }
31              
32             sub try_allocating {
33             my ( $self, $pool, $request, $value ) = @_;
34              
35             if ( $value <= $self->value ) {
36             return $value;
37             } else {
38             return;
39             }
40             }
41              
42             sub finalize_allocation {
43             my ( $self, $pool, $request, $value ) = @_;
44              
45             $self->_value( $self->value - $value );
46              
47             return $value;
48             }
49              
50             sub free_allocation {
51             my ( $self, $pool, $request, $value ) = @_;
52              
53             $self->_value( $self->value + $value );
54              
55             $self->notify_all_pools;
56             }
57              
58             __PACKAGE__
59              
60             __END__
61              
62             =pod
63              
64             =head1 NAME
65              
66             POE::Component::ResourcePool::Resource::Semaphore - numerical semaphore resource.
67              
68             =head1 SYNOPSIS
69              
70             # this example will allow up to 10 concurrent URL fetches by blocking
71             # sessions until they get their resources allocated.
72              
73             # the control could be inverted such that the main loop queues up many
74             # requests, each of which creates a fetcher session.
75              
76             # the actual URL fetching code has been omitted for brevity.
77              
78              
79             # first create the semaphore:
80             my $sem = POE::Component::ResourcePool::Resource::Semaphore->new( initial_value => 10 );
81              
82              
83             # then add it to a pool:
84             my $pool = POE::Component::ResourcePool->new(
85             resources => { connections => $sem },
86             )
87              
88              
89             # finally queue requests that will trigger the callback when they are
90             # fulfilled.
91              
92             foreach my $url ( @urls ) {
93             POE::Session->create(
94             inline_states => {
95             _start => sub {
96             my ( $kernel, $heap ) = @_[KERNEL, HEAP];
97              
98             $pool->request(
99             params => { connections => 1 },
100             event => "fetch",
101             );
102             },
103             fetch => sub {
104             my ( $kernel, $heap ) = @_[KERNEL, HEAP];
105              
106             ... fetch ...
107              
108             $heap->{request}->dismiss;
109             },
110             },
111             );
112             }
113              
114             =head1 DESCRIPTION
115              
116             This class provides a numerical semaphore based resource for
117             L<POE::Component::ResourcePool>.
118              
119             This is useful for throttling resources, for example the number of concurrent
120             jobs or a symbolic value for memory units.
121              
122             The semaphore will fulfill requests for numerical values (the default value is
123             1) as long as it's counter remains above zero.
124              
125             Requests asking for more than the initial value will fail immediately.
126              
127             =head1 METHODS
128              
129             =over 4
130              
131             =item could_allocate
132              
133             Returns true if the value is numerically less than or equal to the semaphore's
134             initial value.
135              
136             =item try_allocating
137              
138             Successfully allocates if the value is numerically less than or equal to the
139             semaphore's current value.
140              
141             =item finalize_allocation
142              
143             Finalizes an allocation by deducting the requested value from the semaphore's
144             current value, and returns the request value as the parameter for the resource.
145              
146             =item free_allocation
147              
148             Adds the freed value to the semaphore's current value, and notifies all pools.
149              
150             Since allocation attempts are a simple procedure no attempt at request tracking
151             is made, and all pools will be notified unconditionally.
152              
153             =back
154              
155             =head1 ATTRIBUTES
156              
157             =over 4
158              
159             =item initial_value
160              
161             The initial value of the semaphore.
162              
163             Required.
164              
165             =item value
166              
167             The current value of the semaphore.
168              
169             Read only.
170              
171             =back
172              
173             =cut