IO::Lambda::Mutex(3p)

NAME
IO::Lambda::Mutex - wait for a shared resource

DESCRIPTION
Objects of class "IO::Lambda::Mutex" are mutexes, that as normal mutexes, can be taken and released. The mutexes allow lambdas to wait for their availability with method "waiter", that creates and returns a new lambda, that in turn will finish as soon as the caller can acquire the mutex.

SYNOPSIS
    use IO::Lambda qw(:lambda);
    use IO::Lambda::Mutex qw(mutex);

    my $mutex = IO::Lambda::Mutex-> new;

    # wait for mutex that shall be available immediately
    my $waiter = $mutex-> waiter;
    my $error = $waiter-> wait;
    die "error:$error" if $error;

    # create and start a lambda that sleeps 2 seconds and then releases the mutex
    my $sleeper = lambda {
        context 2;
        timeout { $mutex-> release }
    };
    $sleeper-> start;

    # Create a new lambda that shall only wait for 0.5 seconds.
    # It will surely fail, since $sleeper is well, still sleeping
    lambda {
        context $mutex-> waiter(0.5);
        tail {
            my $error = shift;
            print $error ? "error:$error\n" : "ok\n";
            # $error is expected to be 'timeout'
        }
    }-> wait;

    # Again, wait for the same mutex but using different syntax.
    # This time should be ok - $sleeper will sleep for 1.5 seconds and
    # then the mutex will be available.
    lambda {
        context $mutex, 3;
        mutex {
            my $error = shift;
            print $error ? "error:$error\n" : "ok\n";
            # expected to be 'ok'
        }
    }->wait;

    # pipeline -  manage a queue of lambdas, stuff new ones to it, guarantees
    # sequential execution:
    lambda {
        context
            $mutex-> pipeline( lambda { print 1 } ),
            $mutex-> pipeline( lambda { print 2 } ),
            $mutex-> pipeline( lambda { print 3 } )
        ;
        &tails();
    }-> wait;
    # prints 123 guaranteedly in that order, even if intermediate lambdas sleep etc

API

new The constructor creates a new free mutex.

is_free
    Returns boolean flag whether the mutex is free or not. Opposite of is_taken.

is_taken
    Returns boolean flag whether the mutex is taken or not. Opposite of is_free.

take
    Attempts to take the mutex. If the mutex is free, the operation is successful and true value is returned. Otherwise, the operation is failed and false value is returned.

release
    Tries to releases the taken mutex. If there are lambdas waiting (see waiter) in the queue, the first lambda will be terminated, and thus whoever waits for the lambda can be notified; it will be up to the code associated with the waiter lambda to call "release" again. If there are no waiters in the queue, the mutex is set free.

waiter($timeout = undef) :: () -> error
    Creates a new lambda, that is finished when the mutex becomes available. The lambda is inserted into the internal waiting queue. It takes as many calls to "release" as many lambdas are in queue, until the mutex becomes free. The lambda returns an error flags, which is "undef" if the mutex was acquired successfully, or the error string.

    If $timeout is defined, and by the time it is expired the mutex could not be obtained, the lambda is removed from the queue, and returned error value is 'timeout'. The mutex state is then unchanged.

    If "waiter" succeeds, a "release" call is issued. Thus, if the next waiter awaits for the mutex, it will be notified; otherwise the mutex becomes free.

pipeline($lambda, $timeout = undef)
    Creates a new lambda, that wraps over $lambda so that it is executed after mutex had been obtained. Also, as soon as $lambda is finished, the mutex is released, thus allowing others to take it.

remove($lambda)
    Internal function, do not use directly, use "$lambda-> terminate" instead.

    Removes the lambda created previously by waiter() from internal queue. Note that after that operation the lambda will never finish by itself.

mutex($mutex, $timeout = undef) -> error
    Condition wrapper over "waiter".

AUTHOR
Dmitry Karasik, <dmitry@karasik.eu.org>.