]> git.ipfire.org Git - thirdparty/gcc.git/blob - libphobos/libdruntime/core/sync/barrier.d
Add D front-end, libphobos library, and D2 testsuite.
[thirdparty/gcc.git] / libphobos / libdruntime / core / sync / barrier.d
1 /**
2 * The barrier module provides a primitive for synchronizing the progress of
3 * a group of threads.
4 *
5 * Copyright: Copyright Sean Kelly 2005 - 2009.
6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Authors: Sean Kelly
8 * Source: $(DRUNTIMESRC core/sync/_barrier.d)
9 */
10
11 /* Copyright Sean Kelly 2005 - 2009.
12 * Distributed under the Boost Software License, Version 1.0.
13 * (See accompanying file LICENSE or copy at
14 * http://www.boost.org/LICENSE_1_0.txt)
15 */
16 module core.sync.barrier;
17
18
19 public import core.sync.exception;
20 private import core.sync.condition;
21 private import core.sync.mutex;
22
23 version (Posix)
24 {
25 private import core.stdc.errno;
26 private import core.sys.posix.pthread;
27 }
28
29
30 ////////////////////////////////////////////////////////////////////////////////
31 // Barrier
32 //
33 // void wait();
34 ////////////////////////////////////////////////////////////////////////////////
35
36
37 /**
38 * This class represents a barrier across which threads may only travel in
39 * groups of a specific size.
40 */
41 class Barrier
42 {
43 ////////////////////////////////////////////////////////////////////////////
44 // Initialization
45 ////////////////////////////////////////////////////////////////////////////
46
47
48 /**
49 * Initializes a barrier object which releases threads in groups of limit
50 * in size.
51 *
52 * Params:
53 * limit = The number of waiting threads to release in unison.
54 *
55 * Throws:
56 * SyncError on error.
57 */
58 this( uint limit )
59 in
60 {
61 assert( limit > 0 );
62 }
63 body
64 {
65 m_lock = new Mutex;
66 m_cond = new Condition( m_lock );
67 m_group = 0;
68 m_limit = limit;
69 m_count = limit;
70 }
71
72
73 ////////////////////////////////////////////////////////////////////////////
74 // General Actions
75 ////////////////////////////////////////////////////////////////////////////
76
77
78 /**
79 * Wait for the pre-determined number of threads and then proceed.
80 *
81 * Throws:
82 * SyncError on error.
83 */
84 void wait()
85 {
86 synchronized( m_lock )
87 {
88 uint group = m_group;
89
90 if ( --m_count == 0 )
91 {
92 m_group++;
93 m_count = m_limit;
94 m_cond.notifyAll();
95 }
96 while ( group == m_group )
97 m_cond.wait();
98 }
99 }
100
101
102 private:
103 Mutex m_lock;
104 Condition m_cond;
105 uint m_group;
106 uint m_limit;
107 uint m_count;
108 }
109
110
111 ////////////////////////////////////////////////////////////////////////////////
112 // Unit Tests
113 ////////////////////////////////////////////////////////////////////////////////
114
115
116 version (unittest)
117 {
118 private import core.thread;
119
120
121 unittest
122 {
123 int numThreads = 10;
124 auto barrier = new Barrier( numThreads );
125 auto synInfo = new Object;
126 int numReady = 0;
127 int numPassed = 0;
128
129 void threadFn()
130 {
131 synchronized( synInfo )
132 {
133 ++numReady;
134 }
135 barrier.wait();
136 synchronized( synInfo )
137 {
138 ++numPassed;
139 }
140 }
141
142 auto group = new ThreadGroup;
143
144 for ( int i = 0; i < numThreads; ++i )
145 {
146 group.create( &threadFn );
147 }
148 group.joinAll();
149 assert( numReady == numThreads && numPassed == numThreads );
150 }
151 }