AGX Dynamics 2.41.3.2
Loading...
Searching...
No Matches
ThreadSynchronization.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#ifndef AGX_THREADSYNCHRONIZATION_H
18#define AGX_THREADSYNCHRONIZATION_H
19
22
23#include <agx/agx.h>
24#include <agx/debug.h>
25#include <agx/SpinMutex.h>
26#include <agx/AtomicValue.h>
27
28#include <agxData/Type.h>
29
30#include <chrono>
31#include <mutex>
32#include <condition_variable>
33
34#if AGX_USE_SSE()
35#include <xmmintrin.h>
36#include <emmintrin.h>
37#endif
38
39#ifndef _MSC_VER
40#include <errno.h>
41#endif
42
43#ifdef _MSC_VER
44# pragma warning(push)
45# pragma warning( disable : 4275 ) // warning C4275: non dll-interface class
46# pragma warning( disable : 4702) // warning C4702: unreachable code
47#endif
48
52#define AGX_MEASURE_LOCK_TIME 0
53
54namespace agx
55{
56
57 using Mutex = std::mutex;
58 using ReentrantMutex = std::recursive_mutex;
59 using Condition = std::condition_variable;
60
61
62
63 //----------------------------------------------------------------------------------
64
69 {
70 public:
71
72 Barrier( int numThreads );
73
74 void block(); // Use numThreads from constructor
75
76 void block(int numThreads); // Override numThreads to wait for
77
78 Barrier( const Barrier& ) = delete;
79 Barrier& operator=(const Barrier& other) = delete;
80
81 private:
82 std::mutex m_mutex;
83 std::condition_variable m_condition;
84
85 int m_wave;
86 int m_numWaiting;
87 int m_barrierCount;
88 };
89
90 //----------------------------------------------------------------------------------
91
92
97 {
98 public:
99
101 Block();
102
104 Block(const Block&) = delete;
105
107 Block& operator=( const Block& other ) = delete;
108
112 void block();
113
119 bool block(unsigned long timeout_ms);
120
124 void release();
125
129 void reset();
130
131
132 protected:
133 private:
134 std::mutex m_mutex;
135 std::condition_variable m_condition;
136 bool m_released;
137 };
138
139
140
141
155
156 public:
161
162 // No copy-constructor
164
166
173
178
182 void lock();
183
187 void unlock();
188
189 private:
190 unsigned int m_numReaders;
191 unsigned int m_numWriters;
192
193 agx::Mutex m_mutex;
194 agx::Condition m_rwCond;
195 };
196
197
198
199
200
201 //----------------------------------------------------------------------------------
202
203 inline Barrier::Barrier(int numThreads)
204 : m_mutex(), m_condition(), m_wave(0), m_numWaiting(0), m_barrierCount( numThreads )
205 {
206 }
207
209 {
210 this->block(0);
211 }
212
213 AGX_FORCE_INLINE void Barrier::block(int numThreads)
214 {
215 #if AGX_DEBUG_SYNCHRONIZATION_OVERHEAD_TESTING()
216 return;
217 #endif
218
219 #if AGX_MEASURE_LOCK_TIME
221 thread->startWaitTimer();
222 #endif
223
224
225 std::unique_lock<std::mutex> lock(m_mutex);
226
227 int wave = m_wave;
228
229 if ( numThreads != 0 )
230 m_barrierCount = numThreads;
231
232 if ( ++m_numWaiting == m_barrierCount ) {
233 // Last one here.
234
235 // Prepare for next barrier use
236 m_numWaiting = 0;
237 m_wave = 1 - wave;
238 m_condition.notify_all();
239 }
240 else {
241 m_condition.wait( lock, [this,wave](){ return m_wave != wave; } );
242 }
243
244
245 #if AGX_MEASURE_LOCK_TIME
246 thread->stopWaitTimer();
247 #endif
248 }
249
250 //----------------------------------------------------------------------------------
251
252 inline Block::Block() :
253 m_mutex(), m_condition(), m_released( false )
254 {
255 }
256
258 {
259 #if AGX_DEBUG_SYNCHRONIZATION_OVERHEAD_TESTING()
260 return;
261 #endif
262
263 #if AGX_MEASURE_LOCK_TIME
265 thread->startWaitTimer();
266 #endif
267
268 std::unique_lock<std::mutex> lock( m_mutex );
269 m_condition.wait( lock, [this]{return m_released;} );
270
271
272 #if AGX_MEASURE_LOCK_TIME
273 thread->stopWaitTimer();
274 #endif
275 }
276
277
278 AGX_FORCE_INLINE bool Block::block(unsigned long timeout_ms)
279 {
280 #if AGX_DEBUG_SYNCHRONIZATION_OVERHEAD_TESTING()
281 return true;
282 #endif
283
284 #if AGX_MEASURE_LOCK_TIME
286 thread->startWaitTimer();
287 #endif
288
289 std::unique_lock<std::mutex> lock(m_mutex);
290 bool status = m_condition.wait_for( lock, std::chrono::milliseconds( timeout_ms ), [this]{return m_released;} );
291
292 // done waiting == true
293 // timeout == false
294
295 #if AGX_MEASURE_LOCK_TIME
296 thread->stopWaitTimer();
297 #endif
298
299 return status;
300 }
301
302
304 {
305 #if AGX_DEBUG_SYNCHRONIZATION_OVERHEAD_TESTING()
306 return;
307 #endif
308
309 std::lock_guard<std::mutex> lock(m_mutex);
310
311 if ( !m_released ) {
312 m_released = true;
313 m_condition.notify_all();
314 }
315 }
316
318 {
319 #if AGX_DEBUG_SYNCHRONIZATION_OVERHEAD_TESTING()
320 return;
321 #endif
322
323 std::lock_guard<std::mutex> lock(m_mutex);
324
325 m_released = false;
326 }
327
328
329
330}
331
332
333#ifdef _MSC_VER
334# pragma warning(pop)
335#endif
336
337#endif /* AGX_THREADSYNCHRONIZATION_H */
#define AGXCORE_EXPORT
Barrier synchronization primitive.
Barrier(int numThreads)
Barrier(const Barrier &)=delete
Barrier & operator=(const Barrier &other)=delete
Block synchronization primitive.
void reset()
Reset the block.
Block()
Default constructor.
Block(const Block &)=delete
No copy-constructor.
void release()
Release the block.
Block & operator=(const Block &other)=delete
No assignment operator.
void block()
Block until released from another thread.
ReaderWriterLock provides shared access for readers and exclusive access for writers.
ReaderWriterLock(const ReaderWriterLock &)=delete
ReaderWriterLock()
Constructor.
void unlock_shared()
Releases the shared access.
void lock()
Acquire exclusive access.
void unlock()
Relese the exclusive access.
ReaderWriterLock & operator=(const ReaderWriterLock &)=delete
void lock_shared()
Acquire the shared lock.
agx::Thread is a representation of an OS specific implementation of a computational thread.
Definition: Thread.h:200
static Thread * getCurrentThread()
#define AGX_FORCE_INLINE
Definition: macros.h:58
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
std::condition_variable Condition
std::mutex Mutex
Definition: Referenced.h:99
std::recursive_mutex ReentrantMutex
Definition: Object.h:48