Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
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.
License:
Boost License 1.0
Authors:
Sean Kelly

Source core/sync/condition.d

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.

Copyright © 1999-2023 by the D Language Foundation | Page generated by Ddoc on Fri Sep 15 21:13:27 2023