diff druntime/src/common/core/sync/barrier.d @ 1458:e0b2d67cfe7c

Added druntime (this should be removed once it works).
author Robert Clipsham <robert@octarineparrot.com>
date Tue, 02 Jun 2009 17:43:06 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/druntime/src/common/core/sync/barrier.d	Tue Jun 02 17:43:06 2009 +0100
@@ -0,0 +1,153 @@
+/**
+ * The barrier module provides a primitive for synchronizing the progress of
+ * a group of threads.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
+ * Authors:   Sean Kelly
+ *
+ *          Copyright Sean Kelly 2005 - 2009.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+module core.sync.barrier;
+
+
+public import core.sync.exception;
+private import core.sync.condition;
+private import core.sync.mutex;
+
+version( Win32 )
+{
+    private import core.sys.windows.windows;
+}
+else version( Posix )
+{
+    private import core.stdc.errno;
+    private import core.sys.posix.pthread;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Barrier
+//
+// void wait();
+////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * This class represents a barrier across which threads may only travel in
+ * groups of a specific size.
+ */
+class Barrier
+{
+    ////////////////////////////////////////////////////////////////////////////
+    // Initialization
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initializes a barrier object which releases threads in groups of limit
+     * in size.
+     *
+     * Params:
+     *  limit = The number of waiting threads to release in unison.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    this( uint limit )
+    in
+    {
+        assert( limit > 0 );
+    }
+    body
+    {
+        m_lock  = new Mutex;
+        m_cond  = new Condition( m_lock );
+        m_group = 0;
+        m_limit = limit;
+        m_count = limit;
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // General Actions
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Wait for the pre-determined number of threads and then proceed.
+     *
+     * Throws:
+     *  SyncException on error.
+     */
+    void wait()
+    {
+        synchronized( m_lock )
+        {
+            uint group = m_group;
+
+            if( --m_count == 0 )
+            {
+                m_group++;
+                m_count = m_limit;
+                m_cond.notifyAll();
+            }
+            while( group == m_group )
+                m_cond.wait();
+        }
+    }
+
+
+private:
+    Mutex       m_lock;
+    Condition   m_cond;
+    uint        m_group;
+    uint        m_limit;
+    uint        m_count;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Unit Tests
+////////////////////////////////////////////////////////////////////////////////
+
+
+version( unittest )
+{
+    private import core.thread;
+
+
+    unittest
+    {
+        int  numThreads = 10;
+        auto barrier    = new Barrier( numThreads );
+        auto synInfo    = new Object;
+        int  numReady   = 0;
+        int  numPassed  = 0;
+
+        void threadFn()
+        {
+            synchronized( synInfo )
+            {
+                ++numReady;
+            }
+            barrier.wait();
+            synchronized( synInfo )
+            {
+                ++numPassed;
+            }
+        }
+
+        auto group = new ThreadGroup;
+
+        for( int i = 0; i < numThreads; ++i )
+        {
+            group.create( &threadFn );
+        }
+        group.joinAll();
+        assert( numReady == numThreads && numPassed == numThreads );
+    }
+}