better thread safety
This commit is contained in:
parent
31d121e43b
commit
b407c2929b
|
|
@ -47,6 +47,8 @@
|
|||
stringDecoder.h stringDecoder.I \
|
||||
subStream.I subStream.h subStreamBuf.h \
|
||||
textEncoder.h textEncoder.I \
|
||||
threadSafePointerTo.I threadSafePointerTo.h \
|
||||
threadSafePointerToBase.I threadSafePointerToBase.h \
|
||||
tokenBoard.I \
|
||||
tokenBoard.h trueClock.I trueClock.h \
|
||||
typedReferenceCount.I typedReferenceCount.h typedef.h \
|
||||
|
|
@ -95,6 +97,8 @@
|
|||
stringDecoder.cxx \
|
||||
subStream.cxx subStreamBuf.cxx \
|
||||
textEncoder.cxx \
|
||||
threadSafePointerTo.cxx \
|
||||
threadSafePointerToBase.cxx \
|
||||
trueClock.cxx \
|
||||
typedReferenceCount.cxx \
|
||||
unicodeLatinMap.cxx \
|
||||
|
|
@ -149,6 +153,8 @@
|
|||
stringDecoder.h stringDecoder.I \
|
||||
subStream.I subStream.h subStreamBuf.h \
|
||||
textEncoder.h textEncoder.I \
|
||||
threadSafePointerTo.I threadSafePointerTo.h \
|
||||
threadSafePointerToBase.I threadSafePointerToBase.h \
|
||||
tokenBoard.I \
|
||||
tokenBoard.h trueClock.I trueClock.h \
|
||||
typedReferenceCount.I typedReferenceCount.h typedef.h \
|
||||
|
|
|
|||
|
|
@ -27,3 +27,4 @@
|
|||
#include "pointerToBase.cxx"
|
||||
#include "pointerToVoid.cxx"
|
||||
#include "profileTimer.cxx"
|
||||
#include "pta_uchar.cxx"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#include "pta_uchar.cxx"
|
||||
#include "ramfile.cxx"
|
||||
#include "referenceCount.cxx"
|
||||
#include "reversedNumericData.cxx"
|
||||
|
|
@ -8,6 +7,8 @@
|
|||
#include "subStream.cxx"
|
||||
#include "subStreamBuf.cxx"
|
||||
#include "textEncoder.cxx"
|
||||
#include "threadSafePointerTo.cxx"
|
||||
#include "threadSafePointerToBase.cxx"
|
||||
#include "trueClock.cxx"
|
||||
#include "typedReferenceCount.cxx"
|
||||
#include "unicodeLatinMap.cxx"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,259 @@
|
|||
// Filename: threadSafePointerTo.I
|
||||
// Created by: drose (28Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: ThreadSafePointerTo::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerTo<T>::
|
||||
ThreadSafePointerTo(To *ptr) : ThreadSafePointerToBase<T>(ptr) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerTo<T>::
|
||||
ThreadSafePointerTo(const ThreadSafePointerTo<T> ©) :
|
||||
ThreadSafePointerToBase<T>((const ThreadSafePointerToBase<T> &)copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerTo<T>::
|
||||
~ThreadSafePointerTo() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::Dereference operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE TYPENAME ThreadSafePointerTo<T>::To &ThreadSafePointerTo<T>::
|
||||
operator *() const {
|
||||
return *((To *)AtomicAdjust::get_ptr(this->_void_ptr));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::Member access operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE TYPENAME ThreadSafePointerTo<T>::To *ThreadSafePointerTo<T>::
|
||||
operator -> () const {
|
||||
return (To *)AtomicAdjust::get_ptr(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::Typecast operator
|
||||
// Access: Public
|
||||
// Description: We also have the typecast operator to automatically
|
||||
// convert ThreadSafePointerTo's to the required kind of actual
|
||||
// pointer. This introduces ambiguities which the
|
||||
// compiler will resolve one way or the other, but we
|
||||
// don't care which way it goes because either will be
|
||||
// correct.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerTo<T>::
|
||||
operator TYPENAME ThreadSafePointerToBase<T>::To *() const {
|
||||
return (To *)AtomicAdjust::get_ptr(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::p
|
||||
// Access: Published
|
||||
// Description: Returns an ordinary pointer instead of a ThreadSafePointerTo.
|
||||
// Useful to work around compiler problems, particularly
|
||||
// for implicit upcasts.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE TYPENAME ThreadSafePointerTo<T>::To *ThreadSafePointerTo<T>::
|
||||
p() const {
|
||||
return (To *)AtomicAdjust::get_ptr(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::Assignment operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerTo<T> &ThreadSafePointerTo<T>::
|
||||
operator = (To *ptr) {
|
||||
reassign(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerTo::Assignment operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerTo<T> &ThreadSafePointerTo<T>::
|
||||
operator = (const ThreadSafePointerTo<T> ©) {
|
||||
reassign((const ThreadSafePointerToBase<T> &)copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T>::
|
||||
ThreadSafeConstPointerTo(const TYPENAME ThreadSafeConstPointerTo<T>::To *ptr) :
|
||||
ThreadSafePointerToBase<T>((TYPENAME ThreadSafeConstPointerTo<T>::To *)ptr)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T>::
|
||||
ThreadSafeConstPointerTo(const ThreadSafePointerTo<T> ©) :
|
||||
ThreadSafePointerToBase<T>((const ThreadSafePointerToBase<T> &)copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T>::
|
||||
~ThreadSafeConstPointerTo() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T>::
|
||||
ThreadSafeConstPointerTo(const ThreadSafeConstPointerTo<T> ©) :
|
||||
ThreadSafePointerToBase<T>((const ThreadSafePointerToBase<T> &)copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Dereference operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const TYPENAME ThreadSafeConstPointerTo<T>::To &ThreadSafeConstPointerTo<T>::
|
||||
operator *() const {
|
||||
return *((To *)AtomicAdjust::get_ptr(this->_void_ptr));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Member access operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const TYPENAME ThreadSafeConstPointerTo<T>::To *ThreadSafeConstPointerTo<T>::
|
||||
operator -> () const {
|
||||
return (To *)AtomicAdjust::get_ptr(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Typecast operator
|
||||
// Access: Public
|
||||
// Description: We also have the typecast operator to automatically
|
||||
// convert ThreadSafeConstPointerTo's to the required kind of actual
|
||||
// pointer. This introduces ambiguities which the
|
||||
// compiler will resolve one way or the other, but we
|
||||
// don't care which way it goes because either will be
|
||||
// correct.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T>::
|
||||
operator const TYPENAME ThreadSafePointerToBase<T>::To *() const {
|
||||
return (To *)AtomicAdjust::get_ptr(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::p
|
||||
// Access: Published
|
||||
// Description: Returns an ordinary pointer instead of a ThreadSafeConstPointerTo.
|
||||
// Useful to work around compiler problems, particularly
|
||||
// for implicit upcasts.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const TYPENAME ThreadSafeConstPointerTo<T>::To *ThreadSafeConstPointerTo<T>::
|
||||
p() const {
|
||||
return (To *)AtomicAdjust::get_ptr(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Assignment operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T> &ThreadSafeConstPointerTo<T>::
|
||||
operator = (const To *ptr) {
|
||||
reassign((To *)ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Assignment operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T> &ThreadSafeConstPointerTo<T>::
|
||||
operator = (const ThreadSafePointerTo<T> ©) {
|
||||
reassign((const ThreadSafePointerToBase<T> &)copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafeConstPointerTo::Assignment operator
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafeConstPointerTo<T> &ThreadSafeConstPointerTo<T>::
|
||||
operator = (const ThreadSafeConstPointerTo<T> ©) {
|
||||
reassign((const ThreadSafePointerToBase<T> &)copy);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: threadSafePointerTo.cxx
|
||||
// Created by: drose (28Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "threadSafePointerTo.h"
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
// Filename: threadSafePointerTo.h
|
||||
// Created by: drose (28Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 THREADSAFEPOINTERTO_H
|
||||
#define THREADSAFEPOINTERTO_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "threadSafePointerToBase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ThreadSafePointerTo
|
||||
// Description : This works exactly like PointerTo, except that the
|
||||
// object is designed to be thread-safe: it is generally
|
||||
// safe to make unprotected assignments to this pointer,
|
||||
// in the sense that the last assignment will win and
|
||||
// the reference counts will be properly maintained.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class ThreadSafePointerTo : public ThreadSafePointerToBase<T> {
|
||||
public:
|
||||
typedef TYPENAME ThreadSafePointerToBase<T>::To To;
|
||||
PUBLISHED:
|
||||
INLINE ThreadSafePointerTo(To *ptr = (To *)NULL);
|
||||
INLINE ThreadSafePointerTo(const ThreadSafePointerTo<T> ©);
|
||||
INLINE ~ThreadSafePointerTo();
|
||||
|
||||
public:
|
||||
INLINE To &operator *() const;
|
||||
INLINE To *operator -> () const;
|
||||
INLINE operator TYPENAME ThreadSafePointerToBase<T>::To *() const;
|
||||
|
||||
PUBLISHED:
|
||||
// When downcasting to a derived class from a ThreadSafePointerTo<BaseClass>,
|
||||
// C++ would normally require you to cast twice: once to an actual
|
||||
// BaseClass pointer, and then again to your desired pointer. You
|
||||
// can use the handy function p() to avoid this first cast and make
|
||||
// your code look a bit cleaner.
|
||||
|
||||
// e.g. instead of (MyType *)(BaseClass *)ptr, use (MyType *)ptr.p()
|
||||
|
||||
// If your base class is a derivative of TypedObject, you might want
|
||||
// to use the DCAST macro defined in typedObject.h instead,
|
||||
// e.g. DCAST(MyType, ptr). This provides a clean downcast that
|
||||
// doesn't require .p() or any double-casting, and it can be
|
||||
// run-time checked for correctness.
|
||||
INLINE To *p() const;
|
||||
|
||||
INLINE ThreadSafePointerTo<T> &operator = (To *ptr);
|
||||
INLINE ThreadSafePointerTo<T> &operator = (const ThreadSafePointerTo<T> ©);
|
||||
|
||||
// These functions normally wouldn't need to be redefined here, but
|
||||
// we do so anyway just to help out interrogate (which doesn't seem
|
||||
// to want to automatically export the ThreadSafePointerToBase class). When
|
||||
// this works again in interrogate, we can remove these.
|
||||
INLINE bool is_null() const { return ThreadSafePointerToBase<T>::is_null(); }
|
||||
INLINE void clear() { ThreadSafePointerToBase<T>::clear(); }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ThreadSafeConstPointerTo
|
||||
// Description :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class ThreadSafeConstPointerTo : public ThreadSafePointerToBase<T> {
|
||||
public:
|
||||
typedef TYPENAME ThreadSafePointerToBase<T>::To To;
|
||||
PUBLISHED:
|
||||
INLINE ThreadSafeConstPointerTo(const To *ptr = (const To *)NULL);
|
||||
INLINE ThreadSafeConstPointerTo(const ThreadSafePointerTo<T> ©);
|
||||
INLINE ThreadSafeConstPointerTo(const ThreadSafeConstPointerTo<T> ©);
|
||||
INLINE ~ThreadSafeConstPointerTo();
|
||||
|
||||
public:
|
||||
INLINE const To &operator *() const;
|
||||
INLINE const To *operator -> () const;
|
||||
INLINE operator const TYPENAME ThreadSafePointerToBase<T>::To *() const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE const To *p() const;
|
||||
|
||||
INLINE ThreadSafeConstPointerTo<T> &operator = (const To *ptr);
|
||||
INLINE ThreadSafeConstPointerTo<T> &operator = (const ThreadSafePointerTo<T> ©);
|
||||
INLINE ThreadSafeConstPointerTo<T> &operator = (const ThreadSafeConstPointerTo<T> ©);
|
||||
|
||||
// This functions normally wouldn't need to be redefined here, but
|
||||
// we do so anyway just to help out interrogate (which doesn't seem
|
||||
// to want to automatically export the ThreadSafePointerToBase class). When
|
||||
// this works again in interrogate, we can remove this.
|
||||
INLINE void clear() { ThreadSafePointerToBase<T>::clear(); }
|
||||
};
|
||||
|
||||
#define TSPT(type) ThreadSafePointerTo< type >
|
||||
#define TSCPT(type) ThreadSafeConstPointerTo< type >
|
||||
|
||||
#include "threadSafePointerTo.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
// Filename: threadSafePointerToBase.I
|
||||
// Created by: drose (28Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: ThreadSafePointerToBase::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerToBase<T>::
|
||||
ThreadSafePointerToBase(To *ptr) {
|
||||
reassign(ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerToBase::Copy Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerToBase<T>::
|
||||
ThreadSafePointerToBase(const ThreadSafePointerToBase<T> ©) {
|
||||
reassign(copy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerToBase::Destructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE ThreadSafePointerToBase<T>::
|
||||
~ThreadSafePointerToBase() {
|
||||
reassign((To *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerToBase::reassign
|
||||
// Access: Protected
|
||||
// Description: This is the main work of the ThreadSafePointerTo family. When
|
||||
// the pointer is reassigned, decrement the old
|
||||
// reference count and increment the new one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void ThreadSafePointerToBase<T>::
|
||||
reassign(To *ptr) {
|
||||
To *old_ptr = (To *)AtomicAdjust::get_ptr(_void_ptr);
|
||||
if (ptr == old_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
void *orig_ptr = AtomicAdjust::compare_and_exchange_ptr(_void_ptr, old_ptr, ptr);
|
||||
while (orig_ptr != old_ptr) {
|
||||
// Some other thread assigned it first. Try again.
|
||||
old_ptr = (To *)AtomicAdjust::get_ptr(_void_ptr);
|
||||
if (ptr == old_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
orig_ptr = AtomicAdjust::compare_and_exchange_ptr(_void_ptr, old_ptr, ptr);
|
||||
}
|
||||
#else // HAVE_THREADS
|
||||
_void_ptr = ptr;
|
||||
#endif // HAVE_THREADS
|
||||
|
||||
if (ptr != (To *)NULL) {
|
||||
ptr->ref();
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
if (MemoryUsage::get_track_memory_usage()) {
|
||||
update_type(ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Now delete the old pointer.
|
||||
if (old_ptr != (To *)NULL) {
|
||||
unref_delete(old_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerToBase::reassign
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void ThreadSafePointerToBase<T>::
|
||||
reassign(const ThreadSafePointerToBase<To> ©) {
|
||||
reassign((To *)copy._void_ptr);
|
||||
}
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerToBase::update_type
|
||||
// Access: Protected
|
||||
// Description: Ensures that the MemoryUsage record for the pointer
|
||||
// has the right type of object, if we know the type
|
||||
// ourselves.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
void ThreadSafePointerToBase<T>::
|
||||
update_type(To *ptr) {
|
||||
TypeHandle type = get_type_handle(To);
|
||||
if (type == TypeHandle::none()) {
|
||||
do_init_type(To);
|
||||
type = get_type_handle(To);
|
||||
}
|
||||
if (type != TypeHandle::none()) {
|
||||
MemoryUsage::update_type(ptr, type);
|
||||
}
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerToBase::clear
|
||||
// Access: Published
|
||||
// Description: A convenient way to set the ThreadSafePointerTo object to NULL.
|
||||
// (Assignment to a NULL pointer also works, of course.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void ThreadSafePointerToBase<T>::
|
||||
clear() {
|
||||
reassign((To *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ThreadSafePointerToBase::output
|
||||
// Access: Published
|
||||
// Description: A handy function to output ThreadSafePointerTo's as a hex
|
||||
// pointer followed by a reference count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void ThreadSafePointerToBase<T>::
|
||||
output(ostream &out) const {
|
||||
out << _void_ptr;
|
||||
if (_void_ptr != (void *)NULL) {
|
||||
out << ":" << ((To *)_void_ptr)->get_ref_count();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: threadSafePointerToBase.cxx
|
||||
// Created by: drose (28Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "threadSafePointerToBase.h"
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Filename: threadSafePointerToBase.h
|
||||
// Created by: drose (28Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 THREADSAFEPOINTERTOBASE_H
|
||||
#define THREADSAFEPOINTERTOBASE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pointerToVoid.h"
|
||||
#include "referenceCount.h"
|
||||
#include "typedef.h"
|
||||
#include "memoryUsage.h"
|
||||
#include "config_express.h"
|
||||
#include "atomicAdjust.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ThreadSafePointerToBase
|
||||
// Description : This is the base class for ThreadSafePointerTo and
|
||||
// ThreadSafeConstPointerTo. Don't try to use it
|
||||
// directly; use either derived class instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class ThreadSafePointerToBase : public PointerToVoid {
|
||||
public:
|
||||
typedef T To;
|
||||
|
||||
protected:
|
||||
INLINE ThreadSafePointerToBase(To *ptr);
|
||||
INLINE ThreadSafePointerToBase(const ThreadSafePointerToBase<T> ©);
|
||||
INLINE ~ThreadSafePointerToBase();
|
||||
|
||||
INLINE void reassign(To *ptr);
|
||||
INLINE void reassign(const ThreadSafePointerToBase<To> ©);
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
void update_type(To *ptr);
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
// No assignment or retrieval functions are declared in
|
||||
// ThreadSafePointerToBase, because we will have to specialize on const
|
||||
// vs. non-const later.
|
||||
|
||||
PUBLISHED:
|
||||
INLINE void clear();
|
||||
|
||||
void output(ostream &out) const;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
INLINE ostream &operator <<(ostream &out, const ThreadSafePointerToBase<T> &pointer) {
|
||||
pointer.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "threadSafePointerToBase.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "mutexHolder.h"
|
||||
|
||||
UpdateSeq Geom::_next_modified;
|
||||
PStatCollector Geom::_draw_primitive_setup_pcollector("Draw:Primitive:Setup");
|
||||
|
|
@ -801,6 +802,7 @@ write(ostream &out, int indent_level) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void Geom::
|
||||
clear_cache() {
|
||||
MutexHolder holder(_cache_lock);
|
||||
for (Cache::iterator ci = _cache.begin();
|
||||
ci != _cache.end();
|
||||
++ci) {
|
||||
|
|
@ -823,6 +825,7 @@ clear_cache() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void Geom::
|
||||
clear_cache_stage(Thread *current_thread) {
|
||||
MutexHolder holder(_cache_lock);
|
||||
for (Cache::iterator ci = _cache.begin();
|
||||
ci != _cache.end();
|
||||
++ci) {
|
||||
|
|
@ -1240,6 +1243,7 @@ make_copy() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void Geom::CacheEntry::
|
||||
evict_callback() {
|
||||
MutexHolder holder(_source->_cache_lock);
|
||||
Cache::iterator ci = _source->_cache.find(this);
|
||||
nassertv(ci != _source->_cache.end());
|
||||
nassertv((*ci) == this);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "boundingVolume.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "deletedChain.h"
|
||||
#include "pmutex.h"
|
||||
|
||||
class GeomContext;
|
||||
class PreparedGraphicsObjects;
|
||||
|
|
@ -254,6 +255,7 @@ private:
|
|||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||
|
||||
Cache _cache;
|
||||
Mutex _cache_lock;
|
||||
|
||||
// This works just like the Texture contexts: each Geom keeps a
|
||||
// record of all the PGO objects that hold the Geom, and vice-versa.
|
||||
|
|
|
|||
|
|
@ -117,22 +117,27 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data,
|
|||
|
||||
Geom::CacheEntry temp_entry(source_data, this);
|
||||
temp_entry.local_object();
|
||||
Geom::Cache::const_iterator ci = geom->_cache.find(&temp_entry);
|
||||
if (ci != geom->_cache.end()) {
|
||||
entry = (*ci);
|
||||
nassertv(entry->_source == geom);
|
||||
|
||||
geom->_cache_lock.lock();
|
||||
Geom::Cache::const_iterator ci = geom->_cache.find(&temp_entry);
|
||||
if (ci == geom->_cache.end()) {
|
||||
geom->_cache_lock.release();
|
||||
} else {
|
||||
entry = (*ci);
|
||||
geom->_cache_lock.release();
|
||||
nassertv(entry->_source == geom);
|
||||
|
||||
// Here's an element in the cache for this computation. Record a
|
||||
// cache hit, so this element will stay in the cache a while
|
||||
// longer.
|
||||
entry->refresh(current_thread);
|
||||
|
||||
|
||||
// Now check that it's fresh.
|
||||
Geom::CDCacheReader cdata(entry->_cycler, current_thread);
|
||||
nassertv(cdata->_source == geom);
|
||||
if (cdata->_geom_result != (Geom *)NULL &&
|
||||
geom->get_modified(current_thread) <= cdata->_geom_result->get_modified(current_thread) &&
|
||||
data->get_modified(current_thread) <= cdata->_data_result->get_modified(current_thread)) {
|
||||
if (cdata->_source == geom &&
|
||||
cdata->_geom_result != (Geom *)NULL &&
|
||||
geom->get_modified(current_thread) <= cdata->_geom_result->get_modified(current_thread) &&
|
||||
data->get_modified(current_thread) <= cdata->_data_result->get_modified(current_thread)) {
|
||||
// The cache entry is still good; use it.
|
||||
|
||||
geom = cdata->_geom_result;
|
||||
|
|
@ -149,16 +154,23 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data,
|
|||
// Ok, invoke the munger.
|
||||
PStatTimer timer(_munge_pcollector, current_thread);
|
||||
|
||||
CPT(Geom) orig_geom = geom;
|
||||
PT(Geom) orig_geom = (Geom *)geom.p();
|
||||
data = munge_data(data);
|
||||
munge_geom_impl(geom, data, current_thread);
|
||||
|
||||
// Record the new result in the cache.
|
||||
if (entry == (Geom::CacheEntry *)NULL) {
|
||||
// Create a new entry for the result.
|
||||
entry = new Geom::CacheEntry((Geom *)orig_geom.p(), source_data, this);
|
||||
bool inserted = ((Geom *)orig_geom.p())->_cache.insert(entry).second;
|
||||
nassertv(inserted);
|
||||
entry = new Geom::CacheEntry(orig_geom, source_data, this);
|
||||
{
|
||||
MutexHolder holder(orig_geom->_cache_lock);
|
||||
bool inserted = orig_geom->_cache.insert(entry).second;
|
||||
if (!inserted) {
|
||||
// Some other thread must have beat us to the punch. Never
|
||||
// mind.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// And tell the cache manager about the new entry. (It might
|
||||
// immediately request a delete from the cache of the thing we
|
||||
|
|
|
|||
|
|
@ -677,9 +677,15 @@ convert_to(const GeomVertexFormat *new_format) const {
|
|||
|
||||
CacheEntry temp_entry(new_format);
|
||||
temp_entry.local_object();
|
||||
|
||||
_cache_lock.lock();
|
||||
Cache::const_iterator ci = _cache.find(&temp_entry);
|
||||
if (ci != _cache.end()) {
|
||||
if (ci == _cache.end()) {
|
||||
_cache_lock.release();
|
||||
|
||||
} else {
|
||||
entry = (*ci);
|
||||
_cache_lock.release();
|
||||
nassertr(entry->_source == this, NULL);
|
||||
|
||||
// Here's an element in the cache for this computation. Record a
|
||||
|
|
@ -717,8 +723,15 @@ convert_to(const GeomVertexFormat *new_format) const {
|
|||
if (entry == (CacheEntry *)NULL) {
|
||||
// Create a new entry for the result.
|
||||
entry = new CacheEntry((GeomVertexData *)this, new_format);
|
||||
bool inserted = ((GeomVertexData *)this)->_cache.insert(entry).second;
|
||||
nassertr(inserted, new_data);
|
||||
{
|
||||
MutexHolder holder(_cache_lock);
|
||||
bool inserted = ((GeomVertexData *)this)->_cache.insert(entry).second;
|
||||
if (!inserted) {
|
||||
// Some other thread must have beat us to the punch. Never
|
||||
// mind.
|
||||
return new_data;
|
||||
}
|
||||
}
|
||||
|
||||
// And tell the cache manager about the new entry. (It might
|
||||
// immediately request a delete from the cache of the thing we
|
||||
|
|
@ -727,7 +740,7 @@ convert_to(const GeomVertexFormat *new_format) const {
|
|||
}
|
||||
|
||||
// Finally, store the cached result on the entry.
|
||||
CDCacheWriter cdata(entry->_cycler, true);
|
||||
CDCacheWriter cdata(entry->_cycler, true, current_thread);
|
||||
cdata->_result = new_data;
|
||||
|
||||
return new_data;
|
||||
|
|
@ -1095,6 +1108,7 @@ write(ostream &out, int indent_level) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexData::
|
||||
clear_cache() {
|
||||
MutexHolder holder(_cache_lock);
|
||||
for (Cache::iterator ci = _cache.begin();
|
||||
ci != _cache.end();
|
||||
++ci) {
|
||||
|
|
@ -1117,6 +1131,7 @@ clear_cache() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexData::
|
||||
clear_cache_stage() {
|
||||
MutexHolder holder(_cache_lock);
|
||||
for (Cache::iterator ci = _cache.begin();
|
||||
ci != _cache.end();
|
||||
++ci) {
|
||||
|
|
@ -1471,6 +1486,7 @@ make_copy() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexData::CacheEntry::
|
||||
evict_callback() {
|
||||
MutexHolder holder(_source->_cache_lock);
|
||||
Cache::iterator ci = _source->_cache.find(this);
|
||||
nassertv(ci != _source->_cache.end());
|
||||
nassertv((*ci) == this);
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ private:
|
|||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||
|
||||
Cache _cache;
|
||||
Mutex _cache_lock;
|
||||
|
||||
private:
|
||||
void update_animated_vertices(CData *cdata, Thread *current_thread);
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ INLINE const CycleData *PipelineCyclerTrueImpl::
|
|||
read(Thread *current_thread) const {
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read(Thread *)", " ", TAU_USER);
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
#ifdef _DEBUG
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
#endif
|
||||
_lock.lock(current_thread);
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
|
@ -238,7 +240,7 @@ increment_write(CycleData *pointer) const {
|
|||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_write(CycleData *pointer) {
|
||||
TAU_PROFILE("void PipelineCyclerTrueImpl::release_write(CycleData *)", " ", TAU_USER);
|
||||
#ifdef NDEBUG
|
||||
#ifdef _DEBUG
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
return release_write_stage(pipeline_stage, pointer);
|
||||
#else
|
||||
|
|
@ -270,7 +272,9 @@ get_num_stages() {
|
|||
INLINE const CycleData *PipelineCyclerTrueImpl::
|
||||
read_stage(int pipeline_stage, Thread *current_thread) const {
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int)", " ", TAU_USER);
|
||||
#ifdef _DEBUG
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
#endif
|
||||
_lock.lock(current_thread);
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue