blocxx
ThreadBarrier.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
38#include "blocxx/BLOCXX_config.h"
40#include "blocxx/Assertion.hpp"
41#include "blocxx/Format.hpp"
44
45#if defined(BLOCXX_USE_PTHREAD) && defined(BLOCXX_HAVE_PTHREAD_BARRIER) && !defined(BLOCXX_VALGRIND_SUPPORT)
46 #include <pthread.h>
47 #include <cstring>
48#else
49 // This is for the generic less-efficient version
50 #include "blocxx/Condition.hpp"
53#endif
54
56namespace BLOCXX_NAMESPACE
57{
58
60
61#if defined(BLOCXX_USE_PTHREAD) && defined(BLOCXX_HAVE_PTHREAD_BARRIER) && !defined(BLOCXX_VALGRIND_SUPPORT) // valgrind doesn't support pthread_barrier_*()
63{
64public:
65 ThreadBarrierImpl(UInt32 threshold)
66 {
67 BLOCXX_ASSERT(threshold != 0);
68 memset(&barrier, 0, sizeof(barrier)); // AIX pukes if the barrier isn't zeroed out.
69 int res = pthread_barrier_init(&barrier, NULL, threshold);
70 if (res != 0)
71 {
72 BLOCXX_THROW(ThreadBarrierException, Format("pthread_barrier_init failed: %1(%2)", res, strerror(res)).c_str());
73 }
74 }
75 ~ThreadBarrierImpl()
76 {
77 int res = pthread_barrier_destroy(&barrier);
78 if (res != 0)
79 {
80 // can't throw... just log it or something...
81 }
82 }
83
84 void wait()
85 {
86 int res = pthread_barrier_wait(&barrier);
87 if (res != 0 && res != PTHREAD_BARRIER_SERIAL_THREAD)
88 {
89 BLOCXX_THROW(ThreadBarrierException, Format("pthread_barrier_wait failed: %1(%2)", res, strerror(res)).c_str());
90 }
91 }
92private:
93 pthread_barrier_t barrier;
94};
95
96#else
97
98// This is the generic less-efficient version
99
101{
102public:
121 ThreadBarrierImpl(UInt32 threshold)
122 : m_threshold(threshold)
123 , m_curSubBarrier(0)
124 {
125 }
126 void wait()
127 {
129 // Select the current SubBarrier
131 ++curBarrier.m_waitingCount;
132 if (curBarrier.m_waitingCount == m_threshold)
133 {
134 // reset the sub barrier so it can be reused
135 curBarrier.m_waitingCount = 0;
136 // swap current barriers
138 // now wake up all the threads that were stopped
139 curBarrier.m_cond.notifyAll();
140 }
141 else
142 {
143 // because of spurious wake-ups we need to put this in a loop.
144 // we need to wait until the count is 0, which will only happen
145 // once m_threshold threads have called wait()
146 while (curBarrier.m_waitingCount != 0)
147 {
148 curBarrier.m_cond.wait(l);
149 }
150 }
151 }
152private:
161};
162
163#endif
164
167 : m_impl(new ThreadBarrierImpl(threshold))
168{
169 BLOCXX_ASSERT(threshold != 0);
170}
173{
174 m_impl->wait();
175}
187{
188 m_impl = x.m_impl;
189 return *this;
190}
191
192} // end namespace BLOCXX_NAMESPACE
193
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(),...
Definition Assertion.hpp:57
#define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME)
Define a new exception class named <NAME>Exception that derives from Exception.
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
ProcessImplRef m_impl
Definition Process.cpp:317
The Condition class represents a synchronization device that allows threads to suspend execution and ...
Definition Condition.hpp:63
void wait(NonRecursiveMutexLock &lock)
Atomically unlock a given mutex and wait for the this Condition object to get signalled.
void notifyAll()
Signal all threads that are currently waiting on the Condition object.
Note that descriptions of what exceptions may be thrown assumes that object is used correctly,...
Note that descriptions of what exceptions may be thrown assumes that object is used correctly,...
The ThreadBarrier class is used to synchronize threads.
ThreadBarrier & operator=(const ThreadBarrier &x)
IntrusiveReference< ThreadBarrierImpl > m_impl
ThreadBarrier(UInt32 threshold)
Constructor.
void wait()
Synchronize participating threads at the barrier.
UInt32 m_threshold
The number of threads to synchronize.
int m_curSubBarrier
Either 0 or 1, depending on whether we are the first generation of waiters or the next generation of ...
Taken from RFC 1321.
This code is inspired by ACE, by Douglas C.
Condition m_cond
Condition for threads to wait on.
UInt32 m_waitingCount
The number of waiting threads.