comparison tango/tango/core/sync/Barrier.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /**
2 * The barrier module provides a primitive for synchronizing the progress of
3 * a group of threads.
4 *
5 * Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved.
6 * License: BSD style: $(LICENSE)
7 * Authors: Sean Kelly
8 */
9 module tango.core.sync.Barrier;
10
11
12 public import tango.core.Exception : SyncException;
13 private import tango.core.sync.Condition;
14 private import tango.core.sync.Mutex;
15
16 version( Win32 )
17 {
18 private import tango.sys.win32.UserGdi;
19 }
20 else version( Posix )
21 {
22 private import tango.stdc.errno;
23 private import tango.stdc.posix.pthread;
24 }
25
26
27 ////////////////////////////////////////////////////////////////////////////////
28 // Barrier
29 //
30 // void wait();
31 ////////////////////////////////////////////////////////////////////////////////
32
33
34 /**
35 * This class represents a barrier across which threads may only travel in
36 * groups of a specific size.
37 */
38 class Barrier
39 {
40 ////////////////////////////////////////////////////////////////////////////
41 // Initialization
42 ////////////////////////////////////////////////////////////////////////////
43
44
45 /**
46 * Initializes a barrier object which releases threads in groups of limit
47 * in size.
48 *
49 * Params:
50 * limit = The number of waiting threads to release in unison.
51 *
52 * Throws:
53 * SyncException on error.
54 */
55 this( uint limit )
56 in
57 {
58 assert( limit > 0 );
59 }
60 body
61 {
62 m_lock = new Mutex;
63 m_cond = new Condition( m_lock );
64 m_group = 0;
65 m_limit = limit;
66 m_count = limit;
67 }
68
69
70 ////////////////////////////////////////////////////////////////////////////
71 // General Actions
72 ////////////////////////////////////////////////////////////////////////////
73
74
75 /**
76 * Wait for the pre-determined number of threads and then proceed.
77 *
78 * Throws:
79 * SyncException on error.
80 */
81 void wait()
82 {
83 synchronized( m_lock )
84 {
85 uint group = m_group;
86
87 if( --m_count == 0 )
88 {
89 m_group++;
90 m_count = m_limit;
91 m_cond.notifyAll();
92 }
93 while( group == m_group )
94 m_cond.wait();
95 }
96 }
97
98
99 private:
100 Mutex m_lock;
101 Condition m_cond;
102 uint m_group;
103 uint m_limit;
104 uint m_count;
105 }
106
107
108 ////////////////////////////////////////////////////////////////////////////////
109 // Unit Tests
110 ////////////////////////////////////////////////////////////////////////////////
111
112
113 debug( UnitTest )
114 {
115 private import tango.core.Thread;
116
117
118 unittest
119 {
120 int numThreads = 10;
121 auto barrier = new Barrier( numThreads );
122 auto synInfo = new Object;
123 int numReady = 0;
124 int numPassed = 0;
125
126 void threadFn()
127 {
128 synchronized( synInfo )
129 {
130 ++numReady;
131 }
132 barrier.wait();
133 synchronized( synInfo )
134 {
135 ++numPassed;
136 }
137 }
138
139 auto group = new ThreadGroup;
140
141 for( int i = 0; i < numThreads; ++i )
142 {
143 group.create( &threadFn );
144 }
145 group.joinAll();
146 assert( numReady == numThreads && numPassed == numThreads );
147 }
148 }