Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

core.sync.condition

The condition module provides a primitive for synchronized condition checking.
Authors:
Sean Kelly
class Condition;
This class represents a condition variable as conceived by C.A.R. Hoare. As per Mesa type monitors however, "signal" has been replaced with "notify" to indicate that control is not transferred to the waiter when a notification is sent.
Examples:
import core.thread;
import core.sync.mutex;
import core.sync.semaphore;


void testNotify()
{
    auto mutex      = new Mutex;
    auto condReady  = new Condition( mutex );
    auto semDone    = new Semaphore;
    auto synLoop    = new Object;
    int  numWaiters = 10;
    int  numTries   = 10;
    int  numReady   = 0;
    int  numTotal   = 0;
    int  numDone    = 0;
    int  numPost    = 0;

    void waiter()
    {
        for ( int i = 0; i < numTries; ++i )
        {
            synchronized( mutex )
            {
                while ( numReady < 1 )
                {
                    condReady.wait();
                }
                --numReady;
                ++numTotal;
            }

            synchronized( synLoop )
            {
                ++numDone;
            }
            semDone.wait();
        }
    }

    auto group = new ThreadGroup;

    for ( int i = 0; i < numWaiters; ++i )
        group.create( &waiter );

    for ( int i = 0; i < numTries; ++i )
    {
        for ( int j = 0; j < numWaiters; ++j )
        {
            synchronized( mutex )
            {
                ++numReady;
                condReady.notify();
            }
        }
        while ( true )
        {
            synchronized( synLoop )
            {
                if ( numDone >= numWaiters )
                    break;
            }
            Thread.yield();
        }
        for ( int j = 0; j < numWaiters; ++j )
        {
            semDone.notify();
        }
    }

    group.joinAll();
    assert( numTotal == numWaiters * numTries );
}


void testNotifyAll()
{
    auto mutex      = new Mutex;
    auto condReady  = new Condition( mutex );
    int  numWaiters = 10;
    int  numReady   = 0;
    int  numDone    = 0;
    bool alert      = false;

    void waiter()
    {
        synchronized( mutex )
        {
            ++numReady;
            while ( !alert )
                condReady.wait();
            ++numDone;
        }
    }

    auto group = new ThreadGroup;

    for ( int i = 0; i < numWaiters; ++i )
        group.create( &waiter );

    while ( true )
    {
        synchronized( mutex )
        {
            if ( numReady >= numWaiters )
            {
                alert = true;
                condReady.notifyAll();
                break;
            }
        }
        Thread.yield();
    }
    group.joinAll();
    assert( numReady == numWaiters && numDone == numWaiters );
}


void testWaitTimeout()
{
    auto mutex      = new Mutex;
    auto condReady  = new Condition( mutex );
    bool waiting    = false;
    bool alertedOne = true;
    bool alertedTwo = true;

    void waiter()
    {
        synchronized( mutex )
        {
            waiting    = true;
            // we never want to miss the notification (30s)
            alertedOne = condReady.wait( dur!"seconds"(30) );
            // but we don't want to wait long for the timeout (10ms)
            alertedTwo = condReady.wait( dur!"msecs"(10) );
        }
    }

    auto thread = new Thread( &waiter );
    thread.start();

    while ( true )
    {
        synchronized( mutex )
        {
            if ( waiting )
            {
                condReady.notify();
                break;
            }
        }
        Thread.yield();
    }
    thread.join();
    assert( waiting );
    assert( alertedOne );
    assert( !alertedTwo );
}

testNotify();
testNotifyAll();
testWaitTimeout();
nothrow @nogc @safe this(Mutex m);

shared nothrow @nogc @safe this(shared Mutex m);
Initializes a condition object which is associated with the supplied mutex object.
Parameters:
Mutex m The mutex with which this condition will be associated.
Throws:
SyncError on error.
@property Mutex mutex();

shared @property shared(Mutex) mutex();
Gets the mutex associated with this condition.
Returns:
The mutex associated with this condition.
void wait();

shared void wait();

void wait(this Q)(bool _unused_)
if (is(Q == Condition) || is(Q == shared(Condition)));
Wait until notified.
Throws:
SyncError on error.
bool wait(Duration val);

shared bool wait(Duration val);

bool wait(this Q)(Duration val, bool _unused_)
if (is(Q == Condition) || is(Q == shared(Condition)));
Suspends the calling thread until a notification occurs or until the supplied time period has elapsed.
Parameters:
Duration val The time to wait.

In val must be non-negative.

Throws:
SyncError on error.
Returns:
true if notified before the timeout and false if not.
void notify();

shared void notify();

void notify(this Q)(bool _unused_)
if (is(Q == Condition) || is(Q == shared(Condition)));
Notifies one waiter.
Throws:
SyncError on error.
void notifyAll();

shared void notifyAll();

void notifyAll(this Q)(bool _unused_)
if (is(Q == Condition) || is(Q == shared(Condition)));
Notifies all waiters.
Throws:
SyncError on error.