NAME
MCE::Shared::Condvar - Condvar helper class
VERSION
This document describes MCE::Shared::Condvar version 1.005
SYNOPSIS
use MCE::Shared;
my $cv = MCE::Shared->condvar( 0 );
# oo interface
$val = $cv->set( $val );
$val = $cv->get();
$len = $cv->len();
# conditional locking primitives
$cv->lock();
$cv->unlock();
$cv->broadcast();
$cv->broadcast(0.05); # delay before broadcasting
$cv->signal();
$cv->signal(0.05); # delay before signaling
$cv->timedwait(2.5);
$cv->wait();
# sugar methods without having to call set/get explicitly
$val = $cv->append( $string ); # $val .= $string
$val = $cv->decr(); # --$val
$val = $cv->decrby( $number ); # $val -= $number
$val = $cv->getdecr(); # $val--
$val = $cv->getincr(); # $val++
$val = $cv->incr(); # ++$val
$val = $cv->incrby( $number ); # $val += $number
$old = $cv->getset( $new ); # $o = $v, $v = $n, $o
DESCRIPTION
This helper class for MCE::Shared provides a Scalar
, Mutex
, and primitives for conditional locking.
The following demonstrates barrier synchronization.
use MCE;
use MCE::Shared;
use Time::HiRes qw(usleep);
my $num_workers = 8;
my $count = MCE::Shared->condvar(0);
my $state = MCE::Shared->scalar("ready");
my $microsecs = ($^O eq "cygwin") ? 0 : 200;
# The lock is released upon entering ->broadcast, ->signal, ->timedwait,
# and ->wait. For performance reasons, the condition variable is *not*
# re-locked prior to exiting the call. Therefore, obtain the lock when
# synchronization is desired subsequently.
sub barrier_sync {
usleep($microsecs) until $state->get eq "ready" or $state->get eq "up";
$count->lock;
$state->set("up"), $count->incr;
if ($count->get == $num_workers) {
$count->decr, $state->set("down");
$count->broadcast;
}
else {
$count->wait while $state->get eq "up";
$count->lock;
$count->decr;
$state->set("ready") if $count->get == 0;
$count->unlock;
}
}
# Time taken from a 2.6 GHz machine running Mac OS X.
#
# threads::shared: 0.238s threads
# forks::shared: 36.426s child processes
# MCE::Shared: 0.397s child processes
# MCE Sync: 0.062s child processes
sub user_func {
my $id = MCE->wid;
for (1 .. 400) {
MCE->print("$_: $id\n");
# MCE->sync(); # via MCE Core API
barrier_sync(); # via MCE::Shared::Condvar
}
}
my $mce = MCE->new(
max_workers => $num_workers,
user_func => \&user_func
)->run;
API DOCUMENTATION
- new ( [ value ] )
-
Constructs a new condition variable. Its value defaults to
0
whenvalue
is not specified.# shared use MCE::Shared; $cv = MCE::Shared->condvar( 100 ); $cv = MCE::Shared->condvar;
- set ( value )
-
Sets the value associated with the
cv
object. The new value is returned in scalar context.$val = $cv->set( 10 ); $cv->set( 10 );
- get
-
Returns the value associated with the
cv
object.$val = $cv->get;
- len
-
Returns the length of the value. It returns the
undef
value if the value is not defined.$len = $var->len;
- lock
-
Attempts to grab the lock and waits if not available. Multiple calls to
$cv-
lock> by the same process or thread is safe. The mutex will remain locked until$cv-
unlock> is called.$cv->lock;
- unlock
-
Releases the lock. A held lock by an exiting process or thread is released automatically.
$cv->unlock;
- signal ( [ floating_seconds ] )
-
Releases a held lock on the variable. Then, unblocks one process or thread that's
wait
ing on that variable. The variable is *not* locked upon return.Optionally, delay
floating_seconds
before signaling.$count->signal; $count->signal( 0.5 );
- broadcast ( [ floating_seconds ] )
-
The
broadcast
method works similarly tosignal
. It releases a held lock on the variable. Then, unblocks all the processes or threads that are blocked in a conditionwait
on the variable, rather than only one. The variable is *not* locked upon return.Optionally, delay
floating_seconds
before broadcasting.$count->broadcast; $count->broadcast( 0.5 );
- wait
-
Releases a held lock on the variable. Then, waits until another thread does a
signal
orbroadcast
for the same variable. The variable is *not* locked upon return.$count->wait() while $state->get() eq "bar";
- timedwait ( floating_seconds )
-
Releases a held lock on the variable. Then, waits until another thread does a
signal
orbroadcast
for the same variable or if the timeout exceedsfloating_seconds
.A false value is returned if the timeout is reached, and a true value otherwise. In either case, the variable is *not* locked upon return.
$count->timedwait( 10 ) while $state->get() eq "foo";
SUGAR METHODS
This module is equipped with sugar methods to not have to call set
and get
explicitly. The API resembles a subset of the Redis primitives http://redis.io/commands#strings without the key argument.
- append ( value )
-
Appends a value at the end of the current value and returns its new length.
$len = $cv->append( "foo" );
- decr
-
Decrements the value by one and returns its new value.
$num = $cv->decr;
- decrby ( number )
-
Decrements the value by the given number and returns its new value.
$num = $cv->decrby( 2 );
- getdecr
-
Decrements the value by one and returns its old value.
$old = $cv->getdecr;
- getincr
-
Increments the value by one and returns its old value.
$old = $cv->getincr;
- getset ( value )
-
Sets the value and returns its old value.
$old = $cv->getset( "baz" );
- incr
-
Increments the value by one and returns its new value.
$num = $cv->incr;
- incrby ( number )
-
Increments the value by the given number and returns its new value.
$num = $cv->incrby( 2 );
CREDITS
The conditional locking aspect is inspired by threads::shared.
LIMITATION
Perl must have the IO::FDPass module installed for constructing a shared queue
or condvar
while the shared-manager process is running.
For platforms where IO::FDPass
is not feasible, construct queues
or condvars
first before other classes. The shared-manager process is delayed until sharing other classes or explicitly starting the process.
use MCE::Shared;
my $q1 = MCE::Shared->queue();
my $cv = MCE::Shared->condvar();
MCE::Shared->start();
INDEX
AUTHOR
Mario E. Roy, <marioeroy AT gmail DOT com>