reduced need for read locks
This commit is contained in:
parent
f6d45f344d
commit
c8eb6c5a82
|
|
@ -94,7 +94,7 @@ void PartBundle::
|
|||
set_blend_type(BlendType bt) {
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
if (cdata->_blend_type != bt) {
|
||||
CDWriter cdataw(_cycler, cdata);
|
||||
cdataw->_blend_type = bt;
|
||||
|
|
@ -131,7 +131,7 @@ void PartBundle::
|
|||
clear_control_effects() {
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
if (!cdata->_blend.empty()) {
|
||||
CDWriter cdataw(_cycler, cdata);
|
||||
cdataw->_blend.clear();
|
||||
|
|
@ -299,7 +299,7 @@ control_activated(AnimControl *control) {
|
|||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
nassertv(control->get_part() == this);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
// If (and only if) our blend type is BT_single, which means no
|
||||
// blending, then starting an animation implicitly enables it.
|
||||
if (cdata->_blend_type == BT_single) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@
|
|||
#include "partSubset.h"
|
||||
#include "pointerTo.h"
|
||||
#include "thread.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
|
||||
class AnimBundle;
|
||||
class PartBundleNode;
|
||||
|
|
@ -150,6 +154,7 @@ private:
|
|||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ void DisplayRegion::
|
|||
set_active(bool active) {
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertv(pipeline_stage == 0);
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
|
||||
if (active != cdata->_active) {
|
||||
CDWriter cdataw(_cycler, cdata);
|
||||
|
|
@ -222,7 +222,7 @@ set_active(bool active) {
|
|||
void DisplayRegion::
|
||||
set_sort(int sort) {
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
|
||||
if (sort != cdata->_sort) {
|
||||
CDWriter cdataw(_cycler, cdata);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "sceneSetup.h"
|
||||
#include "pointerTo.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "cycleDataStageWriter.h"
|
||||
|
|
@ -176,6 +177,7 @@ private:
|
|||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
multifile.I multifile.h \
|
||||
namable.I \
|
||||
namable.h nativeNumericData.I nativeNumericData.h \
|
||||
nodePointerToBase.h nodePointerToBase.I \
|
||||
nodePointerTo.h nodePointerTo.I \
|
||||
nodeReferenceCount.h nodeReferenceCount.I \
|
||||
objectDeletor.h objectDeletor.I \
|
||||
ordered_vector.h ordered_vector.I ordered_vector.T \
|
||||
password_hash.h \
|
||||
|
|
@ -80,6 +83,9 @@
|
|||
memoryUsagePointers.cxx multifile.cxx \
|
||||
namable.cxx \
|
||||
nativeNumericData.cxx \
|
||||
nodePointerToBase.cxx \
|
||||
nodePointerTo.cxx \
|
||||
nodeReferenceCount.cxx \
|
||||
objectDeletor.cxx \
|
||||
ordered_vector.cxx \
|
||||
password_hash.cxx \
|
||||
|
|
@ -136,6 +142,9 @@
|
|||
multifile.I multifile.h \
|
||||
namable.I \
|
||||
namable.h nativeNumericData.I nativeNumericData.h \
|
||||
nodePointerToBase.h nodePointerToBase.I \
|
||||
nodePointerTo.h nodePointerTo.I \
|
||||
nodeReferenceCount.h nodeReferenceCount.I \
|
||||
objectDeletor.h objectDeletor.I \
|
||||
ordered_vector.h ordered_vector.I ordered_vector.T \
|
||||
password_hash.h \
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "config_express.h"
|
||||
#include "datagram.h"
|
||||
#include "nodeReferenceCount.h"
|
||||
#include "referenceCount.h"
|
||||
#include "textEncoder.h"
|
||||
#include "typedObject.h"
|
||||
|
|
@ -147,6 +148,7 @@ init_libexpress() {
|
|||
initialized = true;
|
||||
|
||||
Datagram::init_type();
|
||||
NodeReferenceCount::init_type();
|
||||
ReferenceCount::init_type();
|
||||
TextEncoder::init_type();
|
||||
TypedObject::init_type();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
#include "multifile.cxx"
|
||||
#include "namable.cxx"
|
||||
#include "nativeNumericData.cxx"
|
||||
#include "nodePointerToBase.cxx"
|
||||
#include "nodePointerTo.cxx"
|
||||
#include "nodeReferenceCount.cxx"
|
||||
#include "objectDeletor.cxx"
|
||||
#include "ordered_vector.cxx"
|
||||
#include "patchfile.cxx"
|
||||
|
|
@ -27,4 +30,3 @@
|
|||
#include "pointerToBase.cxx"
|
||||
#include "pointerToVoid.cxx"
|
||||
#include "profileTimer.cxx"
|
||||
#include "pta_uchar.cxx"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "pta_uchar.cxx"
|
||||
#include "ramfile.cxx"
|
||||
#include "referenceCount.cxx"
|
||||
#include "reversedNumericData.cxx"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,259 @@
|
|||
// Filename: nodePointerTo.I
|
||||
// Created by: drose (07May05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: NodePointerTo::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerTo<T>::
|
||||
NodePointerTo(To *ptr) : NodePointerToBase<T>(ptr) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerTo<T>::
|
||||
NodePointerTo(const NodePointerTo<T> ©) :
|
||||
NodePointerToBase<T>((const NodePointerToBase<T> &)copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerTo<T>::
|
||||
~NodePointerTo() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::Dereference operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE TYPENAME NodePointerTo<T>::To &NodePointerTo<T>::
|
||||
operator *() const {
|
||||
return *((To *)(this->_void_ptr));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::Member access operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE TYPENAME NodePointerTo<T>::To *NodePointerTo<T>::
|
||||
operator -> () const {
|
||||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::Typecast operator
|
||||
// Access: Public
|
||||
// Description: We also have the typecast operator to automatically
|
||||
// convert NodePointerTo'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 NodePointerTo<T>::
|
||||
operator TYPENAME NodePointerToBase<T>::To *() const {
|
||||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::p
|
||||
// Access: Public
|
||||
// Description: Returns an ordinary pointer instead of a NodePointerTo.
|
||||
// Useful to work around compiler problems, particularly
|
||||
// for implicit upcasts.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE TYPENAME NodePointerTo<T>::To *NodePointerTo<T>::
|
||||
p() const {
|
||||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::Assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerTo<T> &NodePointerTo<T>::
|
||||
operator = (To *ptr) {
|
||||
reassign(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerTo::Assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerTo<T> &NodePointerTo<T>::
|
||||
operator = (const NodePointerTo<T> ©) {
|
||||
reassign((const NodePointerToBase<T> &)copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodeConstPointerTo<T>::
|
||||
NodeConstPointerTo(const TYPENAME NodeConstPointerTo<T>::To *ptr) :
|
||||
NodePointerToBase<T>((TYPENAME NodeConstPointerTo<T>::To *)ptr)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodeConstPointerTo<T>::
|
||||
NodeConstPointerTo(const NodePointerTo<T> ©) :
|
||||
NodePointerToBase<T>((const NodePointerToBase<T> &)copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodeConstPointerTo<T>::
|
||||
NodeConstPointerTo(const NodeConstPointerTo<T> ©) :
|
||||
NodePointerToBase<T>((const NodePointerToBase<T> &)copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodeConstPointerTo<T>::
|
||||
~NodeConstPointerTo() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Dereference operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const TYPENAME NodeConstPointerTo<T>::To &NodeConstPointerTo<T>::
|
||||
operator *() const {
|
||||
return *((To *)(this->_void_ptr));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Member access operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const TYPENAME NodeConstPointerTo<T>::To *NodeConstPointerTo<T>::
|
||||
operator -> () const {
|
||||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Typecast operator
|
||||
// Access: Public
|
||||
// Description: We also have the typecast operator to automatically
|
||||
// convert NodeConstPointerTo'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 NodeConstPointerTo<T>::
|
||||
operator const TYPENAME NodePointerToBase<T>::To *() const {
|
||||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::p
|
||||
// Access: Public
|
||||
// Description: Returns an ordinary pointer instead of a NodeConstPointerTo.
|
||||
// Useful to work around compiler problems, particularly
|
||||
// for implicit upcasts.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const TYPENAME NodeConstPointerTo<T>::To *NodeConstPointerTo<T>::
|
||||
p() const {
|
||||
return (To *)(this->_void_ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodeConstPointerTo<T> &NodeConstPointerTo<T>::
|
||||
operator = (const To *ptr) {
|
||||
reassign((To *)ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodeConstPointerTo<T> &NodeConstPointerTo<T>::
|
||||
operator = (const NodePointerTo<T> ©) {
|
||||
reassign((const NodePointerToBase<T> &)copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeConstPointerTo::Assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodeConstPointerTo<T> &NodeConstPointerTo<T>::
|
||||
operator = (const NodeConstPointerTo<T> ©) {
|
||||
reassign((const NodePointerToBase<T> &)copy);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: nodePointerTo.cxx
|
||||
// Created by: drose (07May05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "nodePointerTo.h"
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Filename: nodePointerTo.h
|
||||
// Created by: drose (07May05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 NODEPOINTERTO_H
|
||||
#define NODEPOINTERTO_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "nodePointerToBase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NodePointerTo
|
||||
// Description : This implements the special NodePointerTo template
|
||||
// class, which works just like PointerTo except it
|
||||
// manages the objects node_ref_count instead of the
|
||||
// normal ref_count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class NodePointerTo : public NodePointerToBase<T> {
|
||||
public:
|
||||
typedef TYPENAME NodePointerToBase<T>::To To;
|
||||
INLINE NodePointerTo(To *ptr = (To *)NULL);
|
||||
INLINE NodePointerTo(const NodePointerTo<T> ©);
|
||||
INLINE ~NodePointerTo();
|
||||
|
||||
INLINE To &operator *() const;
|
||||
INLINE To *operator -> () const;
|
||||
INLINE operator TYPENAME NodePointerToBase<T>::To *() const;
|
||||
|
||||
INLINE To *p() const;
|
||||
|
||||
INLINE NodePointerTo<T> &operator = (To *ptr);
|
||||
INLINE NodePointerTo<T> &operator = (const NodePointerTo<T> ©);
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NodeConstPointerTo
|
||||
// Description : A NodeConstPointerTo is similar to a NodePointerTo,
|
||||
// except it keeps a const pointer to the thing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class NodeConstPointerTo : public NodePointerToBase<T> {
|
||||
public:
|
||||
typedef TYPENAME NodePointerToBase<T>::To To;
|
||||
INLINE NodeConstPointerTo(const To *ptr = (const To *)NULL);
|
||||
INLINE NodeConstPointerTo(const NodePointerTo<T> ©);
|
||||
INLINE NodeConstPointerTo(const NodeConstPointerTo<T> ©);
|
||||
INLINE ~NodeConstPointerTo();
|
||||
|
||||
INLINE const To &operator *() const;
|
||||
INLINE const To *operator -> () const;
|
||||
INLINE operator const TYPENAME NodePointerToBase<T>::To *() const;
|
||||
|
||||
INLINE const To *p() const;
|
||||
|
||||
INLINE NodeConstPointerTo<T> &operator = (const To *ptr);
|
||||
INLINE NodeConstPointerTo<T> &operator = (const NodePointerTo<T> ©);
|
||||
INLINE NodeConstPointerTo<T> &operator = (const NodeConstPointerTo<T> ©);
|
||||
};
|
||||
|
||||
#define NPT(type) NodePointerTo< type >
|
||||
#define NCPT(type) NodeConstPointerTo< type >
|
||||
|
||||
#include "nodePointerTo.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
// Filename: nodePointerToBase.I
|
||||
// Created by: drose (07May05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: NodePointerToBase::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerToBase<T>::
|
||||
NodePointerToBase(To *ptr) {
|
||||
reassign(ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerToBase::Copy Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerToBase<T>::
|
||||
NodePointerToBase(const NodePointerToBase<T> ©) {
|
||||
reassign(copy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerToBase::Destructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE NodePointerToBase<T>::
|
||||
~NodePointerToBase() {
|
||||
reassign((To *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerToBase::reassign
|
||||
// Access: Protected
|
||||
// Description: This is the main work of the NodePointerTo family. When
|
||||
// the pointer is reassigned, decrement the old
|
||||
// reference count and increment the new one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
void NodePointerToBase<T>::
|
||||
reassign(To *ptr) {
|
||||
if (ptr != (To *)_void_ptr) {
|
||||
// First save the old pointer; we won't delete it until we have
|
||||
// assigned the new one. We do this just in case there are
|
||||
// cascading effects from deleting this pointer that might
|
||||
// inadvertently delete the new one. (Don't laugh--it's
|
||||
// happened!)
|
||||
To *old_ptr = (To *)_void_ptr;
|
||||
|
||||
_void_ptr = (void *)ptr;
|
||||
if (ptr != (To *)NULL) {
|
||||
ptr->node_ref();
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
if (MemoryUsage::get_track_memory_usage()) {
|
||||
// Make sure the MemoryUsage record knows what the TypeHandle
|
||||
// is, if we know it ourselves.
|
||||
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
|
||||
}
|
||||
|
||||
// Now delete the old pointer.
|
||||
if (old_ptr != (To *)NULL) {
|
||||
node_unref_delete(old_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerToBase::reassign
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void NodePointerToBase<T>::
|
||||
reassign(const NodePointerToBase<To> ©) {
|
||||
reassign((To *)copy._void_ptr);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerToBase::clear
|
||||
// Access: Published
|
||||
// Description: A convenient way to set the NodePointerTo object to NULL.
|
||||
// (Assignment to a NULL pointer also works, of course.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void NodePointerToBase<T>::
|
||||
clear() {
|
||||
reassign((To *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePointerToBase::output
|
||||
// Access: Published
|
||||
// Description: A handy function to output NodePointerTo's as a hex
|
||||
// pointer followed by a reference count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE void NodePointerToBase<T>::
|
||||
output(ostream &out) const {
|
||||
out << _void_ptr;
|
||||
if (_void_ptr != (void *)NULL) {
|
||||
out << ":" << ((To *)_void_ptr)->get_node_ref_count() << "/"
|
||||
<< ((To *)_void_ptr)->get_ref_count();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: nodePointerToBase.cxx
|
||||
// Created by: drose (07May05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "nodePointerToBase.h"
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// Filename: nodePointerToBase.h
|
||||
// Created by: drose (07May05)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 NODEPOINTERTOBASE_H
|
||||
#define NODEPOINTERTOBASE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pointerToVoid.h"
|
||||
#include "memoryUsage.h"
|
||||
#include "config_express.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NodePointerToBase
|
||||
// Description : This is similar to PointerToBase, but it manages
|
||||
// objects of type NodeReferenceCount or
|
||||
// NodeCachedReferenceCount, and it updates the
|
||||
// node_ref_count instead of the regular ref_count. It
|
||||
// is intended for use only in PandaNode, to hold a
|
||||
// pointer to RenderState and TransformState, although
|
||||
// it could be used by any object that wanted to
|
||||
// maintain a separate reference count for reporting
|
||||
// purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class NodePointerToBase : public PointerToVoid {
|
||||
public:
|
||||
typedef T To;
|
||||
|
||||
protected:
|
||||
INLINE NodePointerToBase(To *ptr);
|
||||
INLINE NodePointerToBase(const NodePointerToBase<T> ©);
|
||||
INLINE ~NodePointerToBase();
|
||||
|
||||
void reassign(To *ptr);
|
||||
INLINE void reassign(const NodePointerToBase<To> ©);
|
||||
|
||||
// No assignment or retrieval functions are declared in
|
||||
// NodePointerToBase, 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 NodePointerToBase<T> &pointer) {
|
||||
pointer.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "nodePointerToBase.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,295 @@
|
|||
// Filename: nodeReferenceCount.I
|
||||
// Created by: drose (01May06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template<class Base>
|
||||
TypeHandle NodeRefCountObj<Base>::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::Constructor
|
||||
// Access: Protected
|
||||
// Description: The ReferenceCount constructor is protected because
|
||||
// you almost never want to create just a ReferenceCount
|
||||
// object by itself, and it's probably a mistake if you
|
||||
// try.
|
||||
//
|
||||
// ReferenceCount doesn't store any useful information
|
||||
// in its own right; its only purpose is to add
|
||||
// reference-counting to some other class via
|
||||
// inheritance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE NodeReferenceCount::
|
||||
NodeReferenceCount() {
|
||||
_node_ref_count = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::Copy Constructor
|
||||
// Access: Protected
|
||||
// Description: The copies of reference-counted objects do not
|
||||
// themselves inherit the reference count!
|
||||
//
|
||||
// This copy constructor is protected because you almost
|
||||
// never want to create just a ReferenceCount object by
|
||||
// itself, and it's probably a mistake if you try.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE NodeReferenceCount::
|
||||
NodeReferenceCount(const NodeReferenceCount ©) : ReferenceCount(copy) {
|
||||
_node_ref_count = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::Copy Assignment Operator
|
||||
// Access: Protected
|
||||
// Description: The copies of reference-counted objects do not
|
||||
// themselves inherit the reference count!
|
||||
//
|
||||
// This copy assignment operator is protected because
|
||||
// you almost never want to copy just a ReferenceCount
|
||||
// object by itself, and it's probably a mistake if you
|
||||
// try. Instead, this should only be called from a
|
||||
// derived class that implements this operator and then
|
||||
// calls up the inheritance chain.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NodeReferenceCount::
|
||||
operator = (const NodeReferenceCount ©) {
|
||||
nassertv(this != NULL);
|
||||
|
||||
// If this assertion fails, our own pointer was recently deleted.
|
||||
// Possibly you used a real pointer instead of a PointerTo at some
|
||||
// point, and the object was deleted when the PointerTo went out of
|
||||
// scope. Maybe you tried to create an automatic (local variable)
|
||||
// instance of a class that derives from ReferenceCount. Or maybe
|
||||
// your headers are out of sync, and you need to make clean in
|
||||
// direct or some higher tree.
|
||||
nassertv(_node_ref_count != -100);
|
||||
|
||||
ReferenceCount::operator = (copy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::Destructor
|
||||
// Access: Protected
|
||||
// Description: The ReferenceCount destructor is protected to
|
||||
// discourage users from accidentally trying to delete a
|
||||
// ReferenceCount pointer directly. This is almost
|
||||
// always a bad idea, since the destructor is not
|
||||
// virtual, and you've almost certainly got some pointer
|
||||
// to something that inherits from ReferenceCount, not
|
||||
// just a plain old ReferenceCount object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE NodeReferenceCount::
|
||||
~NodeReferenceCount() {
|
||||
nassertv(this != NULL);
|
||||
|
||||
// If this assertion fails, we're trying to delete an object that
|
||||
// was just deleted. Possibly you used a real pointer instead of a
|
||||
// PointerTo at some point, and the object was deleted when the
|
||||
// PointerTo went out of scope. Maybe you tried to create an
|
||||
// automatic (local variable) instance of a class that derives from
|
||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||
// need to make clean in direct or some higher tree.
|
||||
nassertv(_node_ref_count != -100);
|
||||
|
||||
// If this assertion fails, the reference counts are all screwed
|
||||
// up altogether. Maybe some errant code stomped all over memory
|
||||
// somewhere.
|
||||
nassertv(_node_ref_count >= 0);
|
||||
|
||||
// If this assertion fails, someone tried to delete this object
|
||||
// while its reference count was still positive. Maybe you tried
|
||||
// to point a PointerTo at a static object (a local variable,
|
||||
// instead of one allocated via new)? The test below against 0x7f
|
||||
// is supposed to check for that, but it's a pretty hokey test.
|
||||
|
||||
// Another possibility is you inadvertently omitted a copy
|
||||
// constructor for a ReferenceCount object, and then bitwise
|
||||
// copied a dynamically allocated value--reference count and
|
||||
// all--onto a locally allocated one.
|
||||
nassertv(_node_ref_count == 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Ok, all clear to delete. Now set the reference count to -100,
|
||||
// so we'll have a better chance of noticing if we happen to have
|
||||
// a stray pointer to it still out there.
|
||||
_node_ref_count = -100;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::get_node_ref_count
|
||||
// Access: Published
|
||||
// Description: Returns the current reference count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int NodeReferenceCount::
|
||||
get_node_ref_count() const {
|
||||
#ifdef _DEBUG
|
||||
test_ref_count_integrity();
|
||||
#endif
|
||||
return AtomicAdjust::get(_node_ref_count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::node_ref
|
||||
// Access: Published
|
||||
// Description: Explicitly increments the reference count.
|
||||
//
|
||||
// This function is const, even though it changes the
|
||||
// object, because generally fiddling with an object's
|
||||
// reference count isn't considered part of fiddling
|
||||
// with the object. An object might be const in other
|
||||
// ways, but we still need to accurately count the
|
||||
// number of references to it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NodeReferenceCount::
|
||||
node_ref() const {
|
||||
#ifdef _DEBUG
|
||||
nassertv(test_ref_count_integrity());
|
||||
#endif
|
||||
|
||||
ref();
|
||||
AtomicAdjust::inc(((NodeReferenceCount *)this)->_node_ref_count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::node_unref
|
||||
// Access: Published
|
||||
// Description: Explicitly decrements the reference count. Note that
|
||||
// the object will not be implicitly deleted by unref()
|
||||
// simply because the reference count drops to zero.
|
||||
// (Having a member function delete itself is
|
||||
// problematic; plus, we don't have a virtual destructor
|
||||
// anyway.) However, see the helper function
|
||||
// unref_delete().
|
||||
//
|
||||
// User code should avoid using ref() and unref()
|
||||
// directly, which can result in missed reference
|
||||
// counts. Instead, let a PointerTo object manage the
|
||||
// reference counting automatically.
|
||||
//
|
||||
// This function is const, even though it changes the
|
||||
// object, because generally fiddling with an object's
|
||||
// reference count isn't considered part of fiddling
|
||||
// with the object. An object might be const in other
|
||||
// ways, but we still need to accurately count the
|
||||
// number of references to it.
|
||||
//
|
||||
// The return value is true if the new reference count
|
||||
// is nonzero, false if it is zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool NodeReferenceCount::
|
||||
node_unref() const {
|
||||
#ifdef _DEBUG
|
||||
nassertr(test_ref_count_integrity(), 0);
|
||||
#endif
|
||||
|
||||
// If this assertion fails, you tried to unref an object with a
|
||||
// zero reference count. Are you using ref() and unref()
|
||||
// directly? Are you sure you can't use PointerTo's?
|
||||
nassertr(_node_ref_count > 0, 0);
|
||||
|
||||
unref();
|
||||
return AtomicAdjust::dec(((NodeReferenceCount *)this)->_node_ref_count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::test_ref_count_integrity
|
||||
// Access: Published
|
||||
// Description: Does some easy checks to make sure that the reference
|
||||
// count isn't completely bogus.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool NodeReferenceCount::
|
||||
test_ref_count_integrity() const {
|
||||
#ifndef NDEBUG
|
||||
return do_test_ref_count_integrity();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: node_unref_delete
|
||||
// Description: This global helper function will unref the given
|
||||
// ReferenceCount object, and if the reference count
|
||||
// reaches zero, automatically delete it. It can't be a
|
||||
// member function because it's usually a bad idea to
|
||||
// delete an object from within its own member function.
|
||||
// It's a template function so the destructor doesn't
|
||||
// have to be virtual.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class RefCountType>
|
||||
INLINE void
|
||||
node_unref_delete(RefCountType *ptr) {
|
||||
ptr->node_unref();
|
||||
if (ptr->get_ref_count() == 0) {
|
||||
ObjectDeletor *deletor = ObjectDeletor::get_global_ptr();
|
||||
if (deletor != (ObjectDeletor *)NULL) {
|
||||
ptr->ref();
|
||||
deletor->delete_object(RefCountDeleteWrapper<RefCountType>::do_delete, (void *)ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
delete ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeRefCountObj::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Base>
|
||||
INLINE NodeRefCountObj<Base>::
|
||||
NodeRefCountObj() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeRefCountObj::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Base>
|
||||
INLINE NodeRefCountObj<Base>::
|
||||
NodeRefCountObj(const Base ©) : Base(copy) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeRefCountObj::init_type
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Base>
|
||||
void NodeRefCountObj<Base>::
|
||||
init_type() {
|
||||
#if defined(HAVE_RTTI) && !defined(__EDG__)
|
||||
// If we have RTTI, we can determine the name of the base type.
|
||||
string base_name = typeid(Base).name();
|
||||
#else
|
||||
string base_name = "unknown";
|
||||
#endif
|
||||
|
||||
TypeHandle base_type = register_dynamic_type(base_name);
|
||||
|
||||
ReferenceCount::init_type();
|
||||
_type_handle =
|
||||
register_dynamic_type("NodeRefCountObj<" + base_name + ">",
|
||||
base_type, ReferenceCount::get_class_type());
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Filename: nodeReferenceCount.cxx
|
||||
// Created by: drose (01May06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "nodeReferenceCount.h"
|
||||
|
||||
TypeHandle NodeReferenceCount::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeReferenceCount::do_test_ref_count_integrity
|
||||
// Access: Protected
|
||||
// Description: Does some easy checks to make sure that the reference
|
||||
// count isn't completely bogus.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NodeReferenceCount::
|
||||
do_test_ref_count_integrity() const {
|
||||
nassertr(this != NULL, false);
|
||||
|
||||
// If this assertion fails, we're trying to delete an object that
|
||||
// was just deleted. Possibly you used a real pointer instead of a
|
||||
// PointerTo at some point, and the object was deleted when the
|
||||
// PointerTo went out of scope. Maybe you tried to create an
|
||||
// automatic (local variable) instance of a class that derives from
|
||||
// ReferenceCount. Or maybe your headers are out of sync, and you
|
||||
// need to make clean in direct or some higher tree.
|
||||
nassertr(_node_ref_count != -100, false);
|
||||
|
||||
// If this assertion fails, the reference counts are all screwed
|
||||
// up altogether. Maybe some errant code stomped all over memory
|
||||
// somewhere.
|
||||
nassertr(_node_ref_count >= 0, false);
|
||||
|
||||
return ReferenceCount::do_test_ref_count_integrity();
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
// Filename: nodeReferenceCount.h
|
||||
// Created by: drose (01May06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 NODEREFERENCECOUNT_H
|
||||
#define NODEREFERENCECOUNT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "referenceCount.h"
|
||||
#include "objectDeletor.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NodeReferenceCount
|
||||
// Description : This class specializes ReferenceCount to add an
|
||||
// additional counter, called node_ref_count, for the
|
||||
// purposes of counting the number of times the object
|
||||
// is referenced by a "node", whatever that may mean in
|
||||
// context.
|
||||
//
|
||||
// The new methods node_ref() and node_unref()
|
||||
// automatically increment and decrement the primary
|
||||
// reference count as well. There also exists a
|
||||
// NodePointerTo<> class to maintain the node_ref
|
||||
// counters automatically.
|
||||
//
|
||||
// See also CachedTypedWritableReferenceCount, which is
|
||||
// similar in principle, as well as
|
||||
// NodeCachedReferenceCount, which combines both of
|
||||
// these.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS NodeReferenceCount : public ReferenceCount {
|
||||
protected:
|
||||
INLINE NodeReferenceCount();
|
||||
INLINE NodeReferenceCount(const NodeReferenceCount ©);
|
||||
INLINE void operator = (const NodeReferenceCount ©);
|
||||
INLINE ~NodeReferenceCount();
|
||||
|
||||
PUBLISHED:
|
||||
INLINE int get_node_ref_count() const;
|
||||
INLINE void node_ref() const;
|
||||
INLINE bool node_unref() const;
|
||||
INLINE bool test_ref_count_integrity() const;
|
||||
|
||||
protected:
|
||||
bool do_test_ref_count_integrity() const;
|
||||
|
||||
private:
|
||||
PN_int32 _node_ref_count;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
|
||||
static void init_type() {
|
||||
ReferenceCount::init_type();
|
||||
register_type(_type_handle, "NodeReferenceCount",
|
||||
ReferenceCount::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
template<class RefCountType>
|
||||
INLINE void node_unref_delete(RefCountType *ptr);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NodeRefCountObj
|
||||
// Description : This works like RefCountObj, but it inherits from
|
||||
// NodeReferenceCount instead of ReferenceCount.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Base>
|
||||
class NodeRefCountObj : public NodeReferenceCount, public Base {
|
||||
public:
|
||||
INLINE NodeRefCountObj();
|
||||
INLINE NodeRefCountObj(const Base ©);
|
||||
ALLOC_DELETED_CHAIN(NodeRefCountObj<Base>);
|
||||
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type();
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "nodeReferenceCount.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ pvector<Element> ConstPointerToArray<Element>::_empty_array;
|
|||
template<class Element>
|
||||
INLINE PointerToArray<Element>::
|
||||
PointerToArray() :
|
||||
PointerToBase<RefCountObj<pvector<Element> > >((RefCountObj<pvector<Element> > *)NULL)
|
||||
PointerToBase<NodeRefCountObj<pvector<Element> > >((NodeRefCountObj<pvector<Element> > *)NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ PointerToArray<Element>::empty_array(size_type n) {
|
|||
template<class Element>
|
||||
INLINE PointerToArray<Element>::
|
||||
PointerToArray(size_type n, const Element &value) :
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(new RefCountObj<pvector<Element> >) {
|
||||
PointerToBase<NodeRefCountObj<pvector<Element> > >(new NodeRefCountObj<pvector<Element> >) {
|
||||
((To *)(this->_void_ptr))->reserve(n);
|
||||
insert(begin(), n, value);
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ PointerToArray(size_type n, const Element &value) :
|
|||
template<class Element>
|
||||
INLINE PointerToArray<Element>::
|
||||
PointerToArray(const PointerToArray<Element> ©) :
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(copy)
|
||||
PointerToBase<NodeRefCountObj<pvector<Element> > >(copy)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ template<class Element>
|
|||
INLINE TYPENAME PointerToArray<Element>::size_type PointerToArray<Element>::
|
||||
max_size() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
return ((To *)(this->_void_ptr))->max_size();
|
||||
}
|
||||
|
|
@ -170,7 +170,7 @@ template<class Element>
|
|||
INLINE void PointerToArray<Element>::
|
||||
reserve(TYPENAME PointerToArray<Element>::size_type n) {
|
||||
if ((this->_void_ptr) == NULL) {
|
||||
reassign(new RefCountObj<pvector<Element> >);
|
||||
reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
((To *)(this->_void_ptr))->reserve(n);
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ template<class Element>
|
|||
INLINE TYPENAME PointerToArray<Element>::reference PointerToArray<Element>::
|
||||
front() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!((To *)(this->_void_ptr))->empty()) {
|
||||
((To *)(this->_void_ptr))->push_back(Element());
|
||||
|
|
@ -213,7 +213,7 @@ template<class Element>
|
|||
INLINE TYPENAME PointerToArray<Element>::reference PointerToArray<Element>::
|
||||
back() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!((To *)(this->_void_ptr))->empty()) {
|
||||
((To *)(this->_void_ptr))->push_back(Element());
|
||||
|
|
@ -230,7 +230,7 @@ template<class Element>
|
|||
INLINE TYPENAME PointerToArray<Element>::iterator PointerToArray<Element>::
|
||||
insert(iterator position, const Element &x) {
|
||||
if ((this->_void_ptr) == NULL) {
|
||||
reassign(new RefCountObj<pvector<Element> >);
|
||||
reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
position = end();
|
||||
}
|
||||
nassertr(position >= ((To *)(this->_void_ptr))->begin() &&
|
||||
|
|
@ -247,7 +247,7 @@ template<class Element>
|
|||
INLINE void PointerToArray<Element>::
|
||||
insert(iterator position, size_type n, const Element &x) {
|
||||
if ((this->_void_ptr) == NULL) {
|
||||
reassign(new RefCountObj<pvector<Element> >);
|
||||
reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
position = end();
|
||||
}
|
||||
nassertv(position >= ((To *)(this->_void_ptr))->begin() &&
|
||||
|
|
@ -293,7 +293,7 @@ template<class Element>
|
|||
INLINE TYPENAME PointerToArray<Element>::reference PointerToArray<Element>::
|
||||
operator [](size_type n) const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!((To *)(this->_void_ptr))->empty()) {
|
||||
((To *)(this->_void_ptr))->push_back(Element());
|
||||
|
|
@ -354,7 +354,7 @@ template<class Element>
|
|||
INLINE void PointerToArray<Element>::
|
||||
push_back(const Element &x) {
|
||||
if ((this->_void_ptr) == NULL) {
|
||||
reassign(new RefCountObj<pvector<Element> >);
|
||||
reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
((To *)(this->_void_ptr))->push_back(x);
|
||||
}
|
||||
|
|
@ -368,7 +368,7 @@ template<class Element>
|
|||
INLINE void PointerToArray<Element>::
|
||||
pop_back() {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertv(!((To *)(this->_void_ptr))->empty());
|
||||
((To *)(this->_void_ptr))->pop_back();
|
||||
|
|
@ -385,7 +385,7 @@ template<class Element>
|
|||
INLINE void PointerToArray<Element>::
|
||||
make_empty() {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertv(!((To *)(this->_void_ptr))->empty());
|
||||
((To *)(this->_void_ptr))->clear();
|
||||
|
|
@ -429,7 +429,7 @@ template<class Element>
|
|||
INLINE pvector<Element> &PointerToArray<Element>::
|
||||
v() const {
|
||||
if ((this->_void_ptr) == NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
return *((To *)(this->_void_ptr));
|
||||
}
|
||||
|
|
@ -468,6 +468,43 @@ get_ref_count() const {
|
|||
return ((this->_void_ptr) == NULL) ? 0 : ((To *)(this->_void_ptr))->get_ref_count();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::get_node_ref_count
|
||||
// Access: Public
|
||||
// Description: Returns the node_ref of the underlying vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE int PointerToArray<Element>::
|
||||
get_node_ref_count() const {
|
||||
return ((this->_void_ptr) == NULL) ? 0 : ((To *)(this->_void_ptr))->get_node_ref_count();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::node_ref
|
||||
// Access: Public
|
||||
// Description: Increments the node_ref of the underlying vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
node_ref() const {
|
||||
if ((this->_void_ptr) == NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
((To *)(this->_void_ptr))->node_ref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::node_unref
|
||||
// Access: Public
|
||||
// Description: Decrements the node_ref of the underlying vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE bool PointerToArray<Element>::
|
||||
node_unref() const {
|
||||
nassertr((this->_void_ptr) != NULL, true);
|
||||
return ((To *)(this->_void_ptr))->node_unref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::Assignment operator
|
||||
// Access: Public
|
||||
|
|
@ -475,7 +512,7 @@ get_ref_count() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE PointerToArray<Element> &PointerToArray<Element>::
|
||||
operator = (RefCountObj<pvector<Element> > *ptr) {
|
||||
operator = (NodeRefCountObj<pvector<Element> > *ptr) {
|
||||
reassign(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -502,7 +539,7 @@ operator = (const PointerToArray<Element> ©) {
|
|||
template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
clear() {
|
||||
reassign((RefCountObj<pvector<Element> > *)NULL);
|
||||
reassign((NodeRefCountObj<pvector<Element> > *)NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -515,7 +552,7 @@ clear() {
|
|||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::
|
||||
ConstPointerToArray() :
|
||||
PointerToBase<RefCountObj<pvector<Element> > >((RefCountObj<pvector<Element> > *)NULL)
|
||||
PointerToBase<NodeRefCountObj<pvector<Element> > >((NodeRefCountObj<pvector<Element> > *)NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -527,7 +564,7 @@ ConstPointerToArray() :
|
|||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::
|
||||
ConstPointerToArray(const PointerToArray<Element> ©) :
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(copy)
|
||||
PointerToBase<NodeRefCountObj<pvector<Element> > >(copy)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -539,7 +576,7 @@ ConstPointerToArray(const PointerToArray<Element> ©) :
|
|||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::
|
||||
ConstPointerToArray(const ConstPointerToArray<Element> ©) :
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(copy)
|
||||
PointerToBase<NodeRefCountObj<pvector<Element> > >(copy)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -619,7 +656,7 @@ template<class Element>
|
|||
INLINE TYPENAME ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
|
||||
max_size() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
return ((To *)(this->_void_ptr))->max_size();
|
||||
}
|
||||
|
|
@ -644,7 +681,7 @@ template<class Element>
|
|||
INLINE TYPENAME ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
|
||||
capacity() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
return ((To *)(this->_void_ptr))->capacity();
|
||||
}
|
||||
|
|
@ -658,7 +695,7 @@ template<class Element>
|
|||
INLINE TYPENAME ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||
front() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!((To *)(this->_void_ptr))->empty()) {
|
||||
((To *)(this->_void_ptr))->push_back(Element());
|
||||
|
|
@ -675,7 +712,7 @@ template<class Element>
|
|||
INLINE TYPENAME ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||
back() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!((To *)(this->_void_ptr))->empty()) {
|
||||
((To *)(this->_void_ptr))->push_back(Element());
|
||||
|
|
@ -693,7 +730,7 @@ template<class Element>
|
|||
INLINE TYPENAME ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||
operator [](size_type n) const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!((To *)(this->_void_ptr))->empty()) {
|
||||
((To *)(this->_void_ptr))->push_back(Element());
|
||||
|
|
@ -767,7 +804,7 @@ template<class Element>
|
|||
INLINE const pvector<Element> &ConstPointerToArray<Element>::
|
||||
v() const {
|
||||
nassertd((this->_void_ptr) != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
return *(To *)(this->_void_ptr);
|
||||
}
|
||||
|
|
@ -783,6 +820,43 @@ get_ref_count() const {
|
|||
return ((this->_void_ptr) == NULL) ? 0 : ((To *)(this->_void_ptr))->get_ref_count();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConstPointerToArray::get_node_ref_count
|
||||
// Access: Public
|
||||
// Description: Returns the node_ref of the underlying vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE int ConstPointerToArray<Element>::
|
||||
get_node_ref_count() const {
|
||||
return ((this->_void_ptr) == NULL) ? 0 : ((To *)(this->_void_ptr))->get_node_ref_count();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConstPointerToArray::node_ref
|
||||
// Access: Public
|
||||
// Description: Increments the node_ref of the underlying vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE void ConstPointerToArray<Element>::
|
||||
node_ref() const {
|
||||
if ((this->_void_ptr) == NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new NodeRefCountObj<pvector<Element> >);
|
||||
}
|
||||
((To *)(this->_void_ptr))->node_ref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConstPointerToArray::node_unref
|
||||
// Access: Public
|
||||
// Description: Decrements the node_ref of the underlying vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE bool ConstPointerToArray<Element>::
|
||||
node_unref() const {
|
||||
nassertr((this->_void_ptr) != NULL, true);
|
||||
return ((To *)(this->_void_ptr))->node_unref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConstPointerToArray::Assignment operator
|
||||
// Access: Public
|
||||
|
|
@ -790,7 +864,7 @@ get_ref_count() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
|
||||
operator = (RefCountObj<pvector<Element> > *ptr) {
|
||||
operator = (NodeRefCountObj<pvector<Element> > *ptr) {
|
||||
reassign(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -829,6 +903,6 @@ operator = (const ConstPointerToArray<Element> ©) {
|
|||
template<class Element>
|
||||
INLINE void ConstPointerToArray<Element>::
|
||||
clear() {
|
||||
reassign((RefCountObj<pvector<Element> > *)NULL);
|
||||
reassign((NodeRefCountObj<pvector<Element> > *)NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "referenceCount.h"
|
||||
#include "nodeReferenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pvector.h"
|
||||
|
||||
|
|
@ -87,11 +87,21 @@
|
|||
// element. This is actually implemented as an STL
|
||||
// vector, using the RefCountObj class to wrap it up
|
||||
// with a reference count.
|
||||
//
|
||||
// We actually inherit from NodeRefCountObj these days,
|
||||
// which adds node_ref() and node_unref() to the
|
||||
// standard ref() and unref(). This is particularly
|
||||
// useful for GeomVertexArrayData; other classes may or
|
||||
// may not find this additional counter useful, but
|
||||
// since it adds relatively little overhead (compared
|
||||
// with what is presumably a largish array), we go ahead
|
||||
// and add it here, even though it is inherited by many
|
||||
// different parts of the system that may not use it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class Element>
|
||||
class PointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
|
||||
class PointerToArray : public PointerToBase<NodeRefCountObj<pvector<Element> > > {
|
||||
public:
|
||||
typedef TYPENAME PointerToBase<RefCountObj<pvector<Element> > >::To To;
|
||||
typedef TYPENAME PointerToBase<NodeRefCountObj<pvector<Element> > >::To To;
|
||||
typedef TYPENAME pvector<Element>::value_type value_type;
|
||||
typedef TYPENAME pvector<Element>::reference reference;
|
||||
typedef TYPENAME pvector<Element>::const_reference const_reference;
|
||||
|
|
@ -176,9 +186,13 @@ public:
|
|||
|
||||
INLINE int get_ref_count() const;
|
||||
|
||||
INLINE int get_node_ref_count() const;
|
||||
INLINE void node_ref() const;
|
||||
INLINE bool node_unref() const;
|
||||
|
||||
// Reassignment is by pointer, not memberwise as with a vector.
|
||||
INLINE PointerToArray<Element> &
|
||||
operator = (RefCountObj<pvector<Element> > *ptr);
|
||||
operator = (NodeRefCountObj<pvector<Element> > *ptr);
|
||||
INLINE PointerToArray<Element> &
|
||||
operator = (const PointerToArray<Element> ©);
|
||||
INLINE void clear();
|
||||
|
|
@ -198,9 +212,9 @@ private:
|
|||
// may not be modified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class Element>
|
||||
class ConstPointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
|
||||
class ConstPointerToArray : public PointerToBase<NodeRefCountObj<pvector<Element> > > {
|
||||
public:
|
||||
typedef TYPENAME PointerToBase<RefCountObj<pvector<Element> > >::To To;
|
||||
typedef TYPENAME PointerToBase<NodeRefCountObj<pvector<Element> > >::To To;
|
||||
typedef TYPENAME pvector<Element>::value_type value_type;
|
||||
typedef TYPENAME pvector<Element>::const_reference reference;
|
||||
typedef TYPENAME pvector<Element>::const_reference const_reference;
|
||||
|
|
@ -258,9 +272,13 @@ public:
|
|||
|
||||
INLINE int get_ref_count() const;
|
||||
|
||||
INLINE int get_node_ref_count() const;
|
||||
INLINE void node_ref() const;
|
||||
INLINE bool node_unref() const;
|
||||
|
||||
// Reassignment is by pointer, not memberwise as with a vector.
|
||||
INLINE ConstPointerToArray<Element> &
|
||||
operator = (RefCountObj<pvector<Element> > *ptr);
|
||||
operator = (NodeRefCountObj<pvector<Element> > *ptr);
|
||||
INLINE ConstPointerToArray<Element> &
|
||||
operator = (const PointerToArray<Element> ©);
|
||||
INLINE ConstPointerToArray<Element> &
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ get_geom_rendering() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Geom::UsageHint Geom::
|
||||
get_usage_hint() const {
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
if (!cdata->_got_usage_hint) {
|
||||
CDWriter cdataw(((Geom *)this)->_cycler, cdata, false);
|
||||
((Geom *)this)->reset_usage_hint(cdataw);
|
||||
|
|
@ -463,7 +463,7 @@ INLINE GeomPipelineReader::
|
|||
GeomPipelineReader(const Geom *object, Thread *current_thread) :
|
||||
_object(object),
|
||||
_current_thread(current_thread),
|
||||
_cdata(object->_cycler.read(current_thread))
|
||||
_cdata(object->_cycler.read_unlocked(current_thread))
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
|
|
@ -506,7 +506,7 @@ INLINE GeomPipelineReader::
|
|||
nassertv(_cdata->test_ref_count_nonzero());
|
||||
#endif // DO_PIPELINING
|
||||
#endif // _DEBUG
|
||||
_object->_cycler.release_read(_cdata);
|
||||
// _object->_cycler.release_read(_cdata);
|
||||
|
||||
#ifdef _DEBUG
|
||||
_object = NULL;
|
||||
|
|
@ -534,19 +534,6 @@ get_current_thread() const {
|
|||
return _current_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPipelineReader::check_usage_hint
|
||||
// Access: Public
|
||||
// Description: Ensures that the Geom's usage_hint cache has been
|
||||
// computed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GeomPipelineReader::
|
||||
check_usage_hint() const {
|
||||
if (!_cdata->_got_usage_hint) {
|
||||
((Geom *)_object)->reset_usage_hint((Geom::CData *)_cdata);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPipelineReader::get_primitive_type
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -729,7 +729,7 @@ check_valid(const GeomVertexData *vertex_data) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(BoundingVolume) Geom::
|
||||
get_bounds(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
CDLockedReader cdata(_cycler, current_thread);
|
||||
if (cdata->_internal_bounds_stale) {
|
||||
CDWriter cdataw(((Geom *)this)->_cycler, cdata, false);
|
||||
if (cdataw->_user_bounds != (BoundingVolume *)NULL) {
|
||||
|
|
@ -1346,6 +1346,35 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
_modified = Geom::get_next_modified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPipelineReader::check_usage_hint
|
||||
// Access: Public
|
||||
// Description: Ensures that the Geom's usage_hint cache has been
|
||||
// computed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomPipelineReader::
|
||||
check_usage_hint() const {
|
||||
if (!_cdata->_got_usage_hint) {
|
||||
// We'll need to get a fresh pointer, since another thread might
|
||||
// already have modified the pointer on the object since we
|
||||
// queried it.
|
||||
{
|
||||
Geom::CDWriter fresh_cdata(((Geom *)_object)->_cycler, _current_thread);
|
||||
if (!fresh_cdata->_got_usage_hint) {
|
||||
// The cache is still stale. We have to do the work of
|
||||
// freshening it.
|
||||
((Geom *)_object)->reset_usage_hint(fresh_cdata);
|
||||
nassertv(fresh_cdata->_got_usage_hint);
|
||||
}
|
||||
|
||||
// Save the new pointer, and then let the lock release itself.
|
||||
((GeomPipelineReader *)this)->_cdata = fresh_cdata;
|
||||
}
|
||||
}
|
||||
|
||||
nassertv(_cdata->_got_usage_hint);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPipelineReader::check_valid
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "pandabase.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
|
|
@ -261,6 +262,7 @@ private:
|
|||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataStageReader<CData> CDStageReader;
|
||||
|
|
@ -330,7 +332,7 @@ public:
|
|||
INLINE const Geom *get_object() const;
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
INLINE void check_usage_hint() const;
|
||||
void check_usage_hint() const;
|
||||
|
||||
INLINE PrimitiveType get_primitive_type() const;
|
||||
INLINE ShadeModel get_shade_model() const;
|
||||
|
|
@ -350,7 +352,7 @@ public:
|
|||
private:
|
||||
const Geom *_object;
|
||||
Thread *_current_thread;
|
||||
const Geom::CData *_cdata;
|
||||
CPT(Geom::CData) _cdata;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const Geom &obj);
|
||||
|
|
|
|||
|
|
@ -82,10 +82,9 @@ record(Thread *current_thread) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GeomCacheEntry::
|
||||
refresh(Thread *current_thread) {
|
||||
nassertv(_next != (GeomCacheEntry *)NULL && _prev != (GeomCacheEntry *)NULL);
|
||||
|
||||
GeomCacheManager *cache_mgr = GeomCacheManager::get_global_ptr();
|
||||
MutexHolder holder(cache_mgr->_lock);
|
||||
nassertv(_next != (GeomCacheEntry *)NULL && _prev != (GeomCacheEntry *)NULL);
|
||||
|
||||
remove_from_list();
|
||||
insert_before(cache_mgr->_list);
|
||||
|
|
|
|||
|
|
@ -478,7 +478,7 @@ GeomPrimitivePipelineReader(const GeomPrimitive *object,
|
|||
Thread *current_thread) :
|
||||
_object(object),
|
||||
_current_thread(current_thread),
|
||||
_cdata(object->_cycler.read(current_thread)),
|
||||
_cdata(object->_cycler.read_unlocked(current_thread)),
|
||||
_vertices_reader(NULL)
|
||||
{
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
|
|
@ -529,7 +529,7 @@ INLINE GeomPrimitivePipelineReader::
|
|||
nassertv(_cdata->test_ref_count_nonzero());
|
||||
#endif // DO_PIPELINING
|
||||
#endif // _DEBUG
|
||||
_object->_cycler.release_read(_cdata);
|
||||
// _object->_cycler.release_read(_cdata);
|
||||
|
||||
#ifdef _DEBUG
|
||||
_vertices_reader = NULL;
|
||||
|
|
@ -558,19 +558,6 @@ get_current_thread() const {
|
|||
return _current_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPrimitivePipelineReader::check_minmax
|
||||
// Access: Public
|
||||
// Description: Ensures that the primitive's minmax cache has been
|
||||
// computed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GeomPrimitivePipelineReader::
|
||||
check_minmax() const {
|
||||
if (!_cdata->_got_minmax) {
|
||||
((GeomPrimitive *)_object)->recompute_minmax((GeomPrimitive::CData *)_cdata);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPrimitivePipelineReader::get_shade_model
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -1491,6 +1491,34 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
_got_minmax = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPrimitivePipelineReader::check_minmax
|
||||
// Access: Public
|
||||
// Description: Ensures that the primitive's minmax cache has been
|
||||
// computed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomPrimitivePipelineReader::
|
||||
check_minmax() const {
|
||||
if (!_cdata->_got_minmax) {
|
||||
// We'll need to get a fresh pointer, since another thread might
|
||||
// already have modified the pointer on the object since we
|
||||
// queried it.
|
||||
{
|
||||
GeomPrimitive::CDWriter fresh_cdata(((GeomPrimitive *)_object)->_cycler, _current_thread);
|
||||
if (!fresh_cdata->_got_minmax) {
|
||||
// The cache is still stale. We have to do the work of
|
||||
// freshening it.
|
||||
((GeomPrimitive *)_object)->recompute_minmax(fresh_cdata);
|
||||
nassertv(fresh_cdata->_got_minmax);
|
||||
}
|
||||
|
||||
// Save the new pointer, and then let the lock release itself.
|
||||
((GeomPrimitivePipelineReader *)this)->_cdata = fresh_cdata;
|
||||
}
|
||||
}
|
||||
|
||||
nassertv(_cdata->_got_minmax);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomPrimitivePipelineReader::get_first_vertex
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ public:
|
|||
INLINE const GeomPrimitive *get_object() const;
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
INLINE void check_minmax() const;
|
||||
void check_minmax() const;
|
||||
|
||||
INLINE ShadeModel get_shade_model() const;
|
||||
INLINE UsageHint get_usage_hint() const;
|
||||
|
|
@ -334,7 +334,7 @@ public:
|
|||
private:
|
||||
const GeomPrimitive *_object;
|
||||
Thread *_current_thread;
|
||||
const GeomPrimitive::CData *_cdata;
|
||||
CPT(GeomPrimitive::CData) _cdata;
|
||||
GeomVertexArrayDataPipelineReader *_vertices_reader;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ INLINE GeomVertexArrayData::CData::
|
|||
CData() :
|
||||
_usage_hint(UH_unspecified)
|
||||
{
|
||||
_data.node_ref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -196,6 +197,7 @@ CData(const GeomVertexArrayData::CData ©) :
|
|||
_data(copy._data),
|
||||
_modified(copy._modified)
|
||||
{
|
||||
_data.node_ref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -293,7 +295,7 @@ GeomVertexArrayDataPipelineReader(const GeomVertexArrayData *object,
|
|||
Thread *current_thread) :
|
||||
GeomVertexArrayDataPipelineBase((GeomVertexArrayData *)object,
|
||||
current_thread,
|
||||
(GeomVertexArrayData::CData *)object->_cycler.read(current_thread))
|
||||
(GeomVertexArrayData::CData *)object->_cycler.read_unlocked(current_thread))
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
|
|
@ -338,7 +340,7 @@ INLINE GeomVertexArrayDataPipelineReader::
|
|||
nassertv(_cdata->test_ref_count_nonzero());
|
||||
#endif // DO_PIPELINING
|
||||
#endif // _DEBUG
|
||||
_object->_cycler.release_read(_cdata);
|
||||
// _object->_cycler.release_read(_cdata);
|
||||
|
||||
#ifdef _DEBUG
|
||||
_object = NULL;
|
||||
|
|
|
|||
|
|
@ -432,6 +432,9 @@ finalize(BamReader *manager) {
|
|||
// Now is the time to endian-reverse the data.
|
||||
cdata->_data = reverse_data_endianness(cdata->_data);
|
||||
}
|
||||
|
||||
// Now is also the time to node_ref the data.
|
||||
cdata->_data.node_ref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -470,6 +473,16 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
manager->read_cdata(scan, _cycler, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexArrayData::CData::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeomVertexArrayData::CData::
|
||||
~CData() {
|
||||
_data.node_unref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexArrayData::CData::make_copy
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -520,7 +533,7 @@ set_num_rows(int n) {
|
|||
int delta = n - (_cdata->_data.size() / stride);
|
||||
|
||||
if (delta != 0) {
|
||||
if (_cdata->_data.get_ref_count() > 1) {
|
||||
if (_cdata->_data.get_node_ref_count() > 1) {
|
||||
// Copy-on-write: the data is already reffed somewhere else,
|
||||
// so we're just going to make a copy.
|
||||
PTA_uchar new_data;
|
||||
|
|
@ -528,7 +541,9 @@ set_num_rows(int n) {
|
|||
new_data.insert(new_data.end(), n * stride, 0);
|
||||
memcpy(new_data, _cdata->_data,
|
||||
min((size_t)(n * stride), _cdata->_data.size()));
|
||||
_cdata->_data.node_unref();
|
||||
_cdata->_data = new_data;
|
||||
_cdata->_data.node_ref();
|
||||
|
||||
} else {
|
||||
// We've got the only reference to the data, so we can change
|
||||
|
|
@ -557,13 +572,16 @@ set_num_rows(int n) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
PTA_uchar GeomVertexArrayDataPipelineWriter::
|
||||
modify_data() {
|
||||
// Perform copy-on-write: if the reference count on the vertex data
|
||||
// is greater than 1, assume some other GeomVertexData has the same
|
||||
// pointer, so make a copy of it first.
|
||||
if (_cdata->_data.get_ref_count() > 1) {
|
||||
// Perform copy-on-write: if the *node* reference count on the
|
||||
// vertex data is greater than 1, assume some other
|
||||
// GeomVertexArrayData has the same pointer, so make a copy of it
|
||||
// first.
|
||||
if (_cdata->_data.get_node_ref_count() > 1) {
|
||||
PTA_uchar orig_data = _cdata->_data;
|
||||
_cdata->_data.node_unref();
|
||||
_cdata->_data = PTA_uchar();
|
||||
_cdata->_data.v() = orig_data.v();
|
||||
_cdata->_data.node_ref();
|
||||
}
|
||||
_cdata->_modified = Geom::get_next_modified();
|
||||
|
||||
|
|
@ -577,6 +595,8 @@ modify_data() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexArrayDataPipelineWriter::
|
||||
set_data(CPTA_uchar array) {
|
||||
_cdata->_data.node_unref();
|
||||
_cdata->_data = (PTA_uchar &)array;
|
||||
_cdata->_data.node_ref();
|
||||
_cdata->_modified = Geom::get_next_modified();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ private:
|
|||
public:
|
||||
INLINE CData();
|
||||
INLINE CData(const CData ©);
|
||||
virtual ~CData();
|
||||
ALLOC_DELETED_CHAIN(CData);
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg,
|
||||
|
|
@ -207,7 +208,7 @@ public:
|
|||
protected:
|
||||
GeomVertexArrayData *_object;
|
||||
Thread *_current_thread;
|
||||
GeomVertexArrayData::CData *_cdata;
|
||||
PT(GeomVertexArrayData::CData) _cdata;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ INLINE GeomVertexDataPipelineReader::
|
|||
GeomVertexDataPipelineReader(const GeomVertexData *object,
|
||||
Thread *current_thread) :
|
||||
GeomVertexDataPipelineBase((GeomVertexData *)object, current_thread,
|
||||
(GeomVertexData::CData *)object->_cycler.read(current_thread)),
|
||||
(GeomVertexData::CData *)object->_cycler.read_unlocked(current_thread)),
|
||||
_got_array_readers(false)
|
||||
{
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
|
|
@ -637,7 +637,7 @@ INLINE GeomVertexDataPipelineReader::
|
|||
nassertv(_cdata->test_ref_count_nonzero());
|
||||
#endif // DO_PIPELINING
|
||||
#endif // _DEBUG
|
||||
_object->_cycler.release_read(_cdata);
|
||||
// _object->_cycler.release_read(_cdata);
|
||||
|
||||
#ifdef _DEBUG
|
||||
_object = NULL;
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ set_format(const GeomVertexFormat *format) {
|
|||
Thread *current_thread = Thread::get_current_thread();
|
||||
nassertv(format->is_registered());
|
||||
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
CDLockedReader cdata(_cycler, current_thread);
|
||||
|
||||
if (format == cdata->_format) {
|
||||
// Trivially no-op.
|
||||
|
|
@ -902,7 +902,7 @@ set_color(const Colorf &color, int num_components,
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(GeomVertexData) GeomVertexData::
|
||||
animate_vertices(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
CDLockedReader cdata(_cycler, current_thread);
|
||||
|
||||
if (cdata->_format->get_animation().get_animation_type() != AT_panda) {
|
||||
return this;
|
||||
|
|
@ -1812,13 +1812,14 @@ set_num_rows(int n) {
|
|||
if (color_array >= 0 && orig_color_rows < n) {
|
||||
// We have just added some rows, fill the "color" column with
|
||||
// (1, 1, 1, 1), for the programmer's convenience.
|
||||
GeomVertexArrayData *array_data = _cdata->_arrays[color_array];
|
||||
GeomVertexArrayDataPipelineWriter *array_writer = _array_writers[color_array];
|
||||
const GeomVertexArrayFormat *array_format = array_writer->get_array_format();
|
||||
const GeomVertexColumn *column =
|
||||
array_data->get_array_format()->get_column(InternalName::get_color());
|
||||
int stride = array_data->get_array_format()->get_stride();
|
||||
array_format->get_column(InternalName::get_color());
|
||||
int stride = array_format->get_stride();
|
||||
unsigned char *start =
|
||||
array_data->modify_data() + column->get_start();
|
||||
unsigned char *stop = start + array_data->get_data_size_bytes();
|
||||
array_writer->modify_data() + column->get_start();
|
||||
unsigned char *stop = start + array_writer->get_data_size_bytes();
|
||||
unsigned char *pointer = start + stride * orig_color_rows;
|
||||
int num_values = column->get_num_values();
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "sliderTable.h"
|
||||
#include "internalName.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
|
|
@ -257,6 +258,7 @@ private:
|
|||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataStageReader<CData> CDStageReader;
|
||||
|
|
@ -341,7 +343,7 @@ public:
|
|||
protected:
|
||||
GeomVertexData *_object;
|
||||
Thread *_current_thread;
|
||||
GeomVertexData::CData *_cdata;
|
||||
PT(GeomVertexData::CData) _cdata;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ GeomVertexReader(const GeomVertexReader ©) :
|
|||
_current_thread(copy._current_thread),
|
||||
_packer(copy._packer),
|
||||
_stride(copy._stride),
|
||||
_data(copy._data),
|
||||
_pointer_begin(copy._pointer_begin),
|
||||
_pointer_end(copy._pointer_end),
|
||||
_pointer(copy._pointer),
|
||||
|
|
@ -167,6 +168,7 @@ operator = (const GeomVertexReader ©) {
|
|||
_current_thread = copy._current_thread;
|
||||
_packer = copy._packer;
|
||||
_stride = copy._stride;
|
||||
_data = copy._data;
|
||||
_pointer_begin = copy._pointer_begin;
|
||||
_pointer_end = copy._pointer_end;
|
||||
_pointer = copy._pointer;
|
||||
|
|
@ -510,7 +512,8 @@ get_packer() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GeomVertexReader::
|
||||
set_pointer(int row, const GeomVertexArrayDataPipelineReader *array_reader) {
|
||||
_pointer_begin = array_reader->get_data();
|
||||
_data = array_reader->get_data();
|
||||
_pointer_begin = _data;
|
||||
_pointer_end = _pointer_begin + array_reader->get_data_size_bytes();
|
||||
quick_set_pointer(row);
|
||||
}
|
||||
|
|
@ -526,7 +529,12 @@ INLINE void GeomVertexReader::
|
|||
quick_set_pointer(int row) {
|
||||
nassertv(has_column());
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) && !defined(HAVE_THREADS)
|
||||
// Make sure we still have the same pointer as stored the array. We
|
||||
// only perform this test in debug mode, because it is expensive,
|
||||
// and only in single-threaded mode, because in threaded mode
|
||||
// another thread might have reallocated the other pointer outside
|
||||
// of our control anyway.
|
||||
if (_vertex_data != (const GeomVertexData *)NULL) {
|
||||
const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
|
||||
nassertv(_pointer_begin == array_data->get_data());
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ private:
|
|||
GeomVertexColumn::Packer *_packer;
|
||||
int _stride;
|
||||
|
||||
CPTA_uchar _data;
|
||||
const unsigned char *_pointer_begin;
|
||||
const unsigned char *_pointer_end;
|
||||
const unsigned char *_pointer;
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ GeomVertexWriter(const GeomVertexWriter ©) :
|
|||
_current_thread(copy._current_thread),
|
||||
_packer(copy._packer),
|
||||
_stride(copy._stride),
|
||||
_data(copy._data),
|
||||
_pointer_begin(copy._pointer_begin),
|
||||
_pointer_end(copy._pointer_end),
|
||||
_pointer(copy._pointer),
|
||||
|
|
@ -165,6 +166,7 @@ operator = (const GeomVertexWriter ©) {
|
|||
_current_thread = copy._current_thread;
|
||||
_packer = copy._packer;
|
||||
_stride = copy._stride;
|
||||
_data = copy._data;
|
||||
_pointer_begin = copy._pointer_begin;
|
||||
_pointer_end = copy._pointer_end;
|
||||
_pointer = copy._pointer;
|
||||
|
|
@ -813,7 +815,8 @@ get_packer() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GeomVertexWriter::
|
||||
set_pointer(int row, GeomVertexArrayDataPipelineWriter *array_writer) {
|
||||
_pointer_begin = array_writer->modify_data();
|
||||
_data = array_writer->modify_data();
|
||||
_pointer_begin = _data;
|
||||
_pointer_end = _pointer_begin + array_writer->get_data_size_bytes();
|
||||
quick_set_pointer(row);
|
||||
}
|
||||
|
|
@ -829,7 +832,12 @@ INLINE void GeomVertexWriter::
|
|||
quick_set_pointer(int row) {
|
||||
nassertv(has_column());
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) && !defined(HAVE_THREADS)
|
||||
// Make sure we still have the same pointer as stored the array. We
|
||||
// only perform this test in debug mode, because it is expensive,
|
||||
// and only in single-threaded mode, because in threaded mode
|
||||
// another thread might have reallocated the other pointer outside
|
||||
// of our control anyway.
|
||||
if (_vertex_data != (const GeomVertexData *)NULL) {
|
||||
const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
|
||||
nassertv(_pointer_begin == array_data->get_data());
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ private:
|
|||
GeomVertexColumn::Packer *_packer;
|
||||
int _stride;
|
||||
|
||||
PTA_uchar _data;
|
||||
unsigned char *_pointer_begin;
|
||||
unsigned char *_pointer_end;
|
||||
unsigned char *_pointer;
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ set_weight(int n, float weight) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TransformBlend::
|
||||
update_blend(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
CDLockedReader cdata(_cycler, current_thread);
|
||||
if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
|
||||
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
|
||||
((TransformBlend *)this)->recompute_result(cdataw, current_thread);
|
||||
|
|
@ -290,7 +290,7 @@ transform_vector(LVector3f &vector, Thread *current_thread) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE UpdateSeq TransformBlend::
|
||||
get_modified(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
CDLockedReader cdata(_cycler, current_thread);
|
||||
if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
|
||||
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
|
||||
((TransformBlend *)this)->recompute_result(cdataw, current_thread);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "pvector.h"
|
||||
#include "ordered_vector.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "pipelineCycler.h"
|
||||
|
|
@ -114,6 +115,7 @@ private:
|
|||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ get_blend(int n) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE UpdateSeq TransformBlendTable::
|
||||
get_modified(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
|
||||
CDWriter cdataw(((TransformBlendTable *)this)->_cycler, cdata, false);
|
||||
((TransformBlendTable *)this)->recompute_modified(cdataw, current_thread);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "pmap.h"
|
||||
#include "indirectLess.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "pipelineCycler.h"
|
||||
|
|
@ -115,6 +116,7 @@ private:
|
|||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ get_next(int pipeline_stage, Thread *current_thread) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool NodePathComponent::
|
||||
fix_length(int pipeline_stage, Thread *current_thread) {
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
|
||||
int length_should_be = 1;
|
||||
if (cdata->_next != (NodePathComponent *)NULL) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "cycleData.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "cycleDataLockedStageReader.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
#include "cycleDataStageWriter.h"
|
||||
#include "pmutex.h"
|
||||
|
|
@ -100,6 +101,7 @@ private:
|
|||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataLockedStageReader<CData> CDLockedStageReader;
|
||||
typedef CycleDataStageReader<CData> CDStageReader;
|
||||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||
|
||||
|
|
|
|||
|
|
@ -1161,7 +1161,7 @@ INLINE PandaNodePipelineReader::
|
|||
PandaNodePipelineReader(const PandaNode *object, Thread *current_thread) :
|
||||
_object(object),
|
||||
_current_thread(current_thread),
|
||||
_cdata(object->_cycler.read(current_thread))
|
||||
_cdata(object->_cycler.read_unlocked(current_thread))
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
|
|
@ -1182,9 +1182,11 @@ PandaNodePipelineReader(const PandaNodePipelineReader ©) :
|
|||
_current_thread(copy._current_thread),
|
||||
_cdata(copy._cdata)
|
||||
{
|
||||
/*
|
||||
if (_cdata != (PandaNode::CData *)NULL) {
|
||||
_object->_cycler.increment_read(_cdata);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1196,16 +1198,20 @@ INLINE void PandaNodePipelineReader::
|
|||
operator = (const PandaNodePipelineReader ©) {
|
||||
nassertv(_current_thread == copy._current_thread);
|
||||
|
||||
/*
|
||||
if (_cdata != (PandaNode::CData *)NULL) {
|
||||
_object->_cycler.release_read(_cdata);
|
||||
}
|
||||
*/
|
||||
|
||||
_object = copy._object;
|
||||
_cdata = copy._cdata;
|
||||
|
||||
/*
|
||||
if (_cdata != (PandaNode::CData *)NULL) {
|
||||
_object->_cycler.increment_read(_cdata);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1215,9 +1221,11 @@ operator = (const PandaNodePipelineReader ©) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PandaNodePipelineReader::
|
||||
~PandaNodePipelineReader() {
|
||||
/*
|
||||
if (_cdata != (PandaNode::CData *)NULL) {
|
||||
_object->_cycler.release_read(_cdata);
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
_object = NULL;
|
||||
|
|
@ -1253,30 +1261,12 @@ get_current_thread() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PandaNodePipelineReader::
|
||||
release() {
|
||||
/*
|
||||
if (_cdata != (PandaNode::CData *)NULL) {
|
||||
_object->_cycler.release_read(_cdata);
|
||||
_cdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNodePipelineReader::check_bounds
|
||||
// Access: Public
|
||||
// Description: Ensures that the bounding volume is properly computed
|
||||
// on this node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PandaNodePipelineReader::
|
||||
check_bounds() const {
|
||||
nassertv(_cdata != (PandaNode::CData *)NULL);
|
||||
if (_cdata->_last_update != _cdata->_next_update) {
|
||||
// The cache is stale; it needs to be rebuilt.
|
||||
|
||||
// We should technically drop _cdata while we do this operation,
|
||||
// but at the moment, it doesn't really matter.
|
||||
int pipeline_stage = _current_thread->get_pipeline_stage();
|
||||
PandaNode::CDStageReader fresh_cdata(_object->_cycler, pipeline_stage, _current_thread);
|
||||
((PandaNode *)_object)->update_bounds(pipeline_stage, fresh_cdata);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1404,8 +1404,7 @@ copy_tags(PandaNode *other) {
|
|||
Thread *current_thread = Thread::get_current_thread();
|
||||
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||
CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
|
||||
CDStageReader cdatar(other->_cycler, pipeline_stage,
|
||||
current_thread);
|
||||
CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
|
||||
|
||||
TagData::const_iterator ti;
|
||||
for (ti = cdatar->_tag_data.begin();
|
||||
|
|
@ -1565,7 +1564,7 @@ DrawMask PandaNode::
|
|||
get_net_draw_control_mask() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
if (cdata->_last_update != cdata->_next_update) {
|
||||
// The cache is stale; it needs to be rebuilt.
|
||||
CDStageWriter cdataw =
|
||||
|
|
@ -1595,7 +1594,7 @@ DrawMask PandaNode::
|
|||
get_net_draw_show_mask() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
if (cdata->_last_update != cdata->_next_update) {
|
||||
// The cache is stale; it needs to be rebuilt.
|
||||
CDStageWriter cdataw =
|
||||
|
|
@ -1667,7 +1666,7 @@ get_legal_collide_mask() const {
|
|||
CollideMask PandaNode::
|
||||
get_net_collide_mask(Thread *current_thread) const {
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
if (cdata->_last_update != cdata->_next_update) {
|
||||
// The cache is stale; it needs to be rebuilt.
|
||||
CDStageWriter cdataw =
|
||||
|
|
@ -1687,7 +1686,7 @@ get_net_collide_mask(Thread *current_thread) const {
|
|||
CPT(RenderAttrib) PandaNode::
|
||||
get_off_clip_planes(Thread *current_thread) const {
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
if (cdata->_last_update != cdata->_next_update) {
|
||||
// The cache is stale; it needs to be rebuilt.
|
||||
CDStageWriter cdataw =
|
||||
|
|
@ -1808,7 +1807,7 @@ set_bound(const BoundingVolume *volume) {
|
|||
CPT(BoundingVolume) PandaNode::
|
||||
get_bounds(Thread *current_thread) const {
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
if (cdata->_last_update != cdata->_next_update) {
|
||||
// The cache is stale; it needs to be rebuilt.
|
||||
CPT(BoundingVolume) result;
|
||||
|
|
@ -1900,7 +1899,7 @@ as_light() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CPT(BoundingVolume) PandaNode::
|
||||
get_internal_bounds(int pipeline_stage, Thread *current_thread) const {
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
if (cdata->_internal_bounds_stale) {
|
||||
CDStageWriter cdataw(((PandaNode *)this)->_cycler, pipeline_stage, cdata);
|
||||
if (cdataw->_user_bounds != (BoundingVolume *)NULL) {
|
||||
|
|
@ -2868,7 +2867,7 @@ r_list_descendants(ostream &out, int indent_level) const {
|
|||
// released. The new value is returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode::CDStageWriter PandaNode::
|
||||
update_bounds(int pipeline_stage, PandaNode::CDStageReader &cdata) {
|
||||
update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
|
||||
// We might need to try this a couple of times, in case someone else
|
||||
// steps on our result.
|
||||
if (drawmask_cat.is_debug()) {
|
||||
|
|
@ -2878,24 +2877,20 @@ update_bounds(int pipeline_stage, PandaNode::CDStageReader &cdata) {
|
|||
Thread *current_thread = cdata.get_current_thread();
|
||||
|
||||
do {
|
||||
// Grab the last_update counter, then release the lock.
|
||||
// Grab the last_update counter.
|
||||
UpdateSeq last_update = cdata->_last_update;
|
||||
UpdateSeq next_update = cdata->_next_update;
|
||||
nassertr(last_update != next_update, CDStageWriter(_cycler, pipeline_stage, cdata));
|
||||
_cycler.release_read_stage(pipeline_stage, cdata.take_pointer());
|
||||
|
||||
// Start with a clean slate, or at least with the contents of the
|
||||
// node itself.
|
||||
CollideMask net_collide_mask;
|
||||
CollideMask net_collide_mask = cdata->_into_collide_mask;
|
||||
DrawMask net_draw_control_mask, net_draw_show_mask;
|
||||
DrawMask draw_control_mask, draw_show_mask;
|
||||
draw_control_mask = net_draw_control_mask = cdata->_draw_control_mask;
|
||||
draw_show_mask = net_draw_show_mask = cdata->_draw_show_mask;
|
||||
bool renderable = is_renderable();
|
||||
{
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
net_collide_mask = cdata->_into_collide_mask;
|
||||
draw_control_mask = net_draw_control_mask = cdata->_draw_control_mask;
|
||||
draw_show_mask = net_draw_show_mask = cdata->_draw_show_mask;
|
||||
}
|
||||
|
||||
if (!renderable) {
|
||||
// This is not a "renderable" node. This means that this node
|
||||
// does not itself contribute any bits to net_draw_show_mask or
|
||||
|
|
@ -2914,15 +2909,18 @@ update_bounds(int pipeline_stage, PandaNode::CDStageReader &cdata) {
|
|||
<< "\ndraw_show_mask = " << draw_show_mask
|
||||
<< "\n";
|
||||
}
|
||||
CPT(RenderAttrib) off_clip_planes;
|
||||
{
|
||||
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
||||
off_clip_planes = cdata->_state->get_clip_plane();
|
||||
}
|
||||
CPT(RenderAttrib) off_clip_planes = cdata->_state->get_clip_plane();
|
||||
if (off_clip_planes == (RenderAttrib *)NULL) {
|
||||
off_clip_planes = ClipPlaneAttrib::make();
|
||||
}
|
||||
|
||||
// Also get the list of the node's children.
|
||||
Children children(cdata);
|
||||
|
||||
// Now that we've got all the data we need from the node, we can
|
||||
// release the lock.
|
||||
_cycler.release_read_stage(pipeline_stage, cdata.take_pointer());
|
||||
|
||||
// We need to keep references to the bounding volumes, since in a
|
||||
// threaded environment the pointers might go away while we're
|
||||
// working (since we're not holding a lock on our set of children
|
||||
|
|
@ -2937,7 +2935,6 @@ update_bounds(int pipeline_stage, PandaNode::CDStageReader &cdata) {
|
|||
child_volumes.push_back(internal_bounds);
|
||||
|
||||
// Now expand those contents to include all of our children.
|
||||
Children children = get_children(current_thread);
|
||||
int num_children = children.get_num_children();
|
||||
|
||||
for (int i = 0; i < num_children; ++i) {
|
||||
|
|
@ -2945,7 +2942,7 @@ update_bounds(int pipeline_stage, PandaNode::CDStageReader &cdata) {
|
|||
|
||||
const ClipPlaneAttrib *orig_cp = DCAST(ClipPlaneAttrib, off_clip_planes);
|
||||
|
||||
CDStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
|
||||
CDLockedStageReader child_cdata(child->_cycler, pipeline_stage, current_thread);
|
||||
if (child_cdata->_last_update != child_cdata->_next_update) {
|
||||
// Child needs update.
|
||||
CDStageWriter child_cdataw = child->update_bounds(pipeline_stage, child_cdata);
|
||||
|
|
@ -3089,7 +3086,7 @@ update_bounds(int pipeline_stage, PandaNode::CDStageReader &cdata) {
|
|||
|
||||
// We need to go around again. Release the write lock, and grab
|
||||
// the read lock back.
|
||||
cdata = CDStageReader(_cycler, pipeline_stage, current_thread);
|
||||
cdata = CDLockedStageReader(_cycler, pipeline_stage, current_thread);
|
||||
|
||||
if (cdata->_last_update == cdata->_next_update) {
|
||||
// Someone else has computed the cache for us while we were
|
||||
|
|
@ -3633,3 +3630,41 @@ fillin_down_list(PandaNode::Down &down_list,
|
|||
down_list.push_back(DownConnection(NULL, sort));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNodePipelineReader::check_bounds
|
||||
// Access: Public
|
||||
// Description: Ensures that the bounding volume is properly computed
|
||||
// on this node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaNodePipelineReader::
|
||||
check_bounds() const {
|
||||
if (_cdata->_last_update != _cdata->_next_update) {
|
||||
// The cache is stale; it needs to be rebuilt.
|
||||
|
||||
// We'll need to get a fresh read pointer, since another thread
|
||||
// might already have modified the pointer on the object since we
|
||||
// queried it.
|
||||
{
|
||||
int pipeline_stage = _current_thread->get_pipeline_stage();
|
||||
PandaNode::CDLockedStageReader fresh_cdata(_object->_cycler, pipeline_stage, _current_thread);
|
||||
if (fresh_cdata->_last_update == fresh_cdata->_next_update) {
|
||||
// What luck, some other thread has already freshened the
|
||||
// cache for us. Save the new pointer, and let the lock
|
||||
// release itself.
|
||||
((PandaNodePipelineReader *)this)->_cdata = fresh_cdata;
|
||||
|
||||
} else {
|
||||
// No, the cache is still stale. We have to do the work of
|
||||
// freshening it.
|
||||
PandaNode::CDStageWriter cdataw = ((PandaNode *)_object)->update_bounds(pipeline_stage, fresh_cdata);
|
||||
nassertv(cdataw->_last_update == cdataw->_next_update);
|
||||
// As above, we save the new pointer, and then let the lock
|
||||
// release itself.
|
||||
((PandaNodePipelineReader *)this)->_cdata = cdataw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nassertv(_cdata->_last_update == _cdata->_next_update);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "cycleData.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "cycleDataLockedStageReader.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
#include "cycleDataStageWriter.h"
|
||||
#include "pipelineCycler.h"
|
||||
|
|
@ -505,10 +506,11 @@ private:
|
|||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataLockedStageReader<CData> CDLockedStageReader;
|
||||
typedef CycleDataStageReader<CData> CDStageReader;
|
||||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||
|
||||
CDStageWriter update_bounds(int pipeline_stage, CDStageReader &cdata);
|
||||
CDStageWriter update_bounds(int pipeline_stage, CDLockedStageReader &cdata);
|
||||
|
||||
static DrawMask _overall_bit;
|
||||
|
||||
|
|
@ -631,7 +633,7 @@ public:
|
|||
|
||||
INLINE void release();
|
||||
|
||||
INLINE void check_bounds() const;
|
||||
void check_bounds() const;
|
||||
|
||||
INLINE void compose_draw_mask(DrawMask &running_draw_mask) const;
|
||||
INLINE bool compare_draw_mask(DrawMask running_draw_mask,
|
||||
|
|
@ -671,7 +673,7 @@ public:
|
|||
private:
|
||||
const PandaNode *_object;
|
||||
Thread *_current_thread;
|
||||
const PandaNode::CData *_cdata;
|
||||
CPT(PandaNode::CData) _cdata;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const PandaNode &node) {
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ compute_internal_bounds(int pipeline_stage, Thread *current_thread) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
PT(Geom) PlaneNode::
|
||||
get_viz(CullTraverser *trav, CullTraverserData &data) {
|
||||
CDReader cdata(_cycler);
|
||||
CDLockedReader cdata(_cycler);
|
||||
|
||||
// Figure out whether we are looking at the front or the back of the
|
||||
// plane.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "updateSeq.h"
|
||||
#include "geom.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
|
|
@ -97,6 +98,7 @@ private:
|
|||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataStageReader<CData> CDStageReader;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
conditionVarSpinlockImpl.h conditionVarSpinlockImpl.I \
|
||||
config_pipeline.h \
|
||||
cycleData.h cycleData.I \
|
||||
cycleDataLockedReader.h cycleDataLockedReader.I \
|
||||
cycleDataLockedStageReader.h cycleDataLockedStageReader.I \
|
||||
cycleDataReader.h cycleDataReader.I \
|
||||
cycleDataStageReader.h cycleDataStageReader.I \
|
||||
cycleDataStageWriter.h cycleDataStageWriter.I \
|
||||
|
|
@ -62,6 +64,8 @@
|
|||
conditionVarSpinlockImpl.cxx \
|
||||
config_pipeline.cxx \
|
||||
cycleData.cxx \
|
||||
cycleDataLockedReader.cxx \
|
||||
cycleDataLockedStageReader.cxx \
|
||||
cycleDataReader.cxx \
|
||||
cycleDataStageReader.cxx \
|
||||
cycleDataStageWriter.cxx \
|
||||
|
|
@ -100,6 +104,8 @@
|
|||
conditionVarSpinlockImpl.h conditionVarSpinlockImpl.I \
|
||||
config_pipeline.h \
|
||||
cycleData.h cycleData.I \
|
||||
cycleDataLockedReader.h cycleDataLockedReader.I \
|
||||
cycleDataLockedStageReader.h cycleDataLockedStageReader.I \
|
||||
cycleDataReader.h cycleDataReader.I \
|
||||
cycleDataStageReader.h cycleDataStageReader.I \
|
||||
cycleDataStageWriter.h cycleDataStageWriter.I \
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
#include "typeHandle.h"
|
||||
#include "referenceCount.h"
|
||||
#include "nodeReferenceCount.h"
|
||||
|
||||
class BamWriter;
|
||||
class BamReader;
|
||||
|
|
@ -40,8 +40,11 @@ class DatagramIterator;
|
|||
|
||||
// If we are compiling in pipelining support, we maintain a pointer to
|
||||
// a CycleData object in each containing class, instead of the object
|
||||
// itself. Thus, it should be a ReferenceCount object.
|
||||
class EXPCL_PANDA CycleData : public ReferenceCount
|
||||
// itself. Thus, it should be a ReferenceCount object. Furthermore,
|
||||
// since we want to make a distinction between references within the
|
||||
// cycler, and references outside the cycler
|
||||
// (e.g. GeomPipelineReader), we make it a NodeReferenceCount.
|
||||
class EXPCL_PANDA CycleData : public NodeReferenceCount
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,242 @@
|
|||
// Filename: cycleDataLockedReader.I
|
||||
// Created by: drose (30Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the implementation for full support of pipelining (as well
|
||||
// as the sanity-check only implementation).
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
CycleDataLockedReader(const PipelineCycler<CycleDataType> &cycler,
|
||||
Thread *current_thread) :
|
||||
_cycler(&cycler),
|
||||
_current_thread(current_thread)
|
||||
{
|
||||
_pointer = _cycler->read(_current_thread);
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Copy Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
CycleDataLockedReader(const CycleDataLockedReader<CycleDataType> ©) :
|
||||
_cycler(copy._cycler),
|
||||
_current_thread(copy._current_thread),
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Copy Assignment (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataLockedReader<CycleDataType>::
|
||||
operator = (const CycleDataLockedReader<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
nassertv(_current_thread == copy._current_thread);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Destructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
~CycleDataLockedReader() {
|
||||
if (_pointer != NULL) {
|
||||
_cycler->release_read(_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Typecast pointer (full)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataLockedReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
operator const CycleDataType * () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::take_pointer (full)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
const CycleDataType *pointer = _pointer;
|
||||
_pointer = (CycleDataType *)NULL;
|
||||
nassertr(pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::get_current_thread (full)
|
||||
// Access: Public
|
||||
// Description: Returns the Thread pointer of the currently-executing
|
||||
// thread, as passed to the constructor of this object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE Thread *CycleDataLockedReader<CycleDataType>::
|
||||
get_current_thread() const {
|
||||
return _current_thread;
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// This is the trivial, do-nothing implementation.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
CycleDataLockedReader(const PipelineCycler<CycleDataType> &cycler, Thread *) {
|
||||
_pointer = cycler.cheat();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
CycleDataLockedReader(const CycleDataLockedReader<CycleDataType> ©) :
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Copy Assignment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataLockedReader<CycleDataType>::
|
||||
operator = (const CycleDataLockedReader<CycleDataType> ©) {
|
||||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
~CycleDataLockedReader() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::Typecast pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataLockedReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
operator const CycleDataType * () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::take_pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedReader::get_current_thread (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the Thread pointer of the currently-executing
|
||||
// thread, as passed to the constructor of this object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE Thread *CycleDataLockedReader<CycleDataType>::
|
||||
get_current_thread() const {
|
||||
return Thread::get_current_thread();
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: cycleDataLockedReader.cxx
|
||||
// Created by: drose (30Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cycleDataLockedReader.h"
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Filename: cycleDataLockedReader.h
|
||||
// Created by: drose (30Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLEDATALOCKEDREADER_H
|
||||
#define CYCLEDATALOCKEDREADER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
#include "thread.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleDataLockedReader
|
||||
// Description : This template class calls PipelineCycler::read() in
|
||||
// the constructor and PipelineCycler::release_read() in
|
||||
// the destructor. In the interim, it provides a
|
||||
// transparent read-only access to the CycleData.
|
||||
//
|
||||
// Since a lock is held on the data while the instance
|
||||
// of this class exists, no other thread may modify any
|
||||
// stage of the pipeline during that time. Thus, this
|
||||
// class is appropriate to use for cases in which you
|
||||
// might want to read and then modify the data. It is
|
||||
// possible to pass an instance of CycleDataLockedReader
|
||||
// to the CycleDataWriter constructor, which
|
||||
// automatically elevates the read lock into a write
|
||||
// lock.
|
||||
//
|
||||
// It exists as a syntactic convenience to access the
|
||||
// data in the CycleData. It also allows the whole
|
||||
// system to compile down to nothing if
|
||||
// SUPPORT_PIPELINING is not defined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
class CycleDataLockedReader {
|
||||
public:
|
||||
INLINE CycleDataLockedReader(const PipelineCycler<CycleDataType> &cycler,
|
||||
Thread *current_thread = Thread::get_current_thread());
|
||||
INLINE CycleDataLockedReader(const CycleDataLockedReader<CycleDataType> ©);
|
||||
INLINE void operator = (const CycleDataLockedReader<CycleDataType> ©);
|
||||
|
||||
INLINE ~CycleDataLockedReader();
|
||||
|
||||
INLINE const CycleDataType *operator -> () const;
|
||||
INLINE operator const CycleDataType * () const;
|
||||
|
||||
INLINE const CycleDataType *take_pointer();
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
private:
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the data stored for a real pipelining implementation.
|
||||
const PipelineCycler<CycleDataType> *_cycler;
|
||||
Thread *_current_thread;
|
||||
const CycleDataType *_pointer;
|
||||
CycleDataType *_write_pointer;
|
||||
#else // !DO_PIPELINING
|
||||
// This is all we need for the trivial, do-nothing implementation.
|
||||
const CycleDataType *_pointer;
|
||||
#endif // DO_PIPELINING
|
||||
};
|
||||
|
||||
#include "cycleDataLockedReader.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
// Filename: cycleDataLockedStageReader.I
|
||||
// Created by: drose (30Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the implementation for full support of pipelining (as well
|
||||
// as the sanity-check only implementation).
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
CycleDataLockedStageReader(const PipelineCycler<CycleDataType> &cycler,
|
||||
int stage, Thread *current_thread) :
|
||||
_cycler(&cycler),
|
||||
_current_thread(current_thread),
|
||||
_stage(stage)
|
||||
{
|
||||
_pointer = _cycler->read_stage(_stage, _current_thread);
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Copy Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> ©) :
|
||||
_cycler(copy._cycler),
|
||||
_current_thread(copy._current_thread),
|
||||
_pointer(copy._pointer),
|
||||
_stage(copy._stage)
|
||||
{
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Copy Assignment (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataLockedStageReader<CycleDataType>::
|
||||
operator = (const CycleDataLockedStageReader<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
nassertv(_current_thread == copy._current_thread);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
_stage = copy._stage;
|
||||
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Destructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
~CycleDataLockedStageReader() {
|
||||
if (_pointer != NULL) {
|
||||
_cycler->release_read_stage(_stage, _pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedStageReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Typecast pointer (full)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataLockedStageReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
operator const CycleDataType * () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::take_pointer (full)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataStageWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedStageReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
const CycleDataType *pointer = _pointer;
|
||||
_pointer = (CycleDataType *)NULL;
|
||||
nassertr(pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::get_current_thread (full)
|
||||
// Access: Public
|
||||
// Description: Returns the Thread pointer of the currently-executing
|
||||
// thread, as passed to the constructor of this object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE Thread *CycleDataLockedStageReader<CycleDataType>::
|
||||
get_current_thread() const {
|
||||
return _current_thread;
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// This is the trivial, do-nothing implementation.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
CycleDataLockedStageReader(const PipelineCycler<CycleDataType> &cycler, int,
|
||||
Thread *) {
|
||||
_pointer = cycler.cheat();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> ©) :
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Copy Assignment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataLockedStageReader<CycleDataType>::
|
||||
operator = (const CycleDataLockedStageReader<CycleDataType> ©) {
|
||||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
~CycleDataLockedStageReader() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedStageReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::Typecast pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataLockedStageReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
operator const CycleDataType * () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::take_pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataStageWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataLockedStageReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataLockedStageReader::get_current_thread (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns the Thread pointer of the currently-executing
|
||||
// thread, as passed to the constructor of this object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE Thread *CycleDataLockedStageReader<CycleDataType>::
|
||||
get_current_thread() const {
|
||||
return Thread::get_current_thread();
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: cycleDataLockedStageReader.cxx
|
||||
// Created by: drose (30Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cycleDataLockedStageReader.h"
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Filename: cycleDataLockedStageReader.h
|
||||
// Created by: drose (30Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLEDATALOCKEDSTAGEREADER_H
|
||||
#define CYCLEDATALOCKEDSTAGEREADER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleDataLockedStageReader
|
||||
// Description : This class is similar to CycleDataLockedReader,
|
||||
// except it allows reading from a particular stage of
|
||||
// the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
class CycleDataLockedStageReader {
|
||||
public:
|
||||
INLINE CycleDataLockedStageReader(const PipelineCycler<CycleDataType> &cycler,
|
||||
int stage, Thread *current_thread = Thread::get_current_thread());
|
||||
INLINE CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> ©);
|
||||
INLINE void operator = (const CycleDataLockedStageReader<CycleDataType> ©);
|
||||
|
||||
INLINE ~CycleDataLockedStageReader();
|
||||
|
||||
INLINE const CycleDataType *operator -> () const;
|
||||
INLINE operator const CycleDataType * () const;
|
||||
|
||||
INLINE const CycleDataType *take_pointer();
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
private:
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the data stored for a real pipelining implementation.
|
||||
const PipelineCycler<CycleDataType> *_cycler;
|
||||
Thread *_current_thread;
|
||||
const CycleDataType *_pointer;
|
||||
int _stage;
|
||||
#else // !DO_PIPELINING
|
||||
// This is all we need for the trivial, do-nothing implementation.
|
||||
const CycleDataType *_pointer;
|
||||
#endif // DO_PIPELINING
|
||||
};
|
||||
|
||||
#include "cycleDataLockedStageReader.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -32,8 +32,7 @@ CycleDataReader(const PipelineCycler<CycleDataType> &cycler,
|
|||
_cycler(&cycler),
|
||||
_current_thread(current_thread)
|
||||
{
|
||||
_pointer = _cycler->read(_current_thread);
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_pointer = _cycler->read_unlocked(_current_thread);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -48,8 +47,6 @@ CycleDataReader(const CycleDataReader<CycleDataType> ©) :
|
|||
_current_thread(copy._current_thread),
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -60,14 +57,10 @@ CycleDataReader(const CycleDataReader<CycleDataType> ©) :
|
|||
template<class CycleDataType>
|
||||
INLINE void CycleDataReader<CycleDataType>::
|
||||
operator = (const CycleDataReader<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
nassertv(_current_thread == copy._current_thread);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -78,9 +71,6 @@ operator = (const CycleDataReader<CycleDataType> ©) {
|
|||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
~CycleDataReader() {
|
||||
if (_pointer != NULL) {
|
||||
_cycler->release_read(_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -92,7 +82,6 @@ INLINE CycleDataReader<CycleDataType>::
|
|||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
|
|
@ -105,29 +94,9 @@ operator -> () const {
|
|||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
operator const CycleDataType * () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::take_pointer (full)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
const CycleDataType *pointer = _pointer;
|
||||
_pointer = (CycleDataType *)NULL;
|
||||
nassertr(pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::get_current_thread (full)
|
||||
// Access: Public
|
||||
|
|
@ -211,22 +180,6 @@ operator const CycleDataType * () const {
|
|||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::take_pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::get_current_thread (trivial)
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -27,10 +27,14 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleDataReader
|
||||
// Description : This template class calls PipelineCycler::read() in
|
||||
// the constructor and PipelineCycler::release_read() in
|
||||
// the destructor. In the interim, it provides a
|
||||
// transparent read-only access to the CycleData.
|
||||
// Description : This template class calls
|
||||
// PipelineCycler::read_unlocked(), and then provides a
|
||||
// transparent read-only access to the CycleData. It is
|
||||
// used to access the data quickly, without holding a
|
||||
// lock, for a thread that does not intend to modify the
|
||||
// data and write it back out. For cases where the data
|
||||
// might be subsequently modified, you should use
|
||||
// CycleDataLockedReader.
|
||||
//
|
||||
// It exists as a syntactic convenience to access the
|
||||
// data in the CycleData. It also allows the whole
|
||||
|
|
@ -50,7 +54,6 @@ public:
|
|||
INLINE const CycleDataType *operator -> () const;
|
||||
INLINE operator const CycleDataType * () const;
|
||||
|
||||
INLINE const CycleDataType *take_pointer();
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@ CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler,
|
|||
_current_thread(current_thread),
|
||||
_stage(stage)
|
||||
{
|
||||
_pointer = _cycler->read_stage(_stage, _current_thread);
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_pointer = _cycler->read_stage_unlocked(_stage);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -51,8 +50,6 @@ CycleDataStageReader(const CycleDataStageReader<CycleDataType> ©) :
|
|||
_pointer(copy._pointer),
|
||||
_stage(copy._stage)
|
||||
{
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -63,15 +60,11 @@ CycleDataStageReader(const CycleDataStageReader<CycleDataType> ©) :
|
|||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageReader<CycleDataType>::
|
||||
operator = (const CycleDataStageReader<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
nassertv(_current_thread == copy._current_thread);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
_stage = copy._stage;
|
||||
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -82,9 +75,6 @@ operator = (const CycleDataStageReader<CycleDataType> ©) {
|
|||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
~CycleDataStageReader() {
|
||||
if (_pointer != NULL) {
|
||||
_cycler->release_read_stage(_stage, _pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -96,7 +86,6 @@ INLINE CycleDataStageReader<CycleDataType>::
|
|||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataStageReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
|
|
@ -109,29 +98,9 @@ operator -> () const {
|
|||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
operator const CycleDataType * () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::take_pointer (full)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataStageWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataStageReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
const CycleDataType *pointer = _pointer;
|
||||
_pointer = (CycleDataType *)NULL;
|
||||
nassertr(pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::get_current_thread (full)
|
||||
// Access: Public
|
||||
|
|
@ -216,22 +185,6 @@ operator const CycleDataType * () const {
|
|||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::take_pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This is intended to be called only from
|
||||
// CycleDataStageWriter when it elevates the pointer from
|
||||
// read to write status. This function returns the
|
||||
// reader's pointer and relinquishes ownership of the
|
||||
// pointer, rendering the reader invalid for future
|
||||
// reads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataStageReader<CycleDataType>::
|
||||
take_pointer() {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::get_current_thread (trivial)
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ public:
|
|||
INLINE const CycleDataType *operator -> () const;
|
||||
INLINE operator const CycleDataType * () const;
|
||||
|
||||
INLINE const CycleDataType *take_pointer();
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -94,13 +94,13 @@ operator = (const CycleDataStageWriter<CycleDataType> ©) {
|
|||
// Function: CycleDataStageWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataStageReader from a read to a write
|
||||
// from the CycleDataLockedStageReader from a read to a write
|
||||
// pointer (and invalidates the reader).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
|
||||
CycleDataStageReader<CycleDataType> &take_from) :
|
||||
CycleDataLockedStageReader<CycleDataType> &take_from) :
|
||||
_cycler(&cycler),
|
||||
_current_thread(take_from.get_current_thread()),
|
||||
_stage(stage)
|
||||
|
|
@ -113,13 +113,13 @@ CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
|
|||
// Function: CycleDataStageWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataStageReader from a read to a write
|
||||
// from the CycleDataLockedStageReader from a read to a write
|
||||
// pointer (and invalidates the reader).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
|
||||
CycleDataStageReader<CycleDataType> &take_from,
|
||||
CycleDataLockedStageReader<CycleDataType> &take_from,
|
||||
bool force_to_0) :
|
||||
_cycler(&cycler),
|
||||
_current_thread(take_from.get_current_thread()),
|
||||
|
|
@ -245,13 +245,13 @@ operator = (const CycleDataStageWriter<CycleDataType> ©) {
|
|||
// Function: CycleDataStageWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataStageReader from a read to a write
|
||||
// from the CycleDataLockedStageReader from a read to a write
|
||||
// pointer (and invalidates the reader).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(PipelineCycler<CycleDataType> &, int,
|
||||
CycleDataStageReader<CycleDataType> &take_from) :
|
||||
CycleDataLockedStageReader<CycleDataType> &take_from) :
|
||||
_pointer((CycleDataType *)take_from.take_pointer())
|
||||
{
|
||||
}
|
||||
|
|
@ -260,13 +260,13 @@ CycleDataStageWriter(PipelineCycler<CycleDataType> &, int,
|
|||
// Function: CycleDataStageWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataStageReader from a read to a write
|
||||
// from the CycleDataLockedStageReader from a read to a write
|
||||
// pointer (and invalidates the reader).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(PipelineCycler<CycleDataType> &, int,
|
||||
CycleDataStageReader<CycleDataType> &take_from,
|
||||
CycleDataLockedStageReader<CycleDataType> &take_from,
|
||||
bool) :
|
||||
_pointer((CycleDataType *)take_from.take_pointer())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
#include "cycleDataLockedStageReader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleDataStageWriter
|
||||
|
|
@ -46,9 +46,9 @@ public:
|
|||
INLINE void operator = (const CycleDataStageWriter<CycleDataType> ©);
|
||||
|
||||
INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
|
||||
CycleDataStageReader<CycleDataType> &take_from);
|
||||
CycleDataLockedStageReader<CycleDataType> &take_from);
|
||||
INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
|
||||
CycleDataStageReader<CycleDataType> &take_from,
|
||||
CycleDataLockedStageReader<CycleDataType> &take_from,
|
||||
bool force_to_0);
|
||||
|
||||
INLINE ~CycleDataStageWriter();
|
||||
|
|
|
|||
|
|
@ -95,13 +95,13 @@ operator = (const CycleDataWriter<CycleDataType> ©) {
|
|||
// Function: CycleDataWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader from a read to a write
|
||||
// from the CycleDataLockedReader from a read to a write
|
||||
// pointer (and invalidates the reader).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
|
||||
CycleDataReader<CycleDataType> &take_from) :
|
||||
CycleDataLockedReader<CycleDataType> &take_from) :
|
||||
_cycler(&cycler),
|
||||
_current_thread(take_from.get_current_thread())
|
||||
{
|
||||
|
|
@ -112,7 +112,7 @@ CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
|
|||
// Function: CycleDataWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader from a read to a write
|
||||
// from the CycleDataLockedReader from a read to a write
|
||||
// pointer (and invalidates the reader). It also
|
||||
// propagates the pointer back upstream; see
|
||||
// PipelineCycler::write_upstream().
|
||||
|
|
@ -120,7 +120,7 @@ CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
|
|||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
|
||||
CycleDataReader<CycleDataType> &take_from,
|
||||
CycleDataLockedReader<CycleDataType> &take_from,
|
||||
bool force_to_0) :
|
||||
_cycler(&cycler),
|
||||
_current_thread(take_from.get_current_thread())
|
||||
|
|
@ -245,13 +245,13 @@ operator = (const CycleDataWriter<CycleDataType> ©) {
|
|||
// Function: CycleDataWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader from a read to a write
|
||||
// from the CycleDataLockedReader from a read to a write
|
||||
// pointer (and invalidates the reader).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &,
|
||||
CycleDataReader<CycleDataType> &take_from) :
|
||||
CycleDataLockedReader<CycleDataType> &take_from) :
|
||||
_pointer((CycleDataType *)take_from.take_pointer())
|
||||
{
|
||||
}
|
||||
|
|
@ -260,7 +260,7 @@ CycleDataWriter(PipelineCycler<CycleDataType> &,
|
|||
// Function: CycleDataWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader from a read to a write
|
||||
// from the CycleDataLockedReader from a read to a write
|
||||
// pointer (and invalidates the reader). It also
|
||||
// propagates the pointer back upstream; see
|
||||
// PipelineCycler::write_upstream().
|
||||
|
|
@ -268,7 +268,7 @@ CycleDataWriter(PipelineCycler<CycleDataType> &,
|
|||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &,
|
||||
CycleDataReader<CycleDataType> &take_from,
|
||||
CycleDataLockedReader<CycleDataType> &take_from,
|
||||
bool force_to_0) :
|
||||
_pointer((CycleDataType *)take_from.take_pointer())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataLockedReader.h"
|
||||
#include "thread.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -48,8 +48,8 @@ public:
|
|||
INLINE CycleDataWriter(const CycleDataWriter<CycleDataType> ©);
|
||||
INLINE void operator = (const CycleDataWriter<CycleDataType> ©);
|
||||
|
||||
INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler, CycleDataReader<CycleDataType> &take_from);
|
||||
INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler, CycleDataReader<CycleDataType> &take_from, bool force_to_0);
|
||||
INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler, CycleDataLockedReader<CycleDataType> &take_from);
|
||||
INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler, CycleDataLockedReader<CycleDataType> &take_from, bool force_to_0);
|
||||
|
||||
INLINE ~CycleDataWriter();
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,17 @@ operator = (const PipelineCycler<CycleDataType> ©) {
|
|||
PipelineCyclerBase::operator = (copy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read_unlocked (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read_unlocked().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *PipelineCycler<CycleDataType>::
|
||||
read_unlocked(Thread *current_thread) const {
|
||||
return (const CycleDataType *)PipelineCyclerBase::read_unlocked(current_thread);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read (dummy or true)
|
||||
// Access: Public
|
||||
|
|
@ -113,7 +124,18 @@ elevate_read_upstream(const CycleDataType *pointer, bool force_to_0,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read (dummy or true)
|
||||
// Function: PipelineCycler::read_stage_unlocked (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read_stage_unlocked().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *PipelineCycler<CycleDataType>::
|
||||
read_stage_unlocked(int pipeline_stage) const {
|
||||
return (const CycleDataType *)PipelineCyclerBase::read_stage_unlocked(pipeline_stage);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read_stage (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -227,6 +249,17 @@ operator = (const PipelineCycler<CycleDataType> ©) {
|
|||
_typed_data = copy._typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read_unlocked (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read_unlocked().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *PipelineCycler<CycleDataType>::
|
||||
read_unlocked(Thread *) const {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read (trivial)
|
||||
// Access: Public
|
||||
|
|
@ -282,6 +315,17 @@ elevate_read_upstream(const CycleDataType *, bool, Thread *) {
|
|||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read_stage_unlocked (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read_stage_unlocked().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *PipelineCycler<CycleDataType>::
|
||||
read_stage_unlocked(int) const {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read_stage (trivial)
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -63,12 +63,14 @@ public:
|
|||
INLINE PipelineCycler(const PipelineCycler<CycleDataType> ©);
|
||||
INLINE void operator = (const PipelineCycler<CycleDataType> ©);
|
||||
|
||||
INLINE const CycleDataType *read_unlocked(Thread *current_thread) const;
|
||||
INLINE const CycleDataType *read(Thread *current_thread) const;
|
||||
INLINE CycleDataType *write(Thread *current_thread);
|
||||
INLINE CycleDataType *write_upstream(bool force_to_0, Thread *current_thread);
|
||||
INLINE CycleDataType *elevate_read(const CycleDataType *pointer, Thread *current_thread);
|
||||
INLINE CycleDataType *elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
|
||||
|
||||
INLINE const CycleDataType *read_stage_unlocked(int pipeline_stage) const;
|
||||
INLINE const CycleDataType *read_stage(int pipeline_stage, Thread *current_thread) const;
|
||||
INLINE CycleDataType *elevate_read_stage(int pipeline_stage, const CycleDataType *pointer, Thread *current_thread);
|
||||
INLINE CycleDataType *elevate_read_stage_upstream(int pipeline_stage, const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,26 @@ release() {
|
|||
_locked = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::read_unlocked
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. No lock is made on the contents; there
|
||||
// is no guarantee that some other thread won't modify
|
||||
// this object's data while you are working on it.
|
||||
// (However, the data within the returned CycleData
|
||||
// object itself is safe from modification; if another
|
||||
// thread modifies the data, it will perform a
|
||||
// copy-on-write, and thereby change the pointer stored
|
||||
// within the object.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerDummyImpl::
|
||||
read_unlocked(Thread *current_thread) const {
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read_unlocked()", " ", TAU_USER);
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::read
|
||||
// Access: Public
|
||||
|
|
@ -294,6 +314,21 @@ get_num_stages() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::read_stage_unlocked
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the indicated stage of the pipeline. As in
|
||||
// read_unlocked(), no lock is held on the returned
|
||||
// pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerDummyImpl::
|
||||
read_stage_unlocked(int pipeline_stage) const {
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read_stage_unlocked(int)", " ", TAU_USER);
|
||||
nassertr(pipeline_stage == 0, NULL);
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::read_stage
|
||||
// Access: Public
|
||||
|
|
@ -307,7 +342,7 @@ get_num_stages() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerDummyImpl::
|
||||
read_stage(int pipeline_stage, Thread *) const {
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read_stage(int)", " ", TAU_USER);
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read_stage(int, Thread *)", " ", TAU_USER);
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertr(pipeline_stage == 0, NULL);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
INLINE void lock(Thread *current_thread = NULL);
|
||||
INLINE void release();
|
||||
|
||||
INLINE const CycleData *read_unlocked(Thread *current_thread) const;
|
||||
INLINE const CycleData *read(Thread *current_thread) const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
|
@ -67,6 +68,7 @@ public:
|
|||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE const CycleData *read_stage_unlocked(int pipeline_stage) const;
|
||||
INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
|
||||
INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
|
||||
INLINE CycleData *write_stage(int pipeline_stage, Thread *current_thread);
|
||||
|
|
|
|||
|
|
@ -98,6 +98,29 @@ INLINE void PipelineCyclerTrivialImpl::
|
|||
release() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::read_unlocked
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. No lock is made on the contents; there
|
||||
// is no guarantee that some other thread won't modify
|
||||
// this object's data while you are working on it.
|
||||
// (However, the data within the returned CycleData
|
||||
// object itself is safe from modification; if another
|
||||
// thread modifies the data, it will perform a
|
||||
// copy-on-write, and thereby change the pointer stored
|
||||
// within the object.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrivialImpl::
|
||||
read_unlocked(Thread *) const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (const CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::read
|
||||
// Access: Public
|
||||
|
|
@ -265,6 +288,23 @@ get_num_stages() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::read_stage_unlocked
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the indicated stage of the pipeline. As in
|
||||
// read_unlocked(), no lock is held on the returned
|
||||
// pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrivialImpl::
|
||||
read_stage_unlocked(int) const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (const CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::read_stage
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public:
|
|||
INLINE void lock(Thread *current_thread = NULL);
|
||||
INLINE void release();
|
||||
|
||||
INLINE const CycleData *read_unlocked(Thread *current_thread) const;
|
||||
INLINE const CycleData *read(Thread *current_thread) const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
|
@ -73,6 +74,7 @@ public:
|
|||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE const CycleData *read_stage_unlocked(int pipeline_stage) const;
|
||||
INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
|
||||
INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
|
||||
INLINE CycleData *write_stage(int pipeline_stage, Thread *current_thread);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,30 @@ release() {
|
|||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::read_unlocked
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. No lock is made on the contents; there
|
||||
// is no guarantee that some other thread won't modify
|
||||
// this object's data while you are working on it.
|
||||
// (However, the data within the returned CycleData
|
||||
// object itself is safe from modification; if another
|
||||
// thread modifies the data, it will perform a
|
||||
// copy-on-write, and thereby change the pointer stored
|
||||
// within the object.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrueImpl::
|
||||
read_unlocked(Thread *current_thread) const {
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_unlocked(Thread *)", " ", TAU_USER);
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
#ifdef _DEBUG
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
#endif
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::read
|
||||
// Access: Public
|
||||
|
|
@ -258,6 +282,23 @@ get_num_stages() {
|
|||
return _num_stages;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::read_stage_unlocked
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the indicated stage of the pipeline. As in
|
||||
// read_unlocked(), no lock is held on the returned
|
||||
// pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrueImpl::
|
||||
read_stage_unlocked(int pipeline_stage) const {
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage_unlocked(int)", " ", TAU_USER);
|
||||
#ifdef _DEBUG
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
#endif
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::read_stage
|
||||
// Access: Public
|
||||
|
|
@ -271,7 +312,7 @@ 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);
|
||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int, Thread *)", " ", TAU_USER);
|
||||
#ifdef _DEBUG
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
#endif
|
||||
|
|
@ -421,7 +462,7 @@ get_write_count() const {
|
|||
INLINE PT(CycleData) PipelineCyclerTrueImpl::
|
||||
cycle_2() {
|
||||
TAU_PROFILE("PT(CycleData) PipelineCyclerTrueImpl::cycle_2()", " ", TAU_USER);
|
||||
PT(CycleData) last_val = _data[1];
|
||||
PT(CycleData) last_val = _data[1].p();
|
||||
nassertr(_lock.debug_is_locked(), last_val);
|
||||
nassertr(_dirty, last_val);
|
||||
nassertr(_num_stages == 2, last_val);
|
||||
|
|
@ -445,7 +486,7 @@ cycle_2() {
|
|||
INLINE PT(CycleData) PipelineCyclerTrueImpl::
|
||||
cycle_3() {
|
||||
TAU_PROFILE("PT(CycleData) PipelineCyclerTrueImpl::cycle_3()", " ", TAU_USER);
|
||||
PT(CycleData) last_val = _data[2];
|
||||
PT(CycleData) last_val = _data[2].p();
|
||||
nassertr(_lock.debug_is_locked(), last_val);
|
||||
nassertr(_dirty, last_val);
|
||||
nassertr(_num_stages == 3, last_val);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
|||
}
|
||||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
_data = new PT(CycleData)[_num_stages];
|
||||
_data = new NPT(CycleData)[_num_stages];
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i] = initial_data;
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
|||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
_data = new PT(CycleData)[_num_stages];
|
||||
_data = new NPT(CycleData)[_num_stages];
|
||||
|
||||
// It's no longer critically important that we preserve pointerwise
|
||||
// equivalence between different stages in the copy, but it doesn't
|
||||
|
|
@ -77,7 +77,7 @@ PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
|||
if (new_pt == NULL) {
|
||||
new_pt = copy._data[i]->make_copy();
|
||||
}
|
||||
_data[i] = new_pt;
|
||||
_data[i] = new_pt.p();
|
||||
}
|
||||
|
||||
_pipeline->add_cycler(this);
|
||||
|
|
@ -105,7 +105,7 @@ operator = (const PipelineCyclerTrueImpl ©) {
|
|||
if (new_pt == NULL) {
|
||||
new_pt = copy._data[i]->make_copy();
|
||||
}
|
||||
_data[i] = new_pt;
|
||||
_data[i] = new_pt.p();
|
||||
}
|
||||
|
||||
if (copy._dirty && !_dirty) {
|
||||
|
|
@ -152,7 +152,11 @@ write_stage(int pipeline_stage, Thread *current_thread) {
|
|||
|
||||
CycleData *old_data = _data[pipeline_stage];
|
||||
|
||||
if (old_data->get_ref_count() != 1) {
|
||||
// Only the node reference count is considered an important count
|
||||
// for copy-on-write purposes. A standard reference of other than 1
|
||||
// just means that some code (other that the PipelineCycler) has a
|
||||
// pointer, which is safe to modify.
|
||||
if (old_data->get_node_ref_count() != 1) {
|
||||
// Copy-on-write.
|
||||
_data[pipeline_stage] = old_data->make_copy();
|
||||
|
||||
|
|
@ -203,7 +207,7 @@ write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread
|
|||
|
||||
k = pipeline_stage - 1;
|
||||
while (k >= 0 && (_data[k] == old_data || force_to_0)) {
|
||||
_data[k] = new_data;
|
||||
_data[k] = new_data.p();
|
||||
--k;
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +255,7 @@ write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread
|
|||
////////////////////////////////////////////////////////////////////
|
||||
PT(CycleData) PipelineCyclerTrueImpl::
|
||||
cycle() {
|
||||
PT(CycleData) last_val = _data[_num_stages - 1];
|
||||
PT(CycleData) last_val = _data[_num_stages - 1].p();
|
||||
nassertr(_lock.debug_is_locked(), last_val);
|
||||
nassertr(_dirty, last_val);
|
||||
|
||||
|
|
@ -294,7 +298,7 @@ set_num_stages(int num_stages) {
|
|||
|
||||
} else {
|
||||
// To increase the array, we must reallocate it larger.
|
||||
PT(CycleData) *new_data = new PT(CycleData)[num_stages];
|
||||
NPT(CycleData) *new_data = new NPT(CycleData)[num_stages];
|
||||
int i;
|
||||
for (i = 0; i < _num_stages; ++i) {
|
||||
new_data[i] = _data[i];
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "pipelineCyclerLinks.h"
|
||||
#include "cycleData.h"
|
||||
#include "pointerTo.h"
|
||||
#include "nodePointerTo.h"
|
||||
#include "thread.h"
|
||||
#include "reMutex.h"
|
||||
#include "reMutexHolder.h"
|
||||
|
|
@ -61,6 +62,8 @@ public:
|
|||
INLINE void lock(Thread *current_thread);
|
||||
INLINE void release();
|
||||
|
||||
INLINE const CycleData *read_unlocked(Thread *current_thread) const;
|
||||
|
||||
INLINE const CycleData *read(Thread *current_thread) const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
|
@ -73,6 +76,7 @@ public:
|
|||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE const CycleData *read_stage_unlocked(int pipeline_stage) const;
|
||||
INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
|
||||
INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
|
||||
CycleData *write_stage(int pipeline_stage, Thread *current_thread);
|
||||
|
|
@ -113,8 +117,8 @@ private:
|
|||
private:
|
||||
Pipeline *_pipeline;
|
||||
|
||||
// An array of PT(CycleData) objects.
|
||||
PT(CycleData) *_data;
|
||||
// An array of NPT(CycleData) objects.
|
||||
NPT(CycleData) *_data;
|
||||
int _num_stages;
|
||||
bool _dirty;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include "conditionVarSpinlockImpl.cxx"
|
||||
#include "config_pipeline.cxx"
|
||||
#include "cycleData.cxx"
|
||||
#include "cycleDataLockedReader.cxx"
|
||||
#include "cycleDataLockedStageReader.cxx"
|
||||
#include "cycleDataReader.cxx"
|
||||
#include "cycleDataStageReader.cxx"
|
||||
#include "cycleDataStageWriter.cxx"
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@
|
|||
modifierButtons.I modifierButtons.h mouseButton.h \
|
||||
mouseData.I mouseData.h nameUniquifier.I nameUniquifier.h \
|
||||
nodeCachedReferenceCount.h nodeCachedReferenceCount.I \
|
||||
nodePointerToBase.h nodePointerToBase.I \
|
||||
nodePointerTo.h nodePointerTo.I \
|
||||
nonDeletor.h \
|
||||
pta_double.h \
|
||||
pta_float.h pta_int.h \
|
||||
|
|
@ -86,8 +84,6 @@
|
|||
modifierButtons.cxx mouseButton.cxx mouseData.cxx \
|
||||
nameUniquifier.cxx \
|
||||
nodeCachedReferenceCount.cxx \
|
||||
nodePointerToBase.cxx \
|
||||
nodePointerTo.cxx \
|
||||
nonDeletor.cxx \
|
||||
pta_double.cxx pta_float.cxx \
|
||||
pta_int.cxx pta_ushort.cxx \
|
||||
|
|
@ -135,8 +131,6 @@
|
|||
modifierButtons.h mouseButton.h mouseData.I mouseData.h \
|
||||
nameUniquifier.I nameUniquifier.h \
|
||||
nodeCachedReferenceCount.h nodeCachedReferenceCount.I \
|
||||
nodePointerToBase.h nodePointerToBase.I \
|
||||
nodePointerTo.h nodePointerTo.I \
|
||||
nonDeletor.h \
|
||||
pta_double.h \
|
||||
pta_float.h pta_int.h pta_ushort.h \
|
||||
|
|
|
|||
|
|
@ -242,30 +242,3 @@ get_referenced_bits() const {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: node_unref_delete
|
||||
// Description: This global helper function will unref the given
|
||||
// ReferenceCount object, and if the reference count
|
||||
// reaches zero, automatically delete it. It can't be a
|
||||
// member function because it's usually a bad idea to
|
||||
// delete an object from within its own member function.
|
||||
// It's a template function so the destructor doesn't
|
||||
// have to be virtual.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class RefCountType>
|
||||
INLINE void
|
||||
node_unref_delete(RefCountType *ptr) {
|
||||
ptr->node_unref();
|
||||
if (ptr->get_ref_count() == 0) {
|
||||
ObjectDeletor *deletor = ObjectDeletor::get_global_ptr();
|
||||
if (deletor != (ObjectDeletor *)NULL) {
|
||||
ptr->ref();
|
||||
deletor->delete_object(RefCountDeleteWrapper<RefCountType>::do_delete, (void *)ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
delete ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "pandabase.h"
|
||||
|
||||
#include "cachedTypedWritableReferenceCount.h"
|
||||
#include "nodeReferenceCount.h" // for node_unref_delete()
|
||||
#include "objectDeletor.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -32,6 +33,19 @@
|
|||
// number of times the object is referenced by a "node",
|
||||
// presumably a PandaNode.
|
||||
//
|
||||
// This essentially combines the functionality of
|
||||
// NodeReferenceCount and
|
||||
// CachedTypedWritableReferenceCount, so that a
|
||||
// derivative of this object actually has three
|
||||
// counters: the standard reference count, the "cache"
|
||||
// reference count, and the "node" reference count.
|
||||
// Rather than multiply inheriting from the two
|
||||
// reference count classes, we inherit only from
|
||||
// CachedTypedWritableReferenceCount and simply
|
||||
// duplicate the functionality of NodeReferenceCount, to
|
||||
// avoid all of the problems associated with multiple
|
||||
// inheritance.
|
||||
//
|
||||
// The intended design is to use this as a base class
|
||||
// for RenderState and TransformState, both of which are
|
||||
// held by PandaNodes, and also have caches which are
|
||||
|
|
@ -90,9 +104,6 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
template<class RefCountType>
|
||||
INLINE void node_unref_delete(RefCountType *ptr);
|
||||
|
||||
#include "nodeCachedReferenceCount.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
#include "mouseData.cxx"
|
||||
#include "nameUniquifier.cxx"
|
||||
#include "nodeCachedReferenceCount.cxx"
|
||||
#include "nodePointerToBase.cxx"
|
||||
#include "nodePointerTo.cxx"
|
||||
#include "nonDeletor.cxx"
|
||||
#include "pta_double.cxx"
|
||||
#include "pta_float.cxx"
|
||||
|
|
|
|||
Loading…
Reference in New Issue