ConditionVarFull

This commit is contained in:
David Rose 2006-08-29 06:38:53 +00:00
parent ce3ed75e1a
commit 01a09a9d28
34 changed files with 940 additions and 530 deletions

View File

@ -42,6 +42,7 @@ public:
private:
CRITICAL_SECTION _lock;
friend class ConditionVarWin32Impl;
friend class ConditionVarFullWin32Impl;
};
#include "mutexWin32Impl.I"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 &copy) :
#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 &copy) {
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
}

View File

@ -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"

View File

@ -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 &copy);
INLINE void operator = (const ConditionVarFull &copy);
public:
INLINE Mutex &get_mutex() const;
};
#include "conditionVarFull.I"
#endif

View File

@ -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 &copy) :
_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 &copy) {
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;
}

View File

@ -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

View File

@ -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 &copy);
INLINE void operator = (const ConditionVarFullDebug &copy);
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

View File

@ -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 &copy) :
_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 &copy) {
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();
}

View File

@ -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

View File

@ -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 &copy);
INLINE void operator = (const ConditionVarFullDirect &copy);
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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -42,6 +42,7 @@ public:
INLINE void wait();
INLINE void signal();
INLINE void signal_all();
private:
PRCondVar *_cvar;

View File

@ -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);
}

View File

@ -42,6 +42,7 @@ public:
INLINE void wait();
INLINE void signal();
INLINE void signal_all();
private:
MutexPosixImpl &_mutex;

View File

@ -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);
}

View File

@ -46,6 +46,7 @@ public:
void wait();
INLINE void signal();
INLINE void signal_all();
private:
MutexSpinlockImpl &_mutex;

View File

@ -71,6 +71,7 @@ private:
static MutexImpl *_global_lock;
friend class ConditionVarDebug;
friend class ConditionVarFullDebug;
};
INLINE ostream &

View File

@ -52,6 +52,7 @@ private:
MutexImpl _impl;
friend class ConditionVarDirect;
friend class ConditionVarFullDirect;
};
INLINE ostream &

View File

@ -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"

View File

@ -15,6 +15,5 @@
#include "thread.cxx"
#include "threadDummyImpl.cxx"
#include "threadNsprImpl.cxx"
#include "threadLinuxImpl.cxx"
#include "threadPosixImpl.cxx"
#include "threadWin32Impl.cxx"

View File

@ -130,7 +130,6 @@ private:
friend class ThreadDummyImpl;
friend class ThreadWin32Impl;
friend class ThreadLinuxImpl;
friend class ThreadPosixImpl;
friend class ThreadNsprImpl;
};

View File

@ -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"

View File

@ -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

View File

@ -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