diff --git a/dtool/src/dtoolbase/mutexWin32Impl.h b/dtool/src/dtoolbase/mutexWin32Impl.h index 9b34973b1d..47f31a2e8f 100644 --- a/dtool/src/dtoolbase/mutexWin32Impl.h +++ b/dtool/src/dtoolbase/mutexWin32Impl.h @@ -74,7 +74,6 @@ private: volatile PVOID _lock[2] = {nullptr, nullptr}; friend class ConditionVarWin32Impl; - friend class ConditionVarFullWin32Impl; }; /** diff --git a/panda/src/event/asyncFuture.h b/panda/src/event/asyncFuture.h index c12bccb7d0..27fa1db29c 100644 --- a/panda/src/event/asyncFuture.h +++ b/panda/src/event/asyncFuture.h @@ -22,7 +22,6 @@ class AsyncTaskManager; class AsyncTask; -class ConditionVarFull; /** * This class represents a thread-safe handle to a promised future result of diff --git a/panda/src/pipeline/conditionVar.h b/panda/src/pipeline/conditionVar.h index fe90e22063..47ad3c973d 100644 --- a/panda/src/pipeline/conditionVar.h +++ b/panda/src/pipeline/conditionVar.h @@ -24,11 +24,6 @@ * condition variable can be used to "wake up" a thread when some arbitrary * condition has changed. * - * The ConditionVar class does not support the full semantics of POSIX - * condition variables. In particular, it does not support the broadcast or - * notify_all function. See ConditionVarFull for a more complete (but - * possibly more expensive) API. - * * A condition variable is associated with a single mutex, and several * condition variables may share the same mutex. * @@ -51,10 +46,7 @@ PUBLISHED: // These methods are inherited from the base class. //INLINE void wait(); //INLINE void notify(); - - // The notify_all() method is specifically *not* provided by ConditionVar. - // Use ConditionVarFull if you need to call this method. - void notify_all() = delete; + //INLINE void notify_all(); INLINE Mutex &get_mutex() const; }; diff --git a/panda/src/pipeline/conditionVarDebug.cxx b/panda/src/pipeline/conditionVarDebug.cxx index 30a12695ad..c38bdc6d52 100644 --- a/panda/src/pipeline/conditionVarDebug.cxx +++ b/panda/src/pipeline/conditionVarDebug.cxx @@ -78,8 +78,7 @@ wait() { << *current_thread << " waiting on " << *this << "\n"; } - nassertd(current_thread->_waiting_on_cvar == nullptr && - current_thread->_waiting_on_cvar_full == nullptr) { + nassertd(current_thread->_waiting_on_cvar == nullptr) { } current_thread->_waiting_on_cvar = this; @@ -128,8 +127,7 @@ wait(double timeout) { << ", with timeout " << timeout << "\n"; } - nassertd(current_thread->_waiting_on_cvar == nullptr && - current_thread->_waiting_on_cvar_full == nullptr) { + nassertd(current_thread->_waiting_on_cvar == nullptr) { } current_thread->_waiting_on_cvar = this; @@ -156,9 +154,6 @@ wait(double timeout) { * predict which one. It is possible that more than one thread will be woken * up. * - * The caller must be holding the mutex associated with the condition variable - * before making this call, which will not release the mutex. - * * If no threads are waiting, this is a no-op: the notify event is lost. */ void ConditionVarDebug:: @@ -187,6 +182,38 @@ notify() { _mutex._global_lock->unlock(); } +/** + * Informs all of the other threads who are currently blocked on wait() that + * the relevant condition has changed. + * + * If no threads are waiting, this is a no-op: the notify event is lost. + */ +void ConditionVarDebug:: +notify_all() { + _mutex._global_lock->lock(); + + /* + if (!_mutex.do_debug_is_locked()) { + Thread *current_thread = Thread::get_current_thread(); + ostringstream ostr; + ostr << *current_thread << " attempted to notify " + << *this << " without holding " << _mutex; + nassert_raise(ostr.str()); + _mutex._global_lock->unlock(); + return; + } + */ + + if (thread_cat->is_spam()) { + Thread *current_thread = Thread::get_current_thread(); + thread_cat.spam() + << *current_thread << " notifying all " << *this << "\n"; + } + + _impl.notify_all(); + _mutex._global_lock->unlock(); +} + /** * This method is declared virtual in ConditionVarDebug, but non-virtual in * ConditionVarDirect. diff --git a/panda/src/pipeline/conditionVarDebug.h b/panda/src/pipeline/conditionVarDebug.h index 85da3fde2e..d7aa8e7ecb 100644 --- a/panda/src/pipeline/conditionVarDebug.h +++ b/panda/src/pipeline/conditionVarDebug.h @@ -43,6 +43,7 @@ PUBLISHED: BLOCKING void wait(); BLOCKING void wait(double timeout); void notify(); + void notify_all(); virtual void output(std::ostream &out) const; private: diff --git a/panda/src/pipeline/conditionVarDirect.I b/panda/src/pipeline/conditionVarDirect.I index bf8e42aea5..3a5074fd65 100644 --- a/panda/src/pipeline/conditionVarDirect.I +++ b/panda/src/pipeline/conditionVarDirect.I @@ -76,9 +76,6 @@ wait(double timeout) { * predict which one. It is possible that more than one thread will be woken * up. * - * The caller must be holding the mutex associated with the condition variable - * before making this call, which will not release the mutex. - * * If no threads are waiting, this is a no-op: the notify event is lost. */ INLINE void ConditionVarDirect:: @@ -86,3 +83,15 @@ notify() { TAU_PROFILE("ConditionVarDirect::notify()", " ", TAU_USER); _impl.notify(); } + +/** + * Informs all of the other threads who are currently blocked on wait() that + * the relevant condition has changed. + * + * If no threads are waiting, this is a no-op: the notify event is lost. + */ +INLINE void ConditionVarDirect:: +notify_all() { + TAU_PROFILE("ConditionVarDirect::notify()", " ", TAU_USER); + _impl.notify_all(); +} diff --git a/panda/src/pipeline/conditionVarDirect.h b/panda/src/pipeline/conditionVarDirect.h index 2a8c9197cb..17ecca68d9 100644 --- a/panda/src/pipeline/conditionVarDirect.h +++ b/panda/src/pipeline/conditionVarDirect.h @@ -43,6 +43,7 @@ PUBLISHED: BLOCKING INLINE void wait(); BLOCKING INLINE void wait(double timeout); INLINE void notify(); + INLINE void notify_all(); void output(std::ostream &out) const; private: diff --git a/panda/src/pipeline/conditionVarFull.I b/panda/src/pipeline/conditionVarFull.I deleted file mode 100644 index b796e7aed2..0000000000 --- a/panda/src/pipeline/conditionVarFull.I +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFull.I - * @author drose - * @date 2006-08-28 - */ - -/** - * You must pass in a Mutex to the condition variable constructor. This mutex - * may be shared by other condition variables, if desired. It is the caller's - * responsibility to ensure the Mutex object does not destruct during the - * lifetime of the condition variable. - */ -INLINE ConditionVarFull:: -ConditionVarFull(Mutex &mutex) : -#ifdef DEBUG_THREADS - ConditionVarFullDebug(mutex) -#else - ConditionVarFullDirect(mutex) -#endif // DEBUG_THREADS -{ -} - -/** - * Returns the mutex associated with this condition variable. - */ -INLINE Mutex &ConditionVarFull:: -get_mutex() const { -#ifdef DEBUG_THREADS - return (Mutex &)ConditionVarFullDebug::get_mutex(); -#else - return (Mutex &)ConditionVarFullDirect::get_mutex(); -#endif // DEBUG_THREADS -} diff --git a/panda/src/pipeline/conditionVarFull.cxx b/panda/src/pipeline/conditionVarFull.cxx deleted file mode 100644 index b5a32d477c..0000000000 --- a/panda/src/pipeline/conditionVarFull.cxx +++ /dev/null @@ -1,14 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFull.cxx - * @author drose - * @date 2006-08-28 - */ - -#include "conditionVarFull.h" diff --git a/panda/src/pipeline/conditionVarFull.h b/panda/src/pipeline/conditionVarFull.h index 37a9af1e11..f7effac224 100644 --- a/panda/src/pipeline/conditionVarFull.h +++ b/panda/src/pipeline/conditionVarFull.h @@ -14,46 +14,8 @@ #ifndef CONDITIONVARFULL_H #define CONDITIONVARFULL_H -#include "pandabase.h" -#include "conditionVarFullDebug.h" -#include "conditionVarFullDirect.h" +#include "conditionVar.h" -/** - * This class implements a condition variable; see ConditionVar for a brief - * introduction to this class. The ConditionVarFull class provides a more - * complete implementation than ConditionVar; in particular, it provides the - * notify_all() method, which is guaranteed to wake up all threads currently - * waiting on the condition (whereas notify() is guaranteed to wake up at - * least one thread, but may or may not wake up all of them). - * - * This class exists because on certain platforms (e.g. Win32), implementing - * notify_all() requires more overhead, so you should use ConditionVar for - * cases when you do not require the notify_all() semantics. - * - * There are still some minor semantics that POSIX condition variables provide - * which this implementation does not. For instance, it is required (not - * optional) that the caller of notify() or notify_all() is holding the - * condition variable's mutex before the call. - * - * This class inherits its implementation either from ConditionVarFullDebug or - * ConditionVarFullDirect, depending on the definition of DEBUG_THREADS. - */ -#ifdef DEBUG_THREADS -class EXPCL_PANDA_PIPELINE ConditionVarFull : public ConditionVarFullDebug -#else -class EXPCL_PANDA_PIPELINE ConditionVarFull : public ConditionVarFullDirect -#endif // DEBUG_THREADS -{ -PUBLISHED: - INLINE explicit ConditionVarFull(Mutex &mutex); - ConditionVarFull(const ConditionVarFull ©) = delete; - ~ConditionVarFull() = default; - - ConditionVarFull &operator = (const ConditionVarFull ©) = delete; - - INLINE Mutex &get_mutex() const; -}; - -#include "conditionVarFull.I" +typedef ConditionVar ConditionVarFull; #endif diff --git a/panda/src/pipeline/conditionVarFullDebug.I b/panda/src/pipeline/conditionVarFullDebug.I deleted file mode 100644 index 5a09f03a3d..0000000000 --- a/panda/src/pipeline/conditionVarFullDebug.I +++ /dev/null @@ -1,20 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullDebug.I - * @author drose - * @date 2006-08-28 - */ - -/** - * Returns the mutex associated with this condition variable. - */ -INLINE MutexDebug &ConditionVarFullDebug:: -get_mutex() const { - return _mutex; -} diff --git a/panda/src/pipeline/conditionVarFullDebug.cxx b/panda/src/pipeline/conditionVarFullDebug.cxx deleted file mode 100644 index 6b8b7feaa7..0000000000 --- a/panda/src/pipeline/conditionVarFullDebug.cxx +++ /dev/null @@ -1,234 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullDebug.cxx - * @author drose - * @date 2006-08-28 - */ - -#include "conditionVarFullDebug.h" -#include "thread.h" -#include "config_pipeline.h" - -#ifdef DEBUG_THREADS - -using std::ostream; -using std::ostringstream; - -/** - * You must pass in a Mutex to the condition variable constructor. This mutex - * may be shared by other condition variables, if desired. It is the caller's - * responsibility to ensure the Mutex object does not destruct during the - * lifetime of the condition variable. - */ -ConditionVarFullDebug:: -ConditionVarFullDebug(MutexDebug &mutex) : - _mutex(mutex), - _impl(*mutex.get_global_lock()) -{ - nassertv(!_mutex._allow_recursion); -} - -/** - * - */ -ConditionVarFullDebug:: -~ConditionVarFullDebug() { -} - -/** - * Waits on the condition. The caller must already be holding the lock - * associated with the condition variable before calling this function. - * - * wait() will release the lock, then go to sleep until some other thread - * calls notify() on this condition variable. At that time at least one - * thread waiting on the same ConditionVarFullDebug will grab the lock again, - * and then return from wait(). - * - * It is possible that wait() will return even if no one has called notify(). - * It is the responsibility of the calling process to verify the condition on - * return from wait, and possibly loop back to wait again if necessary. - * - * Note the semantics of a condition variable: the mutex must be held before - * wait() is called, and it will still be held when wait() returns. However, - * it will be temporarily released during the wait() call itself. - */ -void ConditionVarFullDebug:: -wait() { - _mutex._global_lock->lock(); - - Thread *current_thread = Thread::get_current_thread(); - - if (!_mutex.do_debug_is_locked()) { - ostringstream ostr; - ostr << *current_thread << " attempted to wait on " - << *this << " without holding " << _mutex; - nassert_raise(ostr.str()); - _mutex._global_lock->unlock(); - return; - } - - if (thread_cat->is_spam()) { - thread_cat.spam() - << *current_thread << " waiting on " << *this << "\n"; - } - - nassertd(current_thread->_waiting_on_cvar == nullptr && - current_thread->_waiting_on_cvar_full == nullptr) { - } - current_thread->_waiting_on_cvar_full = this; - - _mutex.do_unlock(); - _impl.wait(); // temporarily releases _global_lock - _mutex.do_lock(current_thread); - - nassertd(current_thread->_waiting_on_cvar_full == this) { - } - current_thread->_waiting_on_cvar_full = nullptr; - - if (thread_cat.is_spam()) { - thread_cat.spam() - << *current_thread << " awake on " << *this << "\n"; - } - - _mutex._global_lock->unlock(); -} - -/** - * Waits on the condition, with a timeout. The function will return when the - * condition variable is notified, or the timeout occurs. There is no way to - * directly tell which happened, and it is possible that neither in fact - * happened (spurious wakeups are possible). - * - * See wait() with no parameters for more. - */ -void ConditionVarFullDebug:: -wait(double timeout) { - _mutex._global_lock->lock(); - - Thread *current_thread = Thread::get_current_thread(); - - if (!_mutex.do_debug_is_locked()) { - ostringstream ostr; - ostr << *current_thread << " attempted to wait on " - << *this << " without holding " << _mutex; - nassert_raise(ostr.str()); - _mutex._global_lock->unlock(); - return; - } - - if (thread_cat.is_spam()) { - thread_cat.spam() - << *current_thread << " waiting on " << *this - << ", with timeout " << timeout << "\n"; - } - - nassertd(current_thread->_waiting_on_cvar == nullptr && - current_thread->_waiting_on_cvar_full == nullptr) { - } - current_thread->_waiting_on_cvar_full = this; - - _mutex.do_unlock(); - _impl.wait(timeout); // temporarily releases _global_lock - _mutex.do_lock(current_thread); - - nassertd(current_thread->_waiting_on_cvar_full == this) { - } - current_thread->_waiting_on_cvar_full = nullptr; - - if (thread_cat.is_spam()) { - thread_cat.spam() - << *current_thread << " awake on " << *this << "\n"; - } - - _mutex._global_lock->unlock(); -} - -/** - * Informs one of the other threads who are currently blocked on wait() that - * the relevant condition has changed. If multiple threads are currently - * waiting, at least one of them will be woken up, although there is no way to - * predict which one. It is possible that more than one thread will be woken - * up. - * - * The caller must be holding the mutex associated with the condition variable - * before making this call, which will not release the mutex. - * - * If no threads are waiting, this is a no-op: the notify event is lost. - */ -void ConditionVarFullDebug:: -notify() { - _mutex._global_lock->lock(); - - /* - if (!_mutex.do_debug_is_locked()) { - Thread *current_thread = Thread::get_current_thread(); - ostringstream ostr; - ostr << *current_thread << " attempted to notify " - << *this << " without holding " << _mutex; - nassert_raise(ostr.str()); - _mutex._global_lock->unlock(); - return; - } - */ - - if (thread_cat->is_spam()) { - Thread *current_thread = Thread::get_current_thread(); - thread_cat.spam() - << *current_thread << " notifying " << *this << "\n"; - } - - _impl.notify(); - _mutex._global_lock->unlock(); -} - -/** - * Informs all of the other threads who are currently blocked on wait() that - * the relevant condition has changed. - * - * The caller must be holding the mutex associated with the condition variable - * before making this call, which will not release the mutex. - * - * If no threads are waiting, this is a no-op: the notify event is lost. - */ -void ConditionVarFullDebug:: -notify_all() { - _mutex._global_lock->lock(); - - /* - if (!_mutex.do_debug_is_locked()) { - Thread *current_thread = Thread::get_current_thread(); - ostringstream ostr; - ostr << *current_thread << " attempted to notify " - << *this << " without holding " << _mutex; - nassert_raise(ostr.str()); - _mutex._global_lock->unlock(); - return; - } - */ - - if (thread_cat->is_spam()) { - Thread *current_thread = Thread::get_current_thread(); - thread_cat.spam() - << *current_thread << " notifying all " << *this << "\n"; - } - - _impl.notify_all(); - _mutex._global_lock->unlock(); -} - -/** - * This method is declared virtual in ConditionVarFullDebug, but non-virtual - * in ConditionVarFullDirect. - */ -void ConditionVarFullDebug:: -output(ostream &out) const { - out << "ConditionVarFull " << (void *)this << " on " << _mutex; -} - -#endif // DEBUG_THREADS diff --git a/panda/src/pipeline/conditionVarFullDebug.h b/panda/src/pipeline/conditionVarFullDebug.h deleted file mode 100644 index cefb27cad7..0000000000 --- a/panda/src/pipeline/conditionVarFullDebug.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullDebug.h - * @author drose - * @date 2006-08-28 - */ - -#ifndef CONDITIONVARFULLDEBUG_H -#define CONDITIONVARFULLDEBUG_H - -#include "pandabase.h" -#include "pmutex.h" -#include "conditionVarImpl.h" - -#ifdef DEBUG_THREADS - -/** - * A condition variable, usually used to communicate information about - * changing state to a thread that is waiting for something to happen. A - * condition variable can be used to "wake up" a thread when some arbitrary - * condition has changed. - * - * A condition variable is associated with a single mutex, and several - * condition variables may share the same mutex. - */ -class EXPCL_PANDA_PIPELINE ConditionVarFullDebug { -public: - explicit ConditionVarFullDebug(MutexDebug &mutex); - ConditionVarFullDebug(const ConditionVarFullDebug ©) = delete; - virtual ~ConditionVarFullDebug(); - - ConditionVarFullDebug &operator = (const ConditionVarFullDebug ©) = delete; - -PUBLISHED: - INLINE MutexDebug &get_mutex() const; - - BLOCKING void wait(); - BLOCKING void wait(double timeout); - void notify(); - void notify_all(); - virtual void output(std::ostream &out) const; - -private: - MutexDebug &_mutex; - ConditionVarFullImpl _impl; -}; - -INLINE std::ostream & -operator << (std::ostream &out, const ConditionVarFullDebug &cv) { - cv.output(out); - return out; -} - -#include "conditionVarFullDebug.I" - -#endif // DEBUG_THREADS - -#endif diff --git a/panda/src/pipeline/conditionVarFullDirect.I b/panda/src/pipeline/conditionVarFullDirect.I deleted file mode 100644 index 207cb01538..0000000000 --- a/panda/src/pipeline/conditionVarFullDirect.I +++ /dev/null @@ -1,103 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullDirect.I - * @author drose - * @date 2006-08-28 - */ - -/** - * You must pass in a Mutex to the condition variable constructor. This mutex - * may be shared by other condition variables, if desired. It is the caller's - * responsibility to ensure the Mutex object does not destruct during the - * lifetime of the condition variable. - */ -INLINE ConditionVarFullDirect:: -ConditionVarFullDirect(MutexDirect &mutex) : - _mutex(mutex), - _impl(mutex._impl) -{ -} - -/** - * Returns the mutex associated with this condition variable. - */ -INLINE MutexDirect &ConditionVarFullDirect:: -get_mutex() const { - return _mutex; -} - -/** - * Waits on the condition. The caller must already be holding the lock - * associated with the condition variable before calling this function. - * - * wait() will release the lock, then go to sleep until some other thread - * calls notify() on this condition variable. At that time at least one - * thread waiting on the same ConditionVarFullDirect will grab the lock again, - * and then return from wait(). - * - * It is possible that wait() will return even if no one has called notify(). - * It is the responsibility of the calling process to verify the condition on - * return from wait, and possibly loop back to wait again if necessary. - * - * Note the semantics of a condition variable: the mutex must be held before - * wait() is called, and it will still be held when wait() returns. However, - * it will be temporarily released during the wait() call itself. - */ -INLINE void ConditionVarFullDirect:: -wait() { - TAU_PROFILE("ConditionVarFullDirect::wait()", " ", TAU_USER); - _impl.wait(); -} - -/** - * Waits on the condition, with a timeout. The function will return when the - * condition variable is notified, or the timeout occurs. There is no way to - * directly tell which happened, and it is possible that neither in fact - * happened (spurious wakeups are possible). - * - * See wait() with no parameters for more. - */ -void ConditionVarFullDirect:: -wait(double timeout) { - TAU_PROFILE("ConditionVarFullDirect::wait(double)", " ", TAU_USER); - _impl.wait(timeout); -} - -/** - * Informs one of the other threads who are currently blocked on wait() that - * the relevant condition has changed. If multiple threads are currently - * waiting, at least one of them will be woken up, although there is no way to - * predict which one. It is possible that more than one thread will be woken - * up. - * - * The caller must be holding the mutex associated with the condition variable - * before making this call, which will not release the mutex. - * - * If no threads are waiting, this is a no-op: the notify is lost. - */ -INLINE void ConditionVarFullDirect:: -notify() { - TAU_PROFILE("ConditionVarFullDirect::notify()", " ", TAU_USER); - _impl.notify(); -} - -/** - * Informs all of the other threads who are currently blocked on wait() that - * the relevant condition has changed. - * - * The caller must be holding the mutex associated with the condition variable - * before making this call, which will not release the mutex. - * - * If no threads are waiting, this is a no-op: the notify event is lost. - */ -INLINE void ConditionVarFullDirect:: -notify_all() { - TAU_PROFILE("ConditionVarFullDirect::notify()", " ", TAU_USER); - _impl.notify_all(); -} diff --git a/panda/src/pipeline/conditionVarFullDirect.cxx b/panda/src/pipeline/conditionVarFullDirect.cxx deleted file mode 100644 index 04f9c647ed..0000000000 --- a/panda/src/pipeline/conditionVarFullDirect.cxx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullDirect.cxx - * @author drose - * @date 2006-08-28 - */ - -#include "conditionVarFullDirect.h" - -#ifndef DEBUG_THREADS - -/** - * This method is declared virtual in ConditionVarFullDebug, but non-virtual - * in ConditionVarFullDirect. - */ -void ConditionVarFullDirect:: -output(std::ostream &out) const { - out << "ConditionVarFull " << (void *)this << " on " << _mutex; -} - -#endif // !DEBUG_THREADS diff --git a/panda/src/pipeline/conditionVarFullDirect.h b/panda/src/pipeline/conditionVarFullDirect.h deleted file mode 100644 index 729185501b..0000000000 --- a/panda/src/pipeline/conditionVarFullDirect.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullDirect.h - * @author drose - * @date 2006-08-28 - */ - -#ifndef CONDITIONVARFULLDIRECT_H -#define CONDITIONVARFULLDIRECT_H - -#include "pandabase.h" -#include "mutexDirect.h" -#include "conditionVarImpl.h" - -#ifndef DEBUG_THREADS - -/** - * A condition variable, usually used to communicate information about - * changing state to a thread that is waiting for something to happen. A - * condition variable can be used to "wake up" a thread when some arbitrary - * condition has changed. - * - * A condition variable is associated with a single mutex, and several - * condition variables may share the same mutex. - */ -class EXPCL_PANDA_PIPELINE ConditionVarFullDirect { -public: - INLINE explicit ConditionVarFullDirect(MutexDirect &mutex); - ConditionVarFullDirect(const ConditionVarFullDirect ©) = delete; - ~ConditionVarFullDirect() = default; - - ConditionVarFullDirect &operator = (const ConditionVarFullDirect ©) = delete; - -PUBLISHED: - INLINE MutexDirect &get_mutex() const; - - BLOCKING INLINE void wait(); - BLOCKING INLINE void wait(double timeout); - INLINE void notify(); - INLINE void notify_all(); - void output(std::ostream &out) const; - -private: - MutexDirect &_mutex; - ConditionVarFullImpl _impl; -}; - -INLINE std::ostream & -operator << (std::ostream &out, const ConditionVarFullDirect &cv) { - cv.output(out); - return out; -} - -#include "conditionVarFullDirect.I" - -#endif // !DEBUG_THREADS - -#endif diff --git a/panda/src/pipeline/conditionVarFullWin32Impl.I b/panda/src/pipeline/conditionVarFullWin32Impl.I deleted file mode 100644 index 62e8d04e06..0000000000 --- a/panda/src/pipeline/conditionVarFullWin32Impl.I +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullWin32Impl.I - * @author drose - * @date 2006-08-28 - */ - -/** - * - */ -INLINE ConditionVarFullWin32Impl:: -ConditionVarFullWin32Impl(MutexWin32Impl &mutex) : _mutex(mutex) { -} - -/** - * - */ -INLINE ConditionVarFullWin32Impl:: -~ConditionVarFullWin32Impl() { - // These fields are only set in the Windows XP implementation, when these - // both contain events. - if (_cvar[1] != nullptr) { - CloseHandle(_cvar[1]); - } - if (_cvar[2] != nullptr) { - CloseHandle(_cvar[2]); - } -} - -/** - * - */ -INLINE void ConditionVarFullWin32Impl:: -wait() { - MutexWin32Impl::_funcs._cvar_wait(_cvar, _mutex._lock, INFINITE, 0); -} - -/** - * - */ -INLINE void ConditionVarFullWin32Impl:: -wait(double timeout) { - MutexWin32Impl::_funcs._cvar_wait(_cvar, _mutex._lock, (DWORD)(timeout * 1000.0), 0); -} - -/** - * - */ -INLINE void ConditionVarFullWin32Impl:: -notify() { - MutexWin32Impl::_funcs._cvar_notify_one(_cvar); -} - -/** - * - */ -INLINE void ConditionVarFullWin32Impl:: -notify_all() { - MutexWin32Impl::_funcs._cvar_notify_all(_cvar); -} diff --git a/panda/src/pipeline/conditionVarFullWin32Impl.cxx b/panda/src/pipeline/conditionVarFullWin32Impl.cxx deleted file mode 100644 index 6d664735d6..0000000000 --- a/panda/src/pipeline/conditionVarFullWin32Impl.cxx +++ /dev/null @@ -1,20 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullWin32Impl.cxx - * @author drose - * @date 2006-08-28 - */ - -#include "selectThreadImpl.h" - -#if defined(WIN32_VC) || defined(WIN64_VC) - -#include "conditionVarFullWin32Impl.h" - -#endif // WIN32_VC diff --git a/panda/src/pipeline/conditionVarFullWin32Impl.h b/panda/src/pipeline/conditionVarFullWin32Impl.h deleted file mode 100644 index 5c621412e7..0000000000 --- a/panda/src/pipeline/conditionVarFullWin32Impl.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file conditionVarFullWin32Impl.h - * @author drose - * @date 2006-08-28 - */ - -#ifndef CONDITIONVARFULLWIN32IMPL_H -#define CONDITIONVARFULLWIN32IMPL_H - -#include "pandabase.h" -#include "selectThreadImpl.h" - -#if defined(WIN32_VC) - -#include "mutexWin32Impl.h" -#include "pnotify.h" -#include "atomicAdjust.h" - -class MutexWin32Impl; - -/** - * Uses Windows native calls to implement a conditionVarFull. - * - * We follow the "SetEvent" implementation suggested by - * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html . This allows us to - * implement both notify() and notify_all(), but it has more overhead than the - * simpler implementation of ConditionVarWin32Impl. - * - * As described by the above reference, this implementation suffers from a few - * weaknesses; in particular, it does not necessarily wake up all threads - * fairly; and it may sometimes incorrectly wake up a thread that was not - * waiting at the time notify() was called. But we figure it's good enough - * for our purposes. - */ -class EXPCL_PANDA_PIPELINE ConditionVarFullWin32Impl { -public: - INLINE ConditionVarFullWin32Impl(MutexWin32Impl &mutex); - INLINE ~ConditionVarFullWin32Impl(); - - INLINE void wait(); - INLINE void wait(double timeout); - INLINE void notify(); - INLINE void notify_all(); - -private: - MutexWin32Impl &_mutex; - - // On Windows XP, the first field contains a Signal (auto-reset) event, - // the second field a broadcast (manual reset) event, third a waiter count. - // On Windows Vista and above, the first contains a PCONDITION_VARIABLE. - volatile PVOID _cvar[3] = {nullptr, nullptr, nullptr}; -}; - -#include "conditionVarFullWin32Impl.I" - -#endif // WIN32_VC - -#endif diff --git a/panda/src/pipeline/conditionVarImpl.h b/panda/src/pipeline/conditionVarImpl.h index 7837622ba6..774ab72753 100644 --- a/panda/src/pipeline/conditionVarImpl.h +++ b/panda/src/pipeline/conditionVarImpl.h @@ -21,35 +21,31 @@ #include "conditionVarDummyImpl.h" typedef ConditionVarDummyImpl ConditionVarImpl; -typedef ConditionVarDummyImpl ConditionVarFullImpl; #elif defined(THREAD_SIMPLE_IMPL) #include "conditionVarSimpleImpl.h" typedef ConditionVarSimpleImpl ConditionVarImpl; -typedef ConditionVarSimpleImpl ConditionVarFullImpl; #elif defined(MUTEX_SPINLOCK) #include "conditionVarSpinlockImpl.h" typedef ConditionVarSpinlockImpl ConditionVarImpl; -typedef ConditionVarSpinlockImpl ConditionVarFullImpl; #elif defined(THREAD_WIN32_IMPL) #include "conditionVarWin32Impl.h" -#include "conditionVarFullWin32Impl.h" typedef ConditionVarWin32Impl ConditionVarImpl; -typedef ConditionVarFullWin32Impl ConditionVarFullImpl; #elif defined(THREAD_POSIX_IMPL) #include "conditionVarPosixImpl.h" typedef ConditionVarPosixImpl ConditionVarImpl; -typedef ConditionVarPosixImpl ConditionVarFullImpl; #endif +typedef ConditionVarImpl ConditionVarFullImpl; + #if defined(WIN32_VC) #include "conditionVarWin32Impl.h" typedef ConditionVarWin32Impl TrueConditionVarImpl; diff --git a/panda/src/pipeline/conditionVarWin32Impl.I b/panda/src/pipeline/conditionVarWin32Impl.I index 82ba9dea39..7f2b24a079 100644 --- a/panda/src/pipeline/conditionVarWin32Impl.I +++ b/panda/src/pipeline/conditionVarWin32Impl.I @@ -16,8 +16,6 @@ */ INLINE ConditionVarWin32Impl:: ConditionVarWin32Impl(MutexWin32Impl &mutex) : _mutex(mutex) { - // Create an auto-reset event. - _event_signal = CreateEvent(nullptr, false, false, nullptr); } /** @@ -25,7 +23,14 @@ ConditionVarWin32Impl(MutexWin32Impl &mutex) : _mutex(mutex) { */ INLINE ConditionVarWin32Impl:: ~ConditionVarWin32Impl() { - CloseHandle(_event_signal); + // These fields are only set in the Windows XP implementation, when these + // both contain events. + if (_cvar[1] != nullptr) { + CloseHandle(_cvar[1]); + } + if (_cvar[2] != nullptr) { + CloseHandle(_cvar[2]); + } } /** @@ -33,12 +38,7 @@ INLINE ConditionVarWin32Impl:: */ INLINE void ConditionVarWin32Impl:: wait() { - _mutex.unlock(); - - DWORD result = WaitForSingleObject(_event_signal, INFINITE); - nassertv(result == WAIT_OBJECT_0); - - _mutex.lock(); + MutexWin32Impl::_funcs._cvar_wait(_cvar, _mutex._lock, INFINITE, 0); } /** @@ -46,12 +46,7 @@ wait() { */ INLINE void ConditionVarWin32Impl:: wait(double timeout) { - _mutex.unlock(); - - DWORD result = WaitForSingleObject(_event_signal, (DWORD)(timeout * 1000.0)); - nassertv(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT); - - _mutex.lock(); + MutexWin32Impl::_funcs._cvar_wait(_cvar, _mutex._lock, (DWORD)(timeout * 1000.0), 0); } /** @@ -59,5 +54,13 @@ wait(double timeout) { */ INLINE void ConditionVarWin32Impl:: notify() { - SetEvent(_event_signal); + MutexWin32Impl::_funcs._cvar_notify_one(_cvar); +} + +/** + * + */ +INLINE void ConditionVarWin32Impl:: +notify_all() { + MutexWin32Impl::_funcs._cvar_notify_all(_cvar); } diff --git a/panda/src/pipeline/conditionVarWin32Impl.h b/panda/src/pipeline/conditionVarWin32Impl.h index a0c4d882c7..213cacdf9e 100644 --- a/panda/src/pipeline/conditionVarWin32Impl.h +++ b/panda/src/pipeline/conditionVarWin32Impl.h @@ -25,14 +25,19 @@ class MutexWin32Impl; /** - * Uses Windows native calls to implement a conditionVar. + * Uses Windows native calls to implement a ConditionVar. * - * The Windows native synchronization primitives don't actually implement a - * full POSIX-style condition variable, but the Event primitive does a fair - * job if we disallow notify_all() (POSIX broadcast). See - * ConditionVarFullWin32Impl for a full implementation that includes - * notify_all(). This class is much simpler than that full implementation, so - * we can avoid the overhead required to support broadcast. + * On Windows Vista and above, we use the system's native condition variables. + * + * On Windows XP, we follow the "SetEvent" implementation suggested by + * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html . This allows us to + * implement both notify() and notify_all(). + * + * As described by the above reference, this implementation suffers from a few + * weaknesses; in particular, it does not necessarily wake up all threads + * fairly; and it may sometimes incorrectly wake up a thread that was not + * waiting at the time notify() was called. But we figure it's good enough + * for our purposes. */ class EXPCL_PANDA_PIPELINE ConditionVarWin32Impl { public: @@ -42,10 +47,15 @@ public: INLINE void wait(); INLINE void wait(double timeout); INLINE void notify(); + INLINE void notify_all(); private: MutexWin32Impl &_mutex; - HANDLE _event_signal; + + // On Windows XP, the first field contains a Signal (auto-reset) event, + // the second field a broadcast (manual reset) event, third a waiter count. + // On Windows Vista and above, the first contains a PCONDITION_VARIABLE. + volatile PVOID _cvar[3] = {nullptr, nullptr, nullptr}; }; #include "conditionVarWin32Impl.I" diff --git a/panda/src/pipeline/mutexDebug.h b/panda/src/pipeline/mutexDebug.h index 094f2eafc6..298fd9f7ca 100644 --- a/panda/src/pipeline/mutexDebug.h +++ b/panda/src/pipeline/mutexDebug.h @@ -83,7 +83,6 @@ private: static MutexTrueImpl *_global_lock; friend class ConditionVarDebug; - friend class ConditionVarFullDebug; }; INLINE std::ostream & diff --git a/panda/src/pipeline/mutexDirect.h b/panda/src/pipeline/mutexDirect.h index 068f5fc5c4..9e578abd52 100644 --- a/panda/src/pipeline/mutexDirect.h +++ b/panda/src/pipeline/mutexDirect.h @@ -57,7 +57,6 @@ private: mutable MutexTrueImpl _impl; friend class ConditionVarDirect; - friend class ConditionVarFullDirect; }; INLINE std::ostream & diff --git a/panda/src/pipeline/p3pipeline_composite1.cxx b/panda/src/pipeline/p3pipeline_composite1.cxx index 487c5ca0ad..5a9e929283 100644 --- a/panda/src/pipeline/p3pipeline_composite1.cxx +++ b/panda/src/pipeline/p3pipeline_composite1.cxx @@ -2,9 +2,6 @@ #include "conditionVarDebug.cxx" #include "conditionVarDirect.cxx" #include "conditionVarDummyImpl.cxx" -#include "conditionVarFull.cxx" -#include "conditionVarFullDebug.cxx" -#include "conditionVarFullDirect.cxx" #include "conditionVarPosixImpl.cxx" #include "conditionVarWin32Impl.cxx" #include "conditionVarSimpleImpl.cxx" diff --git a/panda/src/pipeline/thread.cxx b/panda/src/pipeline/thread.cxx index 80c32fa7f5..81152a8095 100644 --- a/panda/src/pipeline/thread.cxx +++ b/panda/src/pipeline/thread.cxx @@ -17,7 +17,6 @@ #include "config_pipeline.h" #include "mutexDebug.h" #include "conditionVarDebug.h" -#include "conditionVarFullDebug.h" Thread *Thread::_main_thread; Thread *Thread::_external_thread; @@ -52,7 +51,6 @@ Thread(const std::string &name, const std::string &sync_name) : #ifdef DEBUG_THREADS _blocked_on_mutex = nullptr; _waiting_on_cvar = nullptr; - _waiting_on_cvar_full = nullptr; #endif } @@ -63,8 +61,7 @@ Thread:: ~Thread() { #ifdef DEBUG_THREADS nassertv(_blocked_on_mutex == nullptr && - _waiting_on_cvar == nullptr && - _waiting_on_cvar_full == nullptr); + _waiting_on_cvar == nullptr); #endif } @@ -145,8 +142,6 @@ output_blocker(std::ostream &out) const { _blocked_on_mutex->output_with_holder(out); } else if (_waiting_on_cvar != nullptr) { out << *_waiting_on_cvar; - } else if (_waiting_on_cvar_full != nullptr) { - out << *_waiting_on_cvar_full; } #endif // DEBUG_THREADS } diff --git a/panda/src/pipeline/thread.h b/panda/src/pipeline/thread.h index 69b878725a..159b93c9df 100644 --- a/panda/src/pipeline/thread.h +++ b/panda/src/pipeline/thread.h @@ -31,7 +31,6 @@ class Mutex; class ReMutex; class MutexDebug; class ConditionVarDebug; -class ConditionVarFullDebug; class AsyncTask; /** @@ -156,7 +155,6 @@ private: #ifdef DEBUG_THREADS MutexDebug *_blocked_on_mutex; ConditionVarDebug *_waiting_on_cvar; - ConditionVarFullDebug *_waiting_on_cvar_full; #endif // DEBUG_THREADS private: @@ -184,7 +182,6 @@ private: friend class MutexDebug; friend class ConditionVarDebug; - friend class ConditionVarFullDebug; friend class ThreadDummyImpl; friend class ThreadWin32Impl;