/*========================================================================= Program: Visualization Toolkit Module: vtkConditionVariable.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkConditionVariable * @brief mutual exclusion locking class * * vtkConditionVariable allows the locking of variables which are accessed * through different threads. This header file also defines * vtkSimpleConditionVariable which is not a subclass of vtkObject. * * The win32 implementation is based on notes provided by * Douglas C. Schmidt and Irfan Pyarali, * Department of Computer Science, * Washington University, St. Louis, Missouri. * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html */ #ifndef vtkConditionVariable_h #define vtkConditionVariable_h #include "vtkCommonCoreModule.h" // For export macro #include "vtkObject.h" #include "vtkMutexLock.h" // Need for friend access to vtkSimpleMutexLock #if defined(VTK_USE_PTHREADS) #include // Need POSIX thread implementation of mutex (even win32 provides mutexes) typedef pthread_cond_t vtkConditionType; #endif // Typically a top level windows application sets _WIN32_WINNT. If it is not set we set it to // 0x0501 (Windows XP) #ifdef VTK_USE_WIN32_THREADS #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 // 0x0501 means target Windows XP or later #endif #include "vtkWindows.h" // Needed for win32 CRITICAL_SECTION, HANDLE, etc. #endif #ifdef VTK_USE_WIN32_THREADS #if 1 typedef struct { // Number of threads waiting on condition. int WaitingThreadCount; // Lock for WaitingThreadCount CRITICAL_SECTION WaitingThreadCountCritSec; // Semaphore to block threads waiting for the condition to change. vtkWindowsHANDLE Semaphore; // An event used to wake up thread(s) waiting on the semaphore // when pthread_cond_signal or pthread_cond_broadcast is called. vtkWindowsHANDLE DoneWaiting; // Was pthread_cond_broadcast called? size_t WasBroadcast; } pthread_cond_t; typedef pthread_cond_t vtkConditionType; #else // 0 typedef struct { // Number of threads waiting on condition. int WaitingThreadCount; // Lock for WaitingThreadCount CRITICAL_SECTION WaitingThreadCountCritSec; // Number of threads to release when pthread_cond_broadcast() // or pthread_cond_signal() is called. int ReleaseCount; // Used to prevent one thread from decrementing ReleaseCount all // by itself instead of letting others respond. int NotifyCount; // A manual-reset event that's used to block and release waiting threads. vtkWindowsHANDLE Event; } pthread_cond_t; typedef pthread_cond_t vtkConditionType; #endif // 0 #endif // VTK_USE_WIN32_THREADS #ifndef VTK_USE_PTHREADS #ifndef VTK_USE_WIN32_THREADS typedef int vtkConditionType; #endif #endif // Condition variable that is not a vtkObject. class VTKCOMMONCORE_EXPORT vtkSimpleConditionVariable { public: vtkSimpleConditionVariable(); ~vtkSimpleConditionVariable(); static vtkSimpleConditionVariable* New(); void Delete() { delete this; } /** * Wake one thread waiting for the condition to change. */ void Signal(); /** * Wake all threads waiting for the condition to change. */ void Broadcast(); /** * Wait for the condition to change. * Upon entry, the mutex must be locked and the lock held by the calling thread. * Upon exit, the mutex will be locked and held by the calling thread. * Between entry and exit, the mutex will be unlocked and may be held by other threads. * @param mutex The mutex that should be locked on entry and will be locked on exit (but not in between) * @retval Normally, this function returns 0. Should a thread be interrupted by a signal, a non-zero value may be returned. */ int Wait(vtkSimpleMutexLock& mutex); protected: vtkConditionType ConditionVariable; private: vtkSimpleConditionVariable(const vtkSimpleConditionVariable& other) = delete; vtkSimpleConditionVariable& operator=(const vtkSimpleConditionVariable& rhs) = delete; }; class VTKCOMMONCORE_EXPORT vtkConditionVariable : public vtkObject { public: static vtkConditionVariable* New(); vtkTypeMacro(vtkConditionVariable, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Wake one thread waiting for the condition to change. */ void Signal(); /** * Wake all threads waiting for the condition to change. */ void Broadcast(); /** * Wait for the condition to change. * Upon entry, the mutex must be locked and the lock held by the calling thread. * Upon exit, the mutex will be locked and held by the calling thread. * Between entry and exit, the mutex will be unlocked and may be held by other threads. * @param mutex The mutex that should be locked on entry and will be locked on exit (but not in between) * @retval Normally, this function returns 0. Should a thread be interrupted by a signal, a non-zero value may be returned. */ int Wait(vtkMutexLock* mutex); protected: vtkConditionVariable() {} vtkSimpleConditionVariable SimpleConditionVariable; private: vtkConditionVariable(const vtkConditionVariable&) = delete; void operator=(const vtkConditionVariable&) = delete; }; inline void vtkConditionVariable::Signal() { this->SimpleConditionVariable.Signal(); } inline void vtkConditionVariable::Broadcast() { this->SimpleConditionVariable.Broadcast(); } inline int vtkConditionVariable::Wait(vtkMutexLock* lock) { return this->SimpleConditionVariable.Wait(lock->SimpleMutexLock); } #endif // vtkConditionVariable_h