Rules / Types, classes & roles / domain-specific

Lock::ConditionVariable Reference

Condition variables used in locks

What it is #

Routines #

Signatures are reproduced from the documentation, including their declared return types. A routine listed here is part of the type's published interface; whether Raku++ implements it is a separate question, answered by the examples below.

method wait #

multi method wait( --> Nil )
multi method wait( &predicate --> Nil )

Returns Nil.

Without any predicate, it waits on the condition variable itself; with a predicate, waits until the code returns a truish value. The condition we obtain from the $l lock is awaited using a predicate, in this case, check if the counter is still zero. When it takes another value, the program flow continues in the next instruction.

method signal #

method signal()

If and only if there are any threads that have previously waited on the condition variable, it unblocks at least one of them. Let's see how it works in this example: We are repeating 15 times the same operation: start 100 threads, every one of which modify a single element in an array. We protect the modification of a global variable, $done, and use signal to wake up another thread to do its thing. This outputs the first elements of the generated arrays.

Examples, run three ways #

Every example below comes from the official documentation, together with the output that documentation asserts. Each was then executed by Rakudo and by Raku++ when this page was built. Where the three agree, one result is shown; where they do not, all three are — because which of them is wrong is exactly the information worth having.

3 no-output

class Lock::ConditionVariable {}

Not executed: the documentation states no expected output for this example.

my $times = 100;
my $tried;
my $failed;
for ^$times {
    my $l = Lock.new;
    my $c = $l.condition;
    my $now1;
    my $now2;
    my $counter = 0;
    my $t1 = Thread.start({
        $l.protect({
            $c.wait( { $counter != 0 } );
            $now1 = now;
        });
    });

    my $t2 = Thread.start({
        $l.protect({
            $counter++;
            $c.signal();
        });
    });

    $t1.join();
    $now2 = now;
    $t2.join();

    $tried++;
    last if $failed = ( !$now1.defined or $now1 > $now2 );
}

Not executed: the documentation states no expected output for this example.

constant ITEMS = 100;
for 1..15 -> $iter {
my $lock = Lock.new;
my $cond = $lock.condition;
my $todo = 0;
my $done = 0;
my @in = 1..ITEMS;
my @out = 0 xx ITEMS;

for 1..ITEMS -> $i {
    my $in = $i;
    my $out := @out[$i];
    Thread.start( {
                $out = $in * 10;
                $lock.protect( {
                    $done++;
                    $cond.signal if $done == $todo;
                } );
    } );
    $todo++;
}
$lock.protect( {
    $cond.wait({  $done == $todo } );
});
say @out;
}

Not executed: the documentation states no expected output for this example.