ConditionVarFull
This commit is contained in:
parent
ce3ed75e1a
commit
01a09a9d28
|
|
@ -42,6 +42,7 @@ public:
|
|||
private:
|
||||
CRITICAL_SECTION _lock;
|
||||
friend class ConditionVarWin32Impl;
|
||||
friend class ConditionVarFullWin32Impl;
|
||||
};
|
||||
|
||||
#include "mutexWin32Impl.I"
|
||||
|
|
|
|||
|
|
@ -14,9 +14,12 @@
|
|||
conditionVarDebug.h conditionVarDebug.I \
|
||||
conditionVarDirect.h conditionVarDirect.I \
|
||||
conditionVarDummyImpl.h conditionVarDummyImpl.I \
|
||||
conditionVarFull.h conditionVarFull.I \
|
||||
conditionVarFullDebug.h conditionVarFullDebug.I \
|
||||
conditionVarFullDirect.h conditionVarFullDirect.I \
|
||||
conditionVarFullWin32Impl.h conditionVarFullWin32Impl.I \
|
||||
conditionVarImpl.h \
|
||||
conditionVarNsprImpl.h conditionVarNsprImpl.I \
|
||||
conditionVarLinuxImpl.h conditionVarLinuxImpl.I \
|
||||
conditionVarPosixImpl.h conditionVarPosixImpl.I \
|
||||
conditionVarWin32Impl.h conditionVarWin32Impl.I \
|
||||
conditionVarSpinlockImpl.h conditionVarSpinlockImpl.I \
|
||||
|
|
@ -47,7 +50,6 @@
|
|||
reMutexHolder.I reMutexHolder.h \
|
||||
threadDummyImpl.h threadDummyImpl.I thread.h thread.I threadImpl.h \
|
||||
threadNsprImpl.h threadNsprImpl.I \
|
||||
threadLinuxImpl.h threadLinuxImpl.I \
|
||||
threadPosixImpl.h threadPosixImpl.I \
|
||||
threadWin32Impl.h threadWin32Impl.I \
|
||||
threadPriority.h
|
||||
|
|
@ -57,8 +59,11 @@
|
|||
conditionVarDebug.cxx \
|
||||
conditionVarDirect.cxx \
|
||||
conditionVarDummyImpl.cxx \
|
||||
conditionVarFull.cxx \
|
||||
conditionVarFullDebug.cxx \
|
||||
conditionVarFullDirect.cxx \
|
||||
conditionVarFullWin32Impl.cxx \
|
||||
conditionVarNsprImpl.cxx \
|
||||
conditionVarLinuxImpl.cxx \
|
||||
conditionVarPosixImpl.cxx \
|
||||
conditionVarWin32Impl.cxx \
|
||||
conditionVarSpinlockImpl.cxx \
|
||||
|
|
@ -87,7 +92,6 @@
|
|||
reMutexHolder.cxx \
|
||||
thread.cxx threadDummyImpl.cxx \
|
||||
threadNsprImpl.cxx \
|
||||
threadLinuxImpl.cxx \
|
||||
threadPosixImpl.cxx \
|
||||
threadWin32Impl.cxx
|
||||
|
||||
|
|
@ -96,9 +100,12 @@
|
|||
conditionVarDebug.h conditionVarDebug.I \
|
||||
conditionVarDirect.h conditionVarDirect.I \
|
||||
conditionVarDummyImpl.h conditionVarDummyImpl.I \
|
||||
conditionVarFull.h conditionVarFull.I \
|
||||
conditionVarFullDebug.h conditionVarFullDebug.I \
|
||||
conditionVarFullDirect.h conditionVarFullDirect.I \
|
||||
conditionVarFullWin32Impl.h conditionVarFullWin32Impl.I \
|
||||
conditionVarImpl.h \
|
||||
conditionVarNsprImpl.h conditionVarNsprImpl.I \
|
||||
conditionVarLinuxImpl.h conditionVarLinuxImpl.I \
|
||||
conditionVarPosixImpl.h conditionVarPosixImpl.I \
|
||||
conditionVarWin32Impl.h conditionVarWin32Impl.I \
|
||||
conditionVarSpinlockImpl.h conditionVarSpinlockImpl.I \
|
||||
|
|
@ -129,7 +136,6 @@
|
|||
reMutexHolder.I reMutexHolder.h \
|
||||
threadDummyImpl.h threadDummyImpl.I thread.h thread.I threadImpl.h \
|
||||
threadNsprImpl.h threadNsprImpl.I \
|
||||
threadLinuxImpl.h threadLinuxImpl.I \
|
||||
threadPosixImpl.h threadPosixImpl.I \
|
||||
threadWin32Impl.h threadWin32Impl.I \
|
||||
threadPriority.h
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@
|
|||
// waiting for something to happen. A 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
|
||||
// signal_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
|
||||
|
|
|
|||
|
|
@ -111,7 +111,8 @@ wait() {
|
|||
// 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.
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ wait() {
|
|||
// 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.
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
// Filename: conditionVarFull.I
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFull::Constructor
|
||||
// Access: Public
|
||||
// Description: 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
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFull::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarFull::
|
||||
~ConditionVarFull() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFull::Copy Constructor
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy condition variables.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarFull::
|
||||
ConditionVarFull(const ConditionVarFull ©) :
|
||||
#ifdef DEBUG_THREADS
|
||||
ConditionVarFullDebug(copy.get_mutex())
|
||||
#else
|
||||
ConditionVarFullDirect(copy.get_mutex())
|
||||
#endif // DEBUG_THREADS
|
||||
{
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFull::Copy Assignment Operator
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy condition variables.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFull::
|
||||
operator = (const ConditionVarFull ©) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFull::get_mutex
|
||||
// Access: Public
|
||||
// Description: 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
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: conditionVarFull.cxx
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "conditionVarFull.h"
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// Filename: conditionVarFull.h
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONDITIONVARFULL_H
|
||||
#define CONDITIONVARFULL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "conditionVarFullDebug.h"
|
||||
#include "conditionVarFullDirect.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ConditionVarFull
|
||||
// Description : 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 signal_all() method, which is guaranteed
|
||||
// to wake up all threads currently waiting on the
|
||||
// condition (whereas signal() 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 signal_all() requires more
|
||||
// overhead, so you should use ConditionVar for cases
|
||||
// when you do not require the signal_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 signal() or signal_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 ConditionVarFull : public ConditionVarFullDebug
|
||||
#else
|
||||
class EXPCL_PANDA ConditionVarFull : public ConditionVarFullDirect
|
||||
#endif // DEBUG_THREADS
|
||||
{
|
||||
public:
|
||||
INLINE ConditionVarFull(Mutex &mutex);
|
||||
INLINE ~ConditionVarFull();
|
||||
private:
|
||||
INLINE ConditionVarFull(const ConditionVarFull ©);
|
||||
INLINE void operator = (const ConditionVarFull ©);
|
||||
|
||||
public:
|
||||
INLINE Mutex &get_mutex() const;
|
||||
};
|
||||
|
||||
#include "conditionVarFull.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Filename: threadLinuxImpl.I
|
||||
// Created by: drose (28Mar06)
|
||||
// Filename: conditionVarFullDebug.I
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
@ -18,49 +18,35 @@
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Function: ConditionVarFullDebug::Copy Constructor
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy condition variables.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ThreadLinuxImpl::
|
||||
ThreadLinuxImpl(Thread *parent_obj) :
|
||||
_cv(_mutex),
|
||||
_parent_obj(parent_obj)
|
||||
INLINE ConditionVarFullDebug::
|
||||
ConditionVarFullDebug(const ConditionVarFullDebug ©) :
|
||||
_mutex(copy._mutex),
|
||||
_impl(*_mutex._global_lock)
|
||||
{
|
||||
_thread = 0;
|
||||
_joinable = false;
|
||||
_status = S_new;
|
||||
_stack = NULL;
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::prepare_for_exit
|
||||
// Function: ConditionVarFullDebug::Copy Assignment Operator
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy condition variables.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFullDebug::
|
||||
operator = (const ConditionVarFullDebug ©) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDebug::get_mutex
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Returns the mutex associated with this condition
|
||||
// variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ThreadLinuxImpl::
|
||||
prepare_for_exit() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::is_threading_supported
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ThreadLinuxImpl::
|
||||
is_threading_supported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::sleep
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ThreadLinuxImpl::
|
||||
sleep(double seconds) {
|
||||
struct timespec rqtp;
|
||||
rqtp.tv_sec = time_t(seconds);
|
||||
rqtp.tv_nsec = long((seconds - (double)rqtp.tv_sec) * 1000000000.0);
|
||||
nanosleep(&rqtp, NULL);
|
||||
INLINE MutexDebug &ConditionVarFullDebug::
|
||||
get_mutex() const {
|
||||
return _mutex;
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
// Filename: conditionVarFullDebug.cxx
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "conditionVarFullDebug.h"
|
||||
#include "thread.h"
|
||||
#include "config_pipeline.h"
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDebug::Constructor
|
||||
// Access: Public
|
||||
// Description: 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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDebug::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ConditionVarFullDebug::
|
||||
~ConditionVarFullDebug() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDebug::wait
|
||||
// Access: Public
|
||||
// Description: 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 signal() 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 signal(). 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();
|
||||
|
||||
if (!_mutex.do_debug_is_locked()) {
|
||||
ostringstream ostr;
|
||||
ostr << *Thread::get_current_thread() << " attempted to wait on "
|
||||
<< *this << " without holding " << _mutex;
|
||||
nassert_raise(ostr.str());
|
||||
_mutex._global_lock->release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread_cat.is_spam()) {
|
||||
thread_cat.spam()
|
||||
<< *Thread::get_current_thread() << " waiting on " << *this << "\n";
|
||||
}
|
||||
|
||||
_mutex.do_release();
|
||||
_impl.wait();
|
||||
_mutex.do_lock();
|
||||
|
||||
if (thread_cat.is_spam()) {
|
||||
thread_cat.spam()
|
||||
<< *Thread::get_current_thread() << " awake on " << *this << "\n";
|
||||
}
|
||||
|
||||
_mutex._global_lock->release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDebug::signal
|
||||
// Access: Public
|
||||
// Description: 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
|
||||
// signal is lost.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ConditionVarFullDebug::
|
||||
signal() {
|
||||
_mutex._global_lock->lock();
|
||||
if (!_mutex.do_debug_is_locked()) {
|
||||
ostringstream ostr;
|
||||
ostr << *Thread::get_current_thread() << " attempted to signal "
|
||||
<< *this << " without holding " << _mutex;
|
||||
nassert_raise(ostr.str());
|
||||
_mutex._global_lock->release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread_cat.is_spam()) {
|
||||
thread_cat.spam()
|
||||
<< *Thread::get_current_thread() << " signalling " << *this << "\n";
|
||||
}
|
||||
|
||||
_impl.signal();
|
||||
_mutex._global_lock->release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDebug::signal
|
||||
// Access: Public
|
||||
// Description: 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
|
||||
// signal is lost.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ConditionVarFullDebug::
|
||||
signal_all() {
|
||||
_mutex._global_lock->lock();
|
||||
if (!_mutex.do_debug_is_locked()) {
|
||||
ostringstream ostr;
|
||||
ostr << *Thread::get_current_thread() << " attempted to signal "
|
||||
<< *this << " without holding " << _mutex;
|
||||
nassert_raise(ostr.str());
|
||||
_mutex._global_lock->release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread_cat.is_spam()) {
|
||||
thread_cat.spam()
|
||||
<< *Thread::get_current_thread() << " signalling all " << *this << "\n";
|
||||
}
|
||||
|
||||
_impl.signal_all();
|
||||
_mutex._global_lock->release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDebug::output
|
||||
// Access: Public, Virtual
|
||||
// Description: 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
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Filename: conditionVarFullDebug.h
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONDITIONVARFULLDEBUG_H
|
||||
#define CONDITIONVARFULLDEBUG_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pmutex.h"
|
||||
#include "conditionVarImpl.h"
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ConditionVarFullDebug
|
||||
// Description : 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 ConditionVarFullDebug {
|
||||
public:
|
||||
ConditionVarFullDebug(MutexDebug &mutex);
|
||||
virtual ~ConditionVarFullDebug();
|
||||
private:
|
||||
INLINE ConditionVarFullDebug(const ConditionVarFullDebug ©);
|
||||
INLINE void operator = (const ConditionVarFullDebug ©);
|
||||
|
||||
public:
|
||||
INLINE MutexDebug &get_mutex() const;
|
||||
|
||||
void wait();
|
||||
void signal();
|
||||
void signal_all();
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
MutexDebug &_mutex;
|
||||
ConditionVarFullImpl _impl;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const ConditionVarFullDebug &cv) {
|
||||
cv.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "conditionVarFullDebug.I"
|
||||
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
// Filename: conditionVarFullDirect.I
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::Constructor
|
||||
// Access: Public
|
||||
// Description: 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)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarFullDirect::
|
||||
~ConditionVarFullDirect() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::Copy Constructor
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy condition variables.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarFullDirect::
|
||||
ConditionVarFullDirect(const ConditionVarFullDirect ©) :
|
||||
_mutex(copy._mutex),
|
||||
_impl(_mutex._impl)
|
||||
{
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::Copy Assignment Operator
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy condition variables.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFullDirect::
|
||||
operator = (const ConditionVarFullDirect ©) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::get_mutex
|
||||
// Access: Public
|
||||
// Description: Returns the mutex associated with this condition
|
||||
// variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MutexDirect &ConditionVarFullDirect::
|
||||
get_mutex() const {
|
||||
return _mutex;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::wait
|
||||
// Access: Public
|
||||
// Description: 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 signal() 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 signal(). 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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::signal
|
||||
// Access: Public
|
||||
// Description: 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
|
||||
// signal is lost.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFullDirect::
|
||||
signal() {
|
||||
TAU_PROFILE("ConditionVarFullDirect::signal()", " ", TAU_USER);
|
||||
_impl.signal();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullDirect::signal_all
|
||||
// Access: Public
|
||||
// Description: 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
|
||||
// signal is lost.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFullDirect::
|
||||
signal_all() {
|
||||
TAU_PROFILE("ConditionVarFullDirect::signal()", " ", TAU_USER);
|
||||
_impl.signal_all();
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Filename: conditionVarLinuxImpl.I
|
||||
// Created by: drose (28Mar06)
|
||||
// Filename: conditionVarFullDirect.cxx
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
@ -16,24 +16,19 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "conditionVarFullDirect.h"
|
||||
|
||||
#ifndef DEBUG_THREADS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarLinuxImpl::Constructor
|
||||
// Function: ConditionVarFullDirect::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: This method is declared virtual in ConditionVarFullDebug,
|
||||
// but non-virtual in ConditionVarFullDirect.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarLinuxImpl::
|
||||
ConditionVarLinuxImpl(MutexLinuxImpl &mutex) :
|
||||
_mutex(mutex)
|
||||
{
|
||||
_counter = 0;
|
||||
void ConditionVarFullDirect::
|
||||
output(ostream &out) const {
|
||||
out << "ConditionVarFull " << (void *)this << " on " << _mutex;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarLinuxImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarLinuxImpl::
|
||||
~ConditionVarLinuxImpl() {
|
||||
}
|
||||
#endif // !DEBUG_THREADS
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Filename: conditionVarFullDirect.h
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONDITIONVARFULLDIRECT_H
|
||||
#define CONDITIONVARFULLDIRECT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "mutexDirect.h"
|
||||
#include "conditionVarImpl.h"
|
||||
|
||||
#ifndef DEBUG_THREADS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ConditionVarFullDirect
|
||||
// Description : 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 ConditionVarFullDirect {
|
||||
public:
|
||||
INLINE ConditionVarFullDirect(MutexDirect &mutex);
|
||||
INLINE ~ConditionVarFullDirect();
|
||||
private:
|
||||
INLINE ConditionVarFullDirect(const ConditionVarFullDirect ©);
|
||||
INLINE void operator = (const ConditionVarFullDirect ©);
|
||||
|
||||
public:
|
||||
INLINE MutexDirect &get_mutex() const;
|
||||
|
||||
INLINE void wait();
|
||||
INLINE void signal();
|
||||
INLINE void signal_all();
|
||||
void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
MutexDirect &_mutex;
|
||||
ConditionVarFullImpl _impl;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const ConditionVarFullDirect &cv) {
|
||||
cv.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "conditionVarFullDirect.I"
|
||||
|
||||
#endif // !DEBUG_THREADS
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Filename: conditionVarFullWin32Impl.I
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullWin32Impl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarFullWin32Impl::
|
||||
ConditionVarFullWin32Impl(MutexWin32Impl &mutex) {
|
||||
_external_mutex = &mutex._lock;
|
||||
|
||||
// Create an auto-reset event.
|
||||
_event_signal = CreateEvent(NULL, false, false, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullWin32Impl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarFullWin32Impl::
|
||||
~ConditionVarFullWin32Impl() {
|
||||
CloseHandle(_event_signal);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullWin32Impl::wait
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFullWin32Impl::
|
||||
wait() {
|
||||
LeaveCriticalSection(_external_mutex);
|
||||
|
||||
DWORD result = WaitForSingleObject(_event_signal, INFINITE);
|
||||
nassertv(result == WAIT_OBJECT_0);
|
||||
|
||||
EnterCriticalSection(_external_mutex);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullWin32Impl::signal
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFullWin32Impl::
|
||||
signal() {
|
||||
SetEvent(_event_signal);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarFullWin32Impl::signal_all
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarFullWin32Impl::
|
||||
signal_all() {
|
||||
// TODO.
|
||||
nassertv(false);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Filename: conditionVarFullWin32Impl.cxx
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include "conditionVarFullWin32Impl.h"
|
||||
|
||||
#endif // WIN32_VC
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// Filename: conditionVarFullWin32Impl.h
|
||||
// Created by: drose (28Aug06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONDITIONVARFULLWIN32IMPL_H
|
||||
#define CONDITIONVARFULLWIN32IMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include "mutexWin32Impl.h"
|
||||
#include "pnotify.h"
|
||||
|
||||
class MutexWin32Impl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ConditionVarFullWin32Impl
|
||||
// Description : Uses Windows native calls to implement a
|
||||
// conditionVarFull.
|
||||
//
|
||||
// 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 POSIX broadcast. See
|
||||
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html for
|
||||
// a full implementation that includes broadcast. This
|
||||
// class is much simpler than that full implementation,
|
||||
// so we can avoid the overhead require to support
|
||||
// broadcast.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ConditionVarFullWin32Impl {
|
||||
public:
|
||||
INLINE ConditionVarFullWin32Impl(MutexWin32Impl &mutex);
|
||||
INLINE ~ConditionVarFullWin32Impl();
|
||||
|
||||
INLINE void wait();
|
||||
INLINE void signal();
|
||||
INLINE void signal_all();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION *_external_mutex;
|
||||
HANDLE _event_signal;
|
||||
};
|
||||
|
||||
#include "conditionVarFullWin32Impl.I"
|
||||
|
||||
#endif // WIN32_VC
|
||||
|
||||
#endif
|
||||
|
|
@ -26,31 +26,32 @@
|
|||
|
||||
#include "conditionVarDummyImpl.h"
|
||||
typedef ConditionVarDummyImpl ConditionVarImpl;
|
||||
typedef ConditionVarDummyImpl 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;
|
||||
|
||||
#elif defined(THREAD_LINUX_IMPL)
|
||||
|
||||
#include "conditionVarLinuxImpl.h"
|
||||
typedef ConditionVarLinuxImpl ConditionVarImpl;
|
||||
typedef ConditionVarFullWin32Impl ConditionVarFullImpl;
|
||||
|
||||
#elif defined(THREAD_POSIX_IMPL)
|
||||
|
||||
#include "conditionVarPosixImpl.h"
|
||||
typedef ConditionVarPosixImpl ConditionVarImpl;
|
||||
typedef ConditionVarPosixImpl ConditionVarFullImpl;
|
||||
|
||||
#elif defined(THREAD_NSPR_IMPL)
|
||||
|
||||
#include "conditionVarNsprImpl.h"
|
||||
typedef ConditionVarNsprImpl ConditionVarImpl;
|
||||
typedef ConditionVarNsprImpl ConditionVarFullImpl;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
// Filename: conditionVarLinuxImpl.cxx
|
||||
// Created by: drose (28Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#include "conditionVarLinuxImpl.h"
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarLinuxImpl::wait
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ConditionVarLinuxImpl::
|
||||
wait() {
|
||||
// Grab the current value of the counter before we release the
|
||||
// mutex.
|
||||
PN_int32 orig_counter = _counter;
|
||||
_mutex.release();
|
||||
syscall(SYS_futex, &_counter, FUTEX_WAIT, orig_counter, (void *)NULL);
|
||||
_mutex.lock();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarLinuxImpl::signal
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ConditionVarLinuxImpl::
|
||||
signal() {
|
||||
AtomicAdjust::inc(_counter);
|
||||
syscall(SYS_futex, &_counter, FUTEX_WAKE, 1);
|
||||
}
|
||||
|
||||
#endif // HAVE_LINUX_NATIVE_THREADS
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
// Filename: conditionVarLinuxImpl.h
|
||||
// Created by: drose (28Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONDITIONVARLINUXIMPL_H
|
||||
#define CONDITIONVARLINUXIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#include "mutexLinuxImpl.h"
|
||||
#include "pnotify.h"
|
||||
|
||||
class MutexLinuxImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ConditionVarLinuxImpl
|
||||
// Description : Uses Linux threads to implement a conditionVar.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ConditionVarLinuxImpl {
|
||||
public:
|
||||
INLINE ConditionVarLinuxImpl(MutexLinuxImpl &mutex);
|
||||
INLINE ~ConditionVarLinuxImpl();
|
||||
|
||||
void wait();
|
||||
void signal();
|
||||
|
||||
private:
|
||||
MutexLinuxImpl &_mutex;
|
||||
PN_int32 _counter;
|
||||
};
|
||||
|
||||
#include "conditionVarLinuxImpl.I"
|
||||
|
||||
#endif // HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#endif
|
||||
|
|
@ -59,3 +59,14 @@ signal() {
|
|||
int status = PR_NotifyCondVar(_cvar);
|
||||
nassertv(status == PR_SUCCESS);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarNsprImpl::signal_all
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarNsprImpl::
|
||||
signal_all() {
|
||||
int status = PR_NotifyAllCondVar(_cvar);
|
||||
nassertv(status == PR_SUCCESS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public:
|
|||
|
||||
INLINE void wait();
|
||||
INLINE void signal();
|
||||
INLINE void signal_all();
|
||||
|
||||
private:
|
||||
PRCondVar *_cvar;
|
||||
|
|
|
|||
|
|
@ -66,3 +66,15 @@ signal() {
|
|||
int result = pthread_cond_signal(&_cvar);
|
||||
nassertv(result == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarPosixImpl::signal_all
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarPosixImpl::
|
||||
signal_all() {
|
||||
TAU_PROFILE("ConditionVarPosixImpl::signal()", " ", TAU_USER);
|
||||
int result = pthread_cond_broadcast(&_cvar);
|
||||
nassertv(result == 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public:
|
|||
|
||||
INLINE void wait();
|
||||
INLINE void signal();
|
||||
INLINE void signal_all();
|
||||
|
||||
private:
|
||||
MutexPosixImpl &_mutex;
|
||||
|
|
|
|||
|
|
@ -46,3 +46,13 @@ signal() {
|
|||
// This will wake up all waiters on the lock. But that's allowed.
|
||||
AtomicAdjust::inc(_event);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarSpinlockImpl::signal_all
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarSpinlockImpl::
|
||||
signal_all() {
|
||||
AtomicAdjust::inc(_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public:
|
|||
|
||||
void wait();
|
||||
INLINE void signal();
|
||||
INLINE void signal_all();
|
||||
|
||||
private:
|
||||
MutexSpinlockImpl &_mutex;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ private:
|
|||
static MutexImpl *_global_lock;
|
||||
|
||||
friend class ConditionVarDebug;
|
||||
friend class ConditionVarFullDebug;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ private:
|
|||
MutexImpl _impl;
|
||||
|
||||
friend class ConditionVarDirect;
|
||||
friend class ConditionVarFullDirect;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
#include "conditionVarDebug.cxx"
|
||||
#include "conditionVarDirect.cxx"
|
||||
#include "conditionVarDummyImpl.cxx"
|
||||
#include "conditionVarFull.cxx"
|
||||
#include "conditionVarFullDebug.cxx"
|
||||
#include "conditionVarFullDirect.cxx"
|
||||
#include "conditionVarNsprImpl.cxx"
|
||||
#include "conditionVarLinuxImpl.cxx"
|
||||
#include "conditionVarPosixImpl.cxx"
|
||||
#include "conditionVarWin32Impl.cxx"
|
||||
#include "conditionVarSpinlockImpl.cxx"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,5 @@
|
|||
#include "thread.cxx"
|
||||
#include "threadDummyImpl.cxx"
|
||||
#include "threadNsprImpl.cxx"
|
||||
#include "threadLinuxImpl.cxx"
|
||||
#include "threadPosixImpl.cxx"
|
||||
#include "threadWin32Impl.cxx"
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ private:
|
|||
|
||||
friend class ThreadDummyImpl;
|
||||
friend class ThreadWin32Impl;
|
||||
friend class ThreadLinuxImpl;
|
||||
friend class ThreadPosixImpl;
|
||||
friend class ThreadNsprImpl;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,11 +32,6 @@ typedef ThreadDummyImpl ThreadImpl;
|
|||
#include "threadWin32Impl.h"
|
||||
typedef ThreadWin32Impl ThreadImpl;
|
||||
|
||||
#elif defined(THREAD_LINUX_IMPL)
|
||||
|
||||
#include "threadLinuxImpl.h"
|
||||
typedef ThreadLinuxImpl ThreadImpl;
|
||||
|
||||
#elif defined(THREAD_POSIX_IMPL)
|
||||
|
||||
#include "threadPosixImpl.h"
|
||||
|
|
|
|||
|
|
@ -1,260 +0,0 @@
|
|||
// Filename: threadLinuxImpl.cxx
|
||||
// Created by: drose (28Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "threadLinuxImpl.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_LINUX_IMPL
|
||||
|
||||
#include "pointerTo.h"
|
||||
#include "config_pipeline.h"
|
||||
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h> // for perror
|
||||
|
||||
MutexLinuxImpl ThreadLinuxImpl::_thread_pointers_lock;
|
||||
ThreadLinuxImpl::ThreadPointers ThreadLinuxImpl::_thread_pointers;
|
||||
bool ThreadLinuxImpl::_got_main_thread_pointer;
|
||||
|
||||
inline static pid_t gettid() {
|
||||
#ifdef __i386__
|
||||
pid_t ret;
|
||||
__asm__("int $0x80" : "=a" (ret) : "0" (224) /* SYS_gettid */);
|
||||
return ret;
|
||||
#else
|
||||
#error only i386 supported right now.
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ThreadLinuxImpl::
|
||||
~ThreadLinuxImpl() {
|
||||
if (thread_cat.is_debug()) {
|
||||
thread_cat.debug() << "Deleting thread " << _parent_obj->get_name() << "\n";
|
||||
}
|
||||
|
||||
if (_stack != NULL) {
|
||||
delete[] _stack;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::start
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ThreadLinuxImpl::
|
||||
start(ThreadPriority priority, bool global, bool joinable) {
|
||||
_mutex.lock();
|
||||
if (thread_cat.is_debug()) {
|
||||
thread_cat.debug() << "Starting " << *_parent_obj << "\n";
|
||||
}
|
||||
|
||||
nassertd(_status == S_new && _thread == 0 && _stack == NULL) {
|
||||
_mutex.release();
|
||||
return false;
|
||||
}
|
||||
|
||||
_joinable = joinable;
|
||||
_status = S_start_called;
|
||||
|
||||
if (!_got_main_thread_pointer) {
|
||||
// If we haven't spawned any threads yet, this must be the main
|
||||
// thread.
|
||||
bind_thread(Thread::get_main_thread());
|
||||
_got_main_thread_pointer = true;
|
||||
}
|
||||
|
||||
// Increment the parent object's reference count first. The thread
|
||||
// will eventually decrement it when it terminates.
|
||||
_parent_obj->ref();
|
||||
|
||||
_stack = new unsigned char[thread_stack_size];
|
||||
|
||||
int flags = SIGCHLD | CLONE_PARENT | CLONE_VM;
|
||||
if (!global) {
|
||||
// Make a thread that uses the same pid as the parent.
|
||||
flags |= CLONE_SIGHAND | CLONE_THREAD;
|
||||
}
|
||||
|
||||
_thread =
|
||||
clone(&root_func, _stack + thread_stack_size,
|
||||
flags, (void *)this);
|
||||
|
||||
if (_thread == -1) {
|
||||
// Oops, we couldn't start the thread. Be sure to decrement the
|
||||
// reference count we incremented above, and return false to
|
||||
// indicate failure.
|
||||
perror("clone");
|
||||
unref_delete(_parent_obj);
|
||||
_mutex.release();
|
||||
return false;
|
||||
}
|
||||
|
||||
_mutex.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::interrupt
|
||||
// Access: Public
|
||||
// Description: Sends an interrupt message to the thread. This will
|
||||
// interrupt any blocking-type system calls the thread
|
||||
// may be waiting on, such as I/O, so that the thread
|
||||
// may continue some other processing. The specific
|
||||
// behavior is implementation dependent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ThreadLinuxImpl::
|
||||
interrupt() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::join
|
||||
// Access: Public
|
||||
// Description: Blocks the calling process until the thread
|
||||
// terminates. If the thread has already terminated,
|
||||
// this returns immediately.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ThreadLinuxImpl::
|
||||
join() {
|
||||
_mutex.lock();
|
||||
nassertd(_joinable && _status != S_new) {
|
||||
_mutex.release();
|
||||
return;
|
||||
}
|
||||
|
||||
while (_status != S_finished) {
|
||||
_cv.wait();
|
||||
}
|
||||
_mutex.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::get_current_thread
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Thread *ThreadLinuxImpl::
|
||||
get_current_thread() {
|
||||
if (!_got_main_thread_pointer) {
|
||||
// If we haven't spawned any threads yet, this must be the main
|
||||
// thread.
|
||||
bind_thread(Thread::get_main_thread());
|
||||
_got_main_thread_pointer = true;
|
||||
return Thread::get_main_thread();
|
||||
}
|
||||
|
||||
_thread_pointers_lock.lock();
|
||||
Thread *result = NULL;
|
||||
|
||||
ThreadPointers::const_iterator ti;
|
||||
pid_t my_tid = gettid();
|
||||
ti = _thread_pointers.find(my_tid);
|
||||
if (ti != _thread_pointers.end()) {
|
||||
result = (*ti).second;
|
||||
}
|
||||
_thread_pointers_lock.release();
|
||||
|
||||
nassertr(result != NULL, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::bind_thread
|
||||
// Access: Public, Static
|
||||
// Description: Associates the indicated Thread object with the
|
||||
// currently-executing thread. You should not call this
|
||||
// directly; use Thread::bind_thread() instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ThreadLinuxImpl::
|
||||
bind_thread(Thread *thread) {
|
||||
_thread_pointers_lock.lock();
|
||||
pid_t my_tid = gettid();
|
||||
bool inserted = _thread_pointers.insert(ThreadPointers::value_type(my_tid, thread)).second;
|
||||
_thread_pointers_lock.release();
|
||||
nassertv(inserted);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadLinuxImpl::root_func
|
||||
// Access: Private, Static
|
||||
// Description: The entry point of each thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int ThreadLinuxImpl::
|
||||
root_func(void *data) {
|
||||
ThreadLinuxImpl *self = (ThreadLinuxImpl *)data;
|
||||
|
||||
{
|
||||
_thread_pointers_lock.lock();
|
||||
pid_t my_tid = gettid();
|
||||
|
||||
bool inserted = _thread_pointers.insert(ThreadPointers::value_type(my_tid, self->_parent_obj)).second;
|
||||
nassertd(inserted) {
|
||||
_thread_pointers_lock.release();
|
||||
return 1;
|
||||
}
|
||||
_thread_pointers_lock.release();
|
||||
}
|
||||
|
||||
{
|
||||
self->_mutex.lock();
|
||||
nassertd(self->_status == S_start_called) {
|
||||
self->_mutex.release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
self->_status = S_running;
|
||||
self->_cv.signal();
|
||||
self->_mutex.release();
|
||||
}
|
||||
|
||||
self->_parent_obj->thread_main();
|
||||
|
||||
if (thread_cat.is_debug()) {
|
||||
thread_cat.debug()
|
||||
<< "Terminating thread " << self->_parent_obj->get_name()
|
||||
<< ", count = " << self->_parent_obj->get_ref_count() << "\n";
|
||||
}
|
||||
|
||||
{
|
||||
self->_mutex.lock();
|
||||
nassertd(self->_status == S_running) {
|
||||
self->_mutex.release();
|
||||
return 1;
|
||||
}
|
||||
self->_status = S_finished;
|
||||
self->_cv.signal();
|
||||
self->_mutex.release();
|
||||
}
|
||||
|
||||
// Now drop the parent object reference that we grabbed in start().
|
||||
// This might delete the parent object, and in turn, delete the
|
||||
// ThreadLinuxImpl object.
|
||||
unref_delete(self->_parent_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // THREAD_LINUX_IMPL
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
// Filename: threadLinuxImpl.h
|
||||
// Created by: drose (28Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef THREADLINUXIMPL_H
|
||||
#define THREADLINUXIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_LINUX_IMPL
|
||||
|
||||
#include "pnotify.h"
|
||||
#include "threadPriority.h"
|
||||
#include "mutexLinuxImpl.h"
|
||||
#include "conditionVarLinuxImpl.h"
|
||||
|
||||
class Thread;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ThreadLinuxImpl
|
||||
// Description : Uses low-level Linux-specific calls to implement
|
||||
// threads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ThreadLinuxImpl {
|
||||
public:
|
||||
INLINE ThreadLinuxImpl(Thread *parent_obj);
|
||||
~ThreadLinuxImpl();
|
||||
|
||||
bool start(ThreadPriority priority, bool global, bool joinable);
|
||||
void interrupt();
|
||||
void join();
|
||||
|
||||
INLINE static void prepare_for_exit();
|
||||
|
||||
static Thread *get_current_thread();
|
||||
static void bind_thread(Thread *thread);
|
||||
INLINE static bool is_threading_supported();
|
||||
INLINE static void sleep(double seconds);
|
||||
|
||||
private:
|
||||
static int root_func(void *data);
|
||||
|
||||
enum Status {
|
||||
S_new,
|
||||
S_start_called,
|
||||
S_running,
|
||||
S_finished
|
||||
};
|
||||
|
||||
MutexLinuxImpl _mutex;
|
||||
ConditionVarLinuxImpl _cv;
|
||||
Thread *_parent_obj;
|
||||
int _thread;
|
||||
bool _joinable;
|
||||
Status _status;
|
||||
unsigned char *_stack;
|
||||
|
||||
// per-thread data.
|
||||
typedef pmap<pid_t, Thread *> ThreadPointers;
|
||||
static ThreadPointers _thread_pointers;
|
||||
static MutexLinuxImpl _thread_pointers_lock;
|
||||
static bool _got_main_thread_pointer;
|
||||
};
|
||||
|
||||
#include "threadLinuxImpl.I"
|
||||
|
||||
#endif // THREAD_LINUX_IMPL
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue