move Pipeline* and Cycle* from putil, in order to pipeline the ClockObject class
This commit is contained in:
parent
8c4afe0e13
commit
851eb4cd8b
|
|
@ -26,6 +26,12 @@
|
|||
conditionVarPosixImpl.h conditionVarPosixImpl.I \
|
||||
conditionVarWin32Impl.h conditionVarWin32Impl.I \
|
||||
config_express.h \
|
||||
cycleData.h cycleData.I \
|
||||
cycleDataReader.h cycleDataReader.I \
|
||||
cycleDataStageReader.h cycleDataStageReader.I \
|
||||
cycleDataStageWriter.h cycleDataStageWriter.I \
|
||||
cycleDataWriter.h cycleDataWriter.I \
|
||||
cyclerHolder.h cyclerHolder.I \
|
||||
datagram.I datagram.h datagramGenerator.I \
|
||||
datagramGenerator.h \
|
||||
datagramIterator.I datagramIterator.h datagramSink.I datagramSink.h \
|
||||
|
|
@ -52,6 +58,13 @@
|
|||
ordered_vector.h ordered_vector.I ordered_vector.T \
|
||||
password_hash.h \
|
||||
patchfile.I patchfile.h \
|
||||
pipeline.h pipeline.I \
|
||||
pipelineCycler.h pipelineCycler.I \
|
||||
pipelineCyclerLinks.h pipelineCyclerLinks.I \
|
||||
pipelineCyclerBase.h \
|
||||
pipelineCyclerDummyImpl.h pipelineCyclerDummyImpl.I \
|
||||
pipelineCyclerTrivialImpl.h pipelineCyclerTrivialImpl.I \
|
||||
pipelineCyclerTrueImpl.h pipelineCyclerTrueImpl.I \
|
||||
pmutex.h pmutex.I \
|
||||
pointerTo.I pointerTo.h \
|
||||
pointerToArray.I pointerToArray.h \
|
||||
|
|
@ -105,7 +118,14 @@
|
|||
conditionVarNsprImpl.cxx \
|
||||
conditionVarPosixImpl.cxx \
|
||||
conditionVarWin32Impl.cxx \
|
||||
config_express.cxx datagram.cxx datagramGenerator.cxx \
|
||||
config_express.cxx \
|
||||
cycleData.cxx \
|
||||
cycleDataReader.cxx \
|
||||
cycleDataStageReader.cxx \
|
||||
cycleDataStageWriter.cxx \
|
||||
cycleDataWriter.cxx \
|
||||
cyclerHolder.cxx \
|
||||
datagram.cxx datagramGenerator.cxx \
|
||||
datagramIterator.cxx \
|
||||
datagramSink.cxx dcast.cxx \
|
||||
encryptStreamBuf.cxx encryptStream.cxx \
|
||||
|
|
@ -118,6 +138,11 @@
|
|||
mutexDebug.cxx \
|
||||
mutexDirect.cxx \
|
||||
mutexHolder.cxx \
|
||||
pipeline.cxx \
|
||||
pipelineCycler.cxx \
|
||||
pipelineCyclerDummyImpl.cxx \
|
||||
pipelineCyclerTrivialImpl.cxx \
|
||||
pipelineCyclerTrueImpl.cxx \
|
||||
pmutex.cxx \
|
||||
namable.cxx \
|
||||
nativeNumericData.cxx \
|
||||
|
|
@ -176,7 +201,14 @@
|
|||
conditionVarNsprImpl.h conditionVarNsprImpl.I \
|
||||
conditionVarPosixImpl.h conditionVarPosixImpl.I \
|
||||
conditionVarWin32Impl.h conditionVarWin32Impl.I \
|
||||
config_express.h datagram.I datagram.h \
|
||||
config_express.h \
|
||||
cycleData.h cycleData.I \
|
||||
cycleDataReader.h cycleDataReader.I \
|
||||
cycleDataStageReader.h cycleDataStageReader.I \
|
||||
cycleDataStageWriter.h cycleDataStageWriter.I \
|
||||
cycleDataWriter.h cycleDataWriter.I \
|
||||
cyclerHolder.h cyclerHolder.I \
|
||||
datagram.I datagram.h \
|
||||
datagramGenerator.I datagramGenerator.h \
|
||||
datagramIterator.I datagramIterator.h \
|
||||
datagramSink.I datagramSink.h dcast.T dcast.h \
|
||||
|
|
@ -200,6 +232,13 @@
|
|||
ordered_vector.h ordered_vector.I ordered_vector.T \
|
||||
password_hash.h \
|
||||
patchfile.I patchfile.h \
|
||||
pipeline.h pipeline.I \
|
||||
pipelineCycler.h pipelineCycler.I \
|
||||
pipelineCyclerLinks.h pipelineCyclerLinks.I \
|
||||
pipelineCyclerBase.h \
|
||||
pipelineCyclerDummyImpl.h pipelineCyclerDummyImpl.I \
|
||||
pipelineCyclerTrivialImpl.h pipelineCyclerTrivialImpl.I \
|
||||
pipelineCyclerTrueImpl.h pipelineCyclerTrueImpl.I \
|
||||
pmutex.h pmutex.I \
|
||||
pointerTo.I pointerTo.h \
|
||||
pointerToArray.I pointerToArray.h \
|
||||
|
|
|
|||
|
|
@ -28,13 +28,35 @@ INLINE ClockObject::
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClockObject::set_mode
|
||||
// Access: Published
|
||||
// Description: Changes the mode of the clock, e.g. from normal
|
||||
// (real-time) to non-real-time. In non-real-time mode,
|
||||
// tick() will add the value of dt to the value returned
|
||||
// by get_frame_time(), regardless of how much time has
|
||||
// actually passed. In normal, real-time mode, tick()
|
||||
// will set the value returned by get_frame_time() to
|
||||
// the current real time.
|
||||
// Description: Changes the mode of the clock. Normally, the clock
|
||||
// is in mode M_normal. In this mode, each call to
|
||||
// tick() will set the value returned by
|
||||
// get_frame_time() to the current real time; thus, the
|
||||
// clock simply reports time advancing.
|
||||
//
|
||||
// Other possible modes:
|
||||
//
|
||||
// M_non_real_time - the clock ignores real time
|
||||
// completely; at each call to tick(), it pretends that
|
||||
// exactly dt seconds have elapsed since the last call
|
||||
// to tick(). You may set the value of dt with
|
||||
// set_dt().
|
||||
//
|
||||
// M_forced - the clock forces the application to run at
|
||||
// the rate specified by set_dt(). If the application
|
||||
// would run faster than this rate, the clock will slow
|
||||
// down the application; if the application would run
|
||||
// slower than this rate, the clock slows down time so
|
||||
// that the application believes it is running at the
|
||||
// given rate.
|
||||
//
|
||||
// M_degrade - the clock runs at real time, but the
|
||||
// application is slowed down by a set factor of its
|
||||
// frame rate, specified by set_degrade_factor().
|
||||
//
|
||||
// M_slave - the clock does not advance, but relies on
|
||||
// the user to call set_frame_time() and/or
|
||||
// set_frame_count() each frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ClockObject::
|
||||
set_mode(ClockObject::Mode mode) {
|
||||
|
|
@ -66,7 +88,8 @@ get_mode() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double ClockObject::
|
||||
get_frame_time() const {
|
||||
return _reported_frame_time;
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_reported_frame_time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -130,7 +153,8 @@ reset() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int ClockObject::
|
||||
get_frame_count() const {
|
||||
return _frame_count;
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_frame_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -156,10 +180,11 @@ get_net_frame_rate() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double ClockObject::
|
||||
get_dt() const {
|
||||
CDReader cdata(_cycler);
|
||||
if (_max_dt > 0.0) {
|
||||
return min(_max_dt, _dt);
|
||||
return min(_max_dt, cdata->_dt);
|
||||
}
|
||||
return _dt;
|
||||
return cdata->_dt;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -172,7 +197,9 @@ get_dt() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ClockObject::
|
||||
set_dt(double dt) {
|
||||
_dt = dt;
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_dt = dt;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -282,10 +309,11 @@ get_average_frame_rate_interval() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double ClockObject::
|
||||
get_average_frame_rate() const {
|
||||
CDStageReader cdata(_cycler, 0);
|
||||
if (_ticks.size() <= 1) {
|
||||
return 0.0;
|
||||
} else {
|
||||
return _ticks.size() / (_reported_frame_time - _ticks.front());
|
||||
return _ticks.size() / (cdata->_reported_frame_time - _ticks.front());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -301,6 +329,7 @@ get_average_frame_rate() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ClockObject::
|
||||
check_errors() {
|
||||
CDReader cdata(_cycler); // Just to hold a mutex.
|
||||
int orig_error_count = _error_count;
|
||||
_error_count = _true_clock->get_error_count();
|
||||
return (_error_count != orig_error_count);
|
||||
|
|
@ -321,6 +350,19 @@ get_global_clock() {
|
|||
return _global_clock;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClockObject::CData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ClockObject::CData::
|
||||
CData(const ClockObject::CData ©) :
|
||||
_frame_count(copy._frame_count),
|
||||
_reported_frame_time(copy._reported_frame_time),
|
||||
_dt(copy._dt)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TimeVal::contructor
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -20,16 +20,10 @@
|
|||
#include "clockObject.h"
|
||||
#include "config_express.h"
|
||||
#include "configVariableEnum.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#define WINDOWS_LEAN_AND_MEAN
|
||||
#include <wtypes.h> // For select()
|
||||
#undef WINDOWS_LEAN_AND_MEAN
|
||||
#else
|
||||
#include <sys/time.h> // For select()
|
||||
#endif
|
||||
#include "thread.h"
|
||||
|
||||
ClockObject *ClockObject::_global_clock = (ClockObject *)NULL;
|
||||
TypeHandle ClockObject::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClockObject::Constructor
|
||||
|
|
@ -47,10 +41,7 @@ ClockObject() {
|
|||
|
||||
_start_short_time = _true_clock->get_short_time();
|
||||
_start_long_time = _true_clock->get_long_time();
|
||||
_frame_count = 0;
|
||||
_actual_frame_time = 0.0;
|
||||
_reported_frame_time = 0.0;
|
||||
_dt = 1.0 / clock_frame_rate;
|
||||
_max_dt = max_dt;
|
||||
_degrade_factor = clock_degrade_factor;
|
||||
_average_frame_rate_interval = average_frame_rate_interval;
|
||||
|
|
@ -91,6 +82,7 @@ set_real_time(double time) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void ClockObject::
|
||||
set_frame_time(double time) {
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
#ifdef NOTIFY_DEBUG
|
||||
if (this == _global_clock && _mode != M_slave) {
|
||||
express_cat.warning()
|
||||
|
|
@ -98,8 +90,9 @@ set_frame_time(double time) {
|
|||
<< " seconds.\n";
|
||||
}
|
||||
#endif // NOTIFY_DEBUG
|
||||
CDWriter cdata(_cycler);
|
||||
_actual_frame_time = time;
|
||||
_reported_frame_time = time;
|
||||
cdata->_reported_frame_time = time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -111,6 +104,7 @@ set_frame_time(double time) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void ClockObject::
|
||||
set_frame_count(int frame_count) {
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
#ifdef NOTIFY_DEBUG
|
||||
if (this == _global_clock && _mode != M_slave) {
|
||||
express_cat.warning()
|
||||
|
|
@ -118,7 +112,8 @@ set_frame_count(int frame_count) {
|
|||
<< frame_count - get_frame_count() << " frames.\n";
|
||||
}
|
||||
#endif // NOTIFY_DEBUG
|
||||
_frame_count = frame_count;
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_frame_count = frame_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -133,7 +128,9 @@ set_frame_count(int frame_count) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void ClockObject::
|
||||
tick() {
|
||||
double old_reported_time = _reported_frame_time;
|
||||
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||
CDWriter cdata(_cycler);
|
||||
double old_reported_time = cdata->_reported_frame_time;
|
||||
|
||||
if (_mode != M_slave) {
|
||||
double old_time = _actual_frame_time;
|
||||
|
|
@ -142,39 +139,39 @@ tick() {
|
|||
switch (_mode) {
|
||||
case M_normal:
|
||||
// Time runs as it will; we simply report time elapsing.
|
||||
_dt = _actual_frame_time - old_time;
|
||||
_reported_frame_time = _actual_frame_time;
|
||||
cdata->_dt = _actual_frame_time - old_time;
|
||||
cdata->_reported_frame_time = _actual_frame_time;
|
||||
break;
|
||||
|
||||
case M_non_real_time:
|
||||
// Ignore real time. We always report the same interval having
|
||||
// elapsed each frame.
|
||||
_reported_frame_time += _dt;
|
||||
cdata->_reported_frame_time += cdata->_dt;
|
||||
break;
|
||||
|
||||
case M_forced:
|
||||
// If we are running faster than the desired interval, slow down.
|
||||
// If we are running slower than the desired interval, ignore that
|
||||
// and pretend we're running at the specified rate.
|
||||
wait_until(old_time + _dt);
|
||||
_reported_frame_time += _dt;
|
||||
wait_until(old_time + cdata->_dt);
|
||||
cdata->_reported_frame_time += cdata->_dt;
|
||||
break;
|
||||
|
||||
case M_degrade:
|
||||
// Each frame, wait a certain fraction of the previous frame's
|
||||
// time to degrade performance uniformly.
|
||||
_dt = (_actual_frame_time - old_time) * _degrade_factor;
|
||||
cdata->_dt = (_actual_frame_time - old_time) * _degrade_factor;
|
||||
|
||||
if (_degrade_factor < 1.0) {
|
||||
// If the degrade_factor is less than one, we want to simulate a
|
||||
// higher frame rate by incrementing the clock more slowly.
|
||||
_reported_frame_time += _dt;
|
||||
cdata->_reported_frame_time += cdata->_dt;
|
||||
|
||||
} else {
|
||||
// Otherwise, we simulate a lower frame rate by waiting until
|
||||
// the appropriate time has elapsed.
|
||||
wait_until(old_time + _dt);
|
||||
_reported_frame_time = _actual_frame_time;
|
||||
wait_until(old_time + cdata->_dt);
|
||||
cdata->_reported_frame_time = _actual_frame_time;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -184,13 +181,13 @@ tick() {
|
|||
break;
|
||||
}
|
||||
|
||||
_frame_count++;
|
||||
cdata->_frame_count++;
|
||||
}
|
||||
|
||||
if (_average_frame_rate_interval > 0.0) {
|
||||
_ticks.push_back(old_reported_time);
|
||||
while (!_ticks.empty() &&
|
||||
_reported_frame_time - _ticks.front() > _average_frame_rate_interval) {
|
||||
cdata->_reported_frame_time - _ticks.front() > _average_frame_rate_interval) {
|
||||
_ticks.pop_front();
|
||||
}
|
||||
}
|
||||
|
|
@ -213,7 +210,8 @@ tick() {
|
|||
void ClockObject::
|
||||
sync_frame_time() {
|
||||
if (_mode == M_normal) {
|
||||
_reported_frame_time = get_real_time();
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_reported_frame_time = get_real_time();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,10 +227,7 @@ wait_until(double want_time) {
|
|||
double wait_interval = (want_time - _actual_frame_time) - sleep_precision;
|
||||
|
||||
if (wait_interval > 0.0) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = (int)(wait_interval);
|
||||
tv.tv_usec = (int)((wait_interval - tv.tv_sec) * 1000000.0);
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
Thread::sleep(wait_interval);
|
||||
}
|
||||
|
||||
// Now busy-wait until the actual time elapses.
|
||||
|
|
@ -262,6 +257,28 @@ make_global_clock() {
|
|||
_global_clock->set_mode(clock_mode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClockObject::CData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ClockObject::CData::
|
||||
CData() {
|
||||
_frame_count = 0;
|
||||
_reported_frame_time = 0.0;
|
||||
_dt = 1.0 / clock_frame_rate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClockObject::CData::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *ClockObject::CData::
|
||||
make_copy() const {
|
||||
return new CData(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClockObject::Mode ostream operator
|
||||
// Description:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@
|
|||
|
||||
#include "trueClock.h"
|
||||
#include "pdeque.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
#include "pipelineCycler.h"
|
||||
|
||||
class EXPCL_PANDAEXPRESS TimeVal {
|
||||
PUBLISHED:
|
||||
|
|
@ -113,10 +118,7 @@ private:
|
|||
Mode _mode;
|
||||
double _start_short_time;
|
||||
double _start_long_time;
|
||||
int _frame_count;
|
||||
double _actual_frame_time;
|
||||
double _reported_frame_time;
|
||||
double _dt;
|
||||
double _max_dt;
|
||||
double _degrade_factor;
|
||||
int _error_count;
|
||||
|
|
@ -127,7 +129,39 @@ private:
|
|||
typedef pdeque<double> Ticks;
|
||||
Ticks _ticks;
|
||||
|
||||
// This is the data that needs to be cycled each frame.
|
||||
class EXPCL_PANDAEXPRESS CData : public CycleData {
|
||||
public:
|
||||
CData();
|
||||
INLINE CData(const CData ©);
|
||||
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return ClockObject::get_class_type();
|
||||
}
|
||||
|
||||
int _frame_count;
|
||||
double _reported_frame_time;
|
||||
double _dt;
|
||||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataStageReader<CData> CDStageReader;
|
||||
|
||||
static ClockObject *_global_clock;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
register_type(_type_handle, "ClockObject");
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
EXPCL_PANDAEXPRESS ostream &
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
|
||||
#include "config_express.h"
|
||||
#include "clockObject.h"
|
||||
#include "datagram.h"
|
||||
#include "mainThread.h"
|
||||
#include "externalThread.h"
|
||||
|
|
@ -168,6 +169,7 @@ init_libexpress() {
|
|||
}
|
||||
initialized = true;
|
||||
|
||||
ClockObject::init_type();
|
||||
Datagram::init_type();
|
||||
MainThread::init_type();
|
||||
ExternalThread::init_type();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "clockObject.h"
|
||||
#include "dconfig.h"
|
||||
|
||||
// We include these files to force them to be instrumented by
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// Filename: cycleData.I
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CycleData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData::
|
||||
CycleData() {
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
// Filename: cycleData.cxx
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cycleData.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData::
|
||||
~CycleData() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CycleData::
|
||||
write_datagram(BamWriter *, Datagram &) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CycleData::
|
||||
write_datagram(BamWriter *, Datagram &, void *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::complete_pointers
|
||||
// Access: Public, Virtual
|
||||
// Description: Receives an array of pointers, one for each time
|
||||
// manager->read_pointer() was called in fillin().
|
||||
// Returns the number of pointers processed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CycleData::
|
||||
complete_pointers(TypedWritable **, BamReader *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::fillin
|
||||
// Access: Public, Virtual
|
||||
// Description: This internal function is intended to be called by
|
||||
// each class's make_from_bam() method to read in all of
|
||||
// the relevant data from the BamFile for the new
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CycleData::
|
||||
fillin(DatagramIterator &, BamReader *) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::fillin
|
||||
// Access: Public, Virtual
|
||||
// Description: This internal function is intended to be called by
|
||||
// each class's make_from_bam() method to read in all of
|
||||
// the relevant data from the BamFile for the new
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CycleData::
|
||||
fillin(DatagramIterator &, BamReader *, void *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::get_parent_type
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the type of the container that owns the
|
||||
// CycleData. This is useful mainly for debugging.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle CycleData::
|
||||
get_parent_type() const {
|
||||
return TypeHandle::none();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::output
|
||||
// Access: Public, Virtual
|
||||
// Description: Formats the contents of the CycleData in some
|
||||
// meaningful way for humans. This is useful mainly for
|
||||
// debugging.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CycleData::
|
||||
output(ostream &out) const {
|
||||
out << get_parent_type() << "::CData";
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Filename: cycleData.h
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLEDATA_H
|
||||
#define CYCLEDATA_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "typeHandle.h"
|
||||
#include "referenceCount.h"
|
||||
|
||||
class BamWriter;
|
||||
class BamReader;
|
||||
class TypedWritable;
|
||||
class Datagram;
|
||||
class DatagramIterator;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleData
|
||||
// Description : A single page of data maintained by a PipelineCycler.
|
||||
// Normally you should inherit from this class to define
|
||||
// the data structures that are important to protect
|
||||
// between stages of a pipeline. See PipelineCycler.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef DO_PIPELINING
|
||||
|
||||
// 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_PANDAEXPRESS CycleData : public ReferenceCount
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
|
||||
// If we are *not* compiling in pipelining support, the CycleData
|
||||
// object is stored directly within its containing classes, and hence
|
||||
// should not be a ReferenceCount object.
|
||||
class EXPCL_PANDAEXPRESS CycleData
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
{
|
||||
public:
|
||||
INLINE CycleData();
|
||||
virtual ~CycleData();
|
||||
|
||||
virtual CycleData *make_copy() const=0;
|
||||
|
||||
virtual void write_datagram(BamWriter *, Datagram &) const;
|
||||
virtual void write_datagram(BamWriter *, Datagram &, void *extra_data) const;
|
||||
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager,
|
||||
void *extra_data);
|
||||
|
||||
virtual TypeHandle get_parent_type() const;
|
||||
virtual void output(ostream &out) const;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const CycleData &cd) {
|
||||
cd.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "cycleData.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
// Filename: cycleDataReader.I
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CycleDataReader::Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
CycleDataReader(const PipelineCycler<CycleDataType> &cycler) :
|
||||
_cycler(&cycler)
|
||||
{
|
||||
_pointer = _cycler->read();
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Copy Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
CycleDataReader(const CycleDataReader<CycleDataType> ©) :
|
||||
_cycler(copy._cycler),
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Copy Assignment (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataReader<CycleDataType>::
|
||||
operator = (const CycleDataReader<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Destructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
~CycleDataReader() {
|
||||
if (_pointer != NULL) {
|
||||
_cycler->release_read(_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Typecast pointer (full)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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;
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// This is the trivial, do-nothing implementation.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
CycleDataReader(const PipelineCycler<CycleDataType> &cycler) {
|
||||
_pointer = cycler.read();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
CycleDataReader(const CycleDataReader<CycleDataType> ©) :
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Copy Assignment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataReader<CycleDataType>::
|
||||
operator = (const CycleDataReader<CycleDataType> ©) {
|
||||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
~CycleDataReader() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataReader::Typecast pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataReader<CycleDataType>::
|
||||
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;
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: cycleDataReader.cxx
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cycleDataReader.h"
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Filename: cycleDataReader.h
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLEDATAREADER_H
|
||||
#define CYCLEDATAREADER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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.
|
||||
//
|
||||
// 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 CycleDataReader {
|
||||
public:
|
||||
INLINE CycleDataReader(const PipelineCycler<CycleDataType> &cycler);
|
||||
INLINE CycleDataReader(const CycleDataReader<CycleDataType> ©);
|
||||
INLINE void operator = (const CycleDataReader<CycleDataType> ©);
|
||||
|
||||
INLINE ~CycleDataReader();
|
||||
|
||||
INLINE const CycleDataType *operator -> () const;
|
||||
INLINE operator const CycleDataType * () const;
|
||||
|
||||
INLINE const CycleDataType *take_pointer();
|
||||
|
||||
private:
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the data stored for a real pipelining implementation.
|
||||
const PipelineCycler<CycleDataType> *_cycler;
|
||||
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 "cycleDataReader.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
// Filename: cycleDataStageReader.I
|
||||
// Created by: drose (08Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CycleDataStageReader::Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler,
|
||||
int stage) :
|
||||
_cycler(&cycler),
|
||||
_stage(stage)
|
||||
{
|
||||
_pointer = _cycler->read_stage(_stage);
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Copy Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
CycleDataStageReader(const CycleDataStageReader<CycleDataType> ©) :
|
||||
_cycler(copy._cycler),
|
||||
_pointer(copy._pointer),
|
||||
_stage(copy._stage)
|
||||
{
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Copy Assignment (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageReader<CycleDataType>::
|
||||
operator = (const CycleDataStageReader<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
_stage = copy._stage;
|
||||
|
||||
nassertv(_pointer != (const CycleDataType *)NULL);
|
||||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Destructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
~CycleDataStageReader() {
|
||||
if (_pointer != NULL) {
|
||||
_cycler->release_read_stage(_stage, _pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataStageReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (const CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Typecast pointer (full)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataStageReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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;
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// This is the trivial, do-nothing implementation.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler, int) {
|
||||
_pointer = cycler.read();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
CycleDataStageReader(const CycleDataStageReader<CycleDataType> ©) :
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Copy Assignment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageReader<CycleDataType>::
|
||||
operator = (const CycleDataStageReader<CycleDataType> ©) {
|
||||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
~CycleDataStageReader() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataStageReader<CycleDataType>::
|
||||
operator -> () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageReader::Typecast pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataStageReader to be passed to any
|
||||
// function that expects a const CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageReader<CycleDataType>::
|
||||
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;
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: cycleDataStageReader.cxx
|
||||
// Created by: drose (08Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cycleDataStageReader.h"
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// Filename: cycleDataStageReader.h
|
||||
// Created by: drose (08Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLEDATASTAGEREADER_H
|
||||
#define CYCLEDATASTAGEREADER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleDataStageReader
|
||||
// Description : This class is similar to CycleDataReader, except it
|
||||
// allows reading from a particular stage of the
|
||||
// pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
class CycleDataStageReader {
|
||||
public:
|
||||
INLINE CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler, int stage);
|
||||
INLINE CycleDataStageReader(const CycleDataStageReader<CycleDataType> ©);
|
||||
INLINE void operator = (const CycleDataStageReader<CycleDataType> ©);
|
||||
|
||||
INLINE ~CycleDataStageReader();
|
||||
|
||||
INLINE const CycleDataType *operator -> () const;
|
||||
INLINE operator const CycleDataType * () const;
|
||||
|
||||
INLINE const CycleDataType *take_pointer();
|
||||
|
||||
private:
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the data stored for a real pipelining implementation.
|
||||
const PipelineCycler<CycleDataType> *_cycler;
|
||||
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 "cycleDataStageReader.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
// Filename: cycleDataStageWriter.I
|
||||
// Created by: drose (06Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CycleDataStageWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage) :
|
||||
_cycler(&cycler),
|
||||
_stage(stage)
|
||||
{
|
||||
_pointer = _cycler->write_stage(_stage);
|
||||
nassertv(_pointer != (CycleDataType *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Copy Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> ©) :
|
||||
_cycler(copy._cycler),
|
||||
_pointer(copy._pointer),
|
||||
_stage(copy._stage)
|
||||
{
|
||||
nassertv(_pointer != (CycleDataType *)NULL);
|
||||
_cycler->increment_write(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Copy Assigment (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageWriter<CycleDataType>::
|
||||
operator = (const CycleDataStageWriter<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
_stage = copy._stage;
|
||||
|
||||
nassertv(_pointer != (CycleDataType *)NULL);
|
||||
_cycler->increment_write(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataStageReader 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) :
|
||||
_cycler(&cycler),
|
||||
_stage(stage)
|
||||
{
|
||||
_pointer = _cycler->elevate_read_stage(_stage, take_from.take_pointer());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Destructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
~CycleDataStageWriter() {
|
||||
if (_pointer != (CycleDataType *)NULL) {
|
||||
_cycler->release_write_stage(_stage, _pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *CycleDataStageWriter<CycleDataType>::
|
||||
operator -> () {
|
||||
nassertr(_pointer != (CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataStageWriter<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Typecast pointer (full)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataStageWriter to be passed to any
|
||||
// function that expects a CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
operator CycleDataType * () {
|
||||
nassertr(_pointer != (CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// This is the trivial, do-nothing implementation.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int) {
|
||||
_pointer = cycler.write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> ©) :
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Copy Assigment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageWriter<CycleDataType>::
|
||||
operator = (const CycleDataStageWriter<CycleDataType> ©) {
|
||||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataStageReader 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) :
|
||||
_pointer((CycleDataType *)take_from.take_pointer())
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
~CycleDataStageWriter() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *CycleDataStageWriter<CycleDataType>::
|
||||
operator -> () {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataStageWriter<CycleDataType>::
|
||||
operator -> () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataStageWriter::Typecast pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataStageWriter to be passed to any
|
||||
// function that expects a CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
operator CycleDataType * () {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: cycleDataStageWriter.cxx
|
||||
// Created by: drose (06Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cycleDataStageWriter.h"
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Filename: cycleDataStageWriter.h
|
||||
// Created by: drose (06Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLEDATASTAGEWRITER_H
|
||||
#define CYCLEDATASTAGEWRITER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
#include "cycleDataStageReader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleDataStageWriter
|
||||
// Description : This class is similar to CycleDataWriter, except it
|
||||
// allows writing to a particular stage of the pipeline.
|
||||
// Usually this is used to implement writing directly to
|
||||
// an upstream pipeline value, to recompute a cached
|
||||
// value there (otherwise, the cached value would go
|
||||
// away with the next pipeline cycle).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
class CycleDataStageWriter {
|
||||
public:
|
||||
INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage);
|
||||
INLINE CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> ©);
|
||||
INLINE void operator = (const CycleDataStageWriter<CycleDataType> ©);
|
||||
|
||||
INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
|
||||
CycleDataStageReader<CycleDataType> &take_from);
|
||||
|
||||
INLINE ~CycleDataStageWriter();
|
||||
|
||||
INLINE CycleDataType *operator -> ();
|
||||
INLINE const CycleDataType *operator -> () const;
|
||||
|
||||
INLINE operator CycleDataType * ();
|
||||
|
||||
private:
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the data stored for a real pipelining implementation.
|
||||
PipelineCycler<CycleDataType> *_cycler;
|
||||
CycleDataType *_pointer;
|
||||
int _stage;
|
||||
#else // !DO_PIPELINING
|
||||
// This is all we need for the trivial, do-nothing implementation.
|
||||
CycleDataType *_pointer;
|
||||
#endif // DO_PIPELINING
|
||||
};
|
||||
|
||||
#include "cycleDataStageWriter.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
// Filename: cycleDataWriter.I
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CycleDataWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &cycler) :
|
||||
_cycler(&cycler)
|
||||
{
|
||||
_pointer = _cycler->write();
|
||||
nassertv(_pointer != (CycleDataType *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This two-parameter constructor, with a bool parameter
|
||||
// for the second parameter, automatically propagates
|
||||
// the CycleData pointer upstream from the current
|
||||
// stage, either stopping at the first pointer
|
||||
// encountered that's different, going or all the way to
|
||||
// stage 0, according to force_to_0. See
|
||||
// PipelineCycler::write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool force_to_0) :
|
||||
_cycler(&cycler)
|
||||
{
|
||||
_pointer = _cycler->write_upstream(force_to_0);
|
||||
nassertv(_pointer != (CycleDataType *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Copy Constructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(const CycleDataWriter<CycleDataType> ©) :
|
||||
_cycler(copy._cycler),
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
nassertv(_pointer != (CycleDataType *)NULL);
|
||||
_cycler->increment_write(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Copy Assigment (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataWriter<CycleDataType>::
|
||||
operator = (const CycleDataWriter<CycleDataType> ©) {
|
||||
nassertv(_pointer == (CycleDataType *)NULL);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
|
||||
nassertv(_pointer != (CycleDataType *)NULL);
|
||||
_cycler->increment_write(_pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader 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) :
|
||||
_cycler(&cycler)
|
||||
{
|
||||
_pointer = _cycler->elevate_read(take_from.take_pointer());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader from a read to a write
|
||||
// pointer (and invalidates the reader). It also
|
||||
// propagates the pointer back upstream; see
|
||||
// PipelineCycler::write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
|
||||
CycleDataReader<CycleDataType> &take_from,
|
||||
bool force_to_0) :
|
||||
_cycler(&cycler)
|
||||
{
|
||||
_pointer = _cycler->elevate_read_upstream(take_from.take_pointer(), force_to_0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Destructor (full)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
~CycleDataWriter() {
|
||||
if (_pointer != (CycleDataType *)NULL) {
|
||||
_cycler->release_write(_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *CycleDataWriter<CycleDataType>::
|
||||
operator -> () {
|
||||
nassertr(_pointer != (CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::operator -> (full)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataWriter<CycleDataType>::
|
||||
operator -> () const {
|
||||
nassertr(_pointer != (CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Typecast pointer (full)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataWriter to be passed to any
|
||||
// function that expects a CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
operator CycleDataType * () {
|
||||
nassertr(_pointer != (CycleDataType *)NULL, _cycler->cheat());
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// This is the trivial, do-nothing implementation.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &cycler) {
|
||||
_pointer = cycler.write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Constructor (full)
|
||||
// Access: Public
|
||||
// Description: This two-parameter constructor, with a bool parameter
|
||||
// for the second parameter, automatically propagates
|
||||
// the CycleData pointer upstream from the current
|
||||
// stage, either stopping at the first pointer
|
||||
// encountered that's different, going or all the way to
|
||||
// stage 0, according to force_to_0. See
|
||||
// PipelineCycler::write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool) {
|
||||
_pointer = cycler.write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(const CycleDataWriter<CycleDataType> ©) :
|
||||
_pointer(copy._pointer)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Copy Assigment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataWriter<CycleDataType>::
|
||||
operator = (const CycleDataWriter<CycleDataType> ©) {
|
||||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader from a read to a write
|
||||
// pointer (and invalidates the reader).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &,
|
||||
CycleDataReader<CycleDataType> &take_from) :
|
||||
_pointer((CycleDataType *)take_from.take_pointer())
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description: This flavor of the constructor elevates the pointer
|
||||
// from the CycleDataReader from a read to a write
|
||||
// pointer (and invalidates the reader). It also
|
||||
// propagates the pointer back upstream; see
|
||||
// PipelineCycler::write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
CycleDataWriter(PipelineCycler<CycleDataType> &,
|
||||
CycleDataReader<CycleDataType> &take_from,
|
||||
bool force_to_0) :
|
||||
_pointer((CycleDataType *)take_from.take_pointer())
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Destructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
~CycleDataWriter() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *CycleDataWriter<CycleDataType>::
|
||||
operator -> () {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::operator -> (trivial)
|
||||
// Access: Public
|
||||
// Description: This provides an indirect member access to the actual
|
||||
// CycleData data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *CycleDataWriter<CycleDataType>::
|
||||
operator -> () const {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleDataWriter::Typecast pointer (trivial)
|
||||
// Access: Public
|
||||
// Description: This allows the CycleDataWriter to be passed to any
|
||||
// function that expects a CycleDataType pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataWriter<CycleDataType>::
|
||||
operator CycleDataType * () {
|
||||
return _pointer;
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: cycleDataWriter.cxx
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cycleDataWriter.h"
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Filename: cycleDataWriter.h
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLEDATAWRITER_H
|
||||
#define CYCLEDATAWRITER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipelineCycler.h"
|
||||
#include "cycleDataReader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CycleDataWriter
|
||||
// Description : This template class calls PipelineCycler::write() in
|
||||
// the constructor and PipelineCycler::release_write() in
|
||||
// the destructor. In the interim, it provides a
|
||||
// transparent read-write access to the CycleData.
|
||||
//
|
||||
// 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 CycleDataWriter {
|
||||
public:
|
||||
INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler);
|
||||
INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool force_to_0);
|
||||
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();
|
||||
|
||||
INLINE CycleDataType *operator -> ();
|
||||
INLINE const CycleDataType *operator -> () const;
|
||||
|
||||
INLINE operator CycleDataType * ();
|
||||
|
||||
private:
|
||||
#ifdef DO_PIPELINING
|
||||
// This is the data stored for a real pipelining implementation.
|
||||
PipelineCycler<CycleDataType> *_cycler;
|
||||
CycleDataType *_pointer;
|
||||
#else // !DO_PIPELINING
|
||||
// This is all we need for the trivial, do-nothing implementation.
|
||||
CycleDataType *_pointer;
|
||||
#endif // DO_PIPELINING
|
||||
};
|
||||
|
||||
#include "cycleDataWriter.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// Filename: cyclerHolder.I
|
||||
// Created by: drose (09Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: CyclerHolder::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CyclerHolder::
|
||||
CyclerHolder(PipelineCyclerBase &cycler) {
|
||||
#ifdef DO_PIPELINING
|
||||
_cycler = &cycler;
|
||||
_cycler->lock();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CyclerHolder::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CyclerHolder::
|
||||
~CyclerHolder() {
|
||||
#ifdef DO_PIPELINING
|
||||
_cycler->release();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CyclerHolder::Copy Constructor
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy CyclerHolders.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CyclerHolder::
|
||||
CyclerHolder(const CyclerHolder ©) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CyclerHolder::Copy Assignment Operator
|
||||
// Access: Private
|
||||
// Description: Do not attempt to copy CyclerHolders.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CyclerHolder::
|
||||
operator = (const CyclerHolder ©) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: cyclerHolder.cxx
|
||||
// Created by: drose (09Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "cyclerHolder.h"
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Filename: cyclerHolder.h
|
||||
// Created by: drose (09Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 CYCLERHOLDER_H
|
||||
#define CYCLERHOLDER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pipelineCyclerBase.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CyclerHolder
|
||||
// Description : A lightweight C++ object whose constructor calls
|
||||
// lock() and whose destructor calls release() on a
|
||||
// PipelineCyclerBase object. This is similar to a
|
||||
// MutexHolder.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS CyclerHolder {
|
||||
public:
|
||||
INLINE CyclerHolder(PipelineCyclerBase &cycler);
|
||||
INLINE ~CyclerHolder();
|
||||
private:
|
||||
INLINE CyclerHolder(const CyclerHolder ©);
|
||||
INLINE void operator = (const CyclerHolder ©);
|
||||
|
||||
private:
|
||||
#ifdef DO_PIPELINING
|
||||
PipelineCyclerBase *_cycler;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "cyclerHolder.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -14,6 +14,12 @@
|
|||
#include "conditionVarPosixImpl.cxx"
|
||||
#include "conditionVarWin32Impl.cxx"
|
||||
#include "config_express.cxx"
|
||||
#include "cycleData.cxx"
|
||||
#include "cycleDataReader.cxx"
|
||||
#include "cycleDataStageReader.cxx"
|
||||
#include "cycleDataStageWriter.cxx"
|
||||
#include "cycleDataWriter.cxx"
|
||||
#include "cyclerHolder.cxx"
|
||||
#include "datagram.cxx"
|
||||
#include "datagramGenerator.cxx"
|
||||
#include "datagramIterator.cxx"
|
||||
|
|
@ -37,3 +43,5 @@
|
|||
#include "namable.cxx"
|
||||
#include "nativeNumericData.cxx"
|
||||
#include "ordered_vector.cxx"
|
||||
#include "patchfile.cxx"
|
||||
#include "password_hash.cxx"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "patchfile.cxx"
|
||||
#include "password_hash.cxx"
|
||||
#include "pipeline.cxx"
|
||||
#include "pipelineCycler.cxx"
|
||||
#include "pipelineCyclerDummyImpl.cxx"
|
||||
#include "pipelineCyclerTrivialImpl.cxx"
|
||||
#include "pipelineCyclerTrueImpl.cxx"
|
||||
#include "pmutex.cxx"
|
||||
#include "pointerTo.cxx"
|
||||
#include "pointerToArray.cxx"
|
||||
|
|
@ -42,4 +45,3 @@
|
|||
#include "windowsRegistry.cxx"
|
||||
#include "zStream.cxx"
|
||||
#include "zStreamBuf.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
// Filename: pipeline.I
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: Pipeline::get_render_pipeline
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the global render pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Pipeline *Pipeline::
|
||||
get_render_pipeline() {
|
||||
if (_render_pipeline == (Pipeline *)NULL) {
|
||||
make_render_pipeline();
|
||||
}
|
||||
return _render_pipeline;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::set_min_stages
|
||||
// Access: Public
|
||||
// Description: Ensures that at least the indicated number of stages
|
||||
// are in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Pipeline::
|
||||
set_min_stages(int min_stages) {
|
||||
set_num_stages(max(min_stages, get_num_stages()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::get_num_stages
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages required for the
|
||||
// pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Pipeline::
|
||||
get_num_stages() const {
|
||||
return _num_stages;
|
||||
}
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::get_num_cyclers
|
||||
// Access: Public
|
||||
// Description: Returns the number of PipelineCyclers in the universe
|
||||
// that reference this Pipeline object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Pipeline::
|
||||
get_num_cyclers() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _num_cyclers;
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::get_num_dirty_cyclers
|
||||
// Access: Public
|
||||
// Description: Returns the number of PipelineCyclers in the universe
|
||||
// that reference this Pipeline object and are currently
|
||||
// marked "dirty"; that is, there is a difference in
|
||||
// pointer value between some of their stages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Pipeline::
|
||||
get_num_dirty_cyclers() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _dirty_cyclers.size();
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
|
|
@ -0,0 +1,377 @@
|
|||
// Filename: pipeline.cxx
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "pipeline.h"
|
||||
#include "pipelineCyclerTrueImpl.h"
|
||||
#include "reMutexHolder.h"
|
||||
#include "configVariableInt.h"
|
||||
#include "config_express.h"
|
||||
|
||||
Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Pipeline::
|
||||
Pipeline(const string &name, int num_stages) :
|
||||
Namable(name)
|
||||
{
|
||||
#ifdef THREADED_PIPELINE
|
||||
// Set up the linked list of cyclers to be a circular list that
|
||||
// begins with this object.
|
||||
_prev = this;
|
||||
_next = this;
|
||||
|
||||
_num_cyclers = 0;
|
||||
_cycling = false;
|
||||
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
set_num_stages(num_stages);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Pipeline::
|
||||
~Pipeline() {
|
||||
#ifdef THREADED_PIPELINE
|
||||
nassertv(_num_cyclers == 0);
|
||||
nassertv(_prev == this && _next == this);
|
||||
_prev = NULL;
|
||||
_next = NULL;
|
||||
nassertv(!_cycling);
|
||||
#endif // THREADED_PIPELINE
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::cycle
|
||||
// Access: Public
|
||||
// Description: Flows all the pipeline data down to the next stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
cycle() {
|
||||
#ifdef THREADED_PIPELINE
|
||||
pvector< PT(CycleData) > saved_cdatas;
|
||||
saved_cdatas.reserve(_dirty_cyclers.size());
|
||||
{
|
||||
ReMutexHolder holder(_lock);
|
||||
if (_num_stages == 1) {
|
||||
// No need to cycle if there's only one stage.
|
||||
nassertv(_dirty_cyclers.empty());
|
||||
return;
|
||||
}
|
||||
|
||||
nassertv(!_cycling);
|
||||
_cycling = true;
|
||||
|
||||
Cyclers next_dirty_cyclers;
|
||||
|
||||
Cyclers::iterator ci;
|
||||
switch (_num_stages) {
|
||||
case 2:
|
||||
for (ci = _dirty_cyclers.begin(); ci != _dirty_cyclers.end(); ++ci) {
|
||||
PipelineCyclerTrueImpl *cycler = (*ci);
|
||||
ReMutexHolder holder2(cycler->_lock);
|
||||
|
||||
// We save the result of cycle(), so that we can defer the
|
||||
// side-effects that might occur when CycleDatas destruct, at
|
||||
// least until the end of this loop.
|
||||
saved_cdatas.push_back(cycler->cycle_2());
|
||||
|
||||
if (cycler->_dirty) {
|
||||
// The cycler is still dirty after cycling. Preserve it in the
|
||||
// set for next time.
|
||||
bool inserted = next_dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
} else {
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
for (ci = _dirty_cyclers.begin(); ci != _dirty_cyclers.end(); ++ci) {
|
||||
PipelineCyclerTrueImpl *cycler = (*ci);
|
||||
ReMutexHolder holder2(cycler->_lock);
|
||||
|
||||
saved_cdatas.push_back(cycler->cycle_3());
|
||||
if (cycler->_dirty) {
|
||||
bool inserted = next_dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
} else {
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
for (ci = _dirty_cyclers.begin(); ci != _dirty_cyclers.end(); ++ci) {
|
||||
PipelineCyclerTrueImpl *cycler = (*ci);
|
||||
ReMutexHolder holder2(cycler->_lock);
|
||||
|
||||
saved_cdatas.push_back(cycler->cycle());
|
||||
if (cycler->_dirty) {
|
||||
bool inserted = next_dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
} else {
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Finally, we're ready for the next frame.
|
||||
_dirty_cyclers.swap(next_dirty_cyclers);
|
||||
_cycling = false;
|
||||
}
|
||||
|
||||
// And now it's safe to let the CycleData pointers in saved_cdatas
|
||||
// destruct, which may cause cascading deletes, and which will in
|
||||
// turn case PipelineCyclers to remove themselves from (or add
|
||||
// themselves to) the _dirty_cyclers list.
|
||||
|
||||
#endif // THREADED_PIPELINE
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::set_num_stages
|
||||
// Access: Public
|
||||
// Description: Specifies the number of stages required for the
|
||||
// pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
set_num_stages(int num_stages) {
|
||||
nassertv(num_stages >= 1);
|
||||
#ifdef THREADED_PIPELINE
|
||||
ReMutexHolder holder(_lock);
|
||||
if (num_stages != _num_stages) {
|
||||
|
||||
// We need to lock every PipelineCycler object attached to this
|
||||
// pipeline before we can adjust the number of stages.
|
||||
PipelineCyclerLinks *links;
|
||||
for (links = this->_next; links != this; links = links->_next) {
|
||||
PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
|
||||
cycler->_lock.lock();
|
||||
}
|
||||
|
||||
_num_stages = num_stages;
|
||||
|
||||
for (links = this->_next; links != this; links = links->_next) {
|
||||
PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
|
||||
cycler->set_num_stages(num_stages);
|
||||
}
|
||||
|
||||
// Now release them all.
|
||||
int count = 0;
|
||||
for (links = this->_next; links != this; links = links->_next) {
|
||||
PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
|
||||
cycler->_lock.release();
|
||||
++count;
|
||||
}
|
||||
nassertv(count == _num_cyclers);
|
||||
}
|
||||
|
||||
#else // THREADED_PIPELINE
|
||||
if (num_stages != 1) {
|
||||
express_cat.warning()
|
||||
<< "Requested " << num_stages
|
||||
<< " pipeline stages but multithreaded render pipelines not enabled in build.\n";
|
||||
}
|
||||
_num_stages = 1;
|
||||
#endif // THREADED_PIPELINE
|
||||
}
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::add_cycler
|
||||
// Access: Public
|
||||
// Description: Adds the indicated cycler to the list of cyclers
|
||||
// associated with the pipeline. This method only
|
||||
// exists when true pipelining is configured on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
add_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(!cycler->_dirty);
|
||||
nassertv(!_cycling);
|
||||
++_num_cyclers;
|
||||
cycler->insert_before(this);
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), 1);
|
||||
#endif
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::add_dirty_cycler
|
||||
// Access: Public
|
||||
// Description: Marks the indicated cycler as "dirty", meaning it
|
||||
// will need to be cycled next frame. This both adds it
|
||||
// to the "dirty" set and also sets the "dirty" flag
|
||||
// within the cycler. This method only exists when true
|
||||
// pipelining is configured on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
add_dirty_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
nassertv(cycler->_lock.debug_is_locked());
|
||||
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(!_cycling);
|
||||
nassertv(!cycler->_dirty);
|
||||
cycler->_dirty = true;
|
||||
|
||||
bool inserted = _dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), 1);
|
||||
#endif
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::remove_cycler
|
||||
// Access: Public
|
||||
// Description: Removes the indicated cycler from the list of cyclers
|
||||
// associated with the pipeline. This method only
|
||||
// exists when true pipelining is configured on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
nassertv(cycler->_lock.debug_is_locked());
|
||||
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(!_cycling);
|
||||
|
||||
--_num_cyclers;
|
||||
cycler->remove_from_list();
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
|
||||
if (cycler->_dirty) {
|
||||
cycler->_dirty = false;
|
||||
Cyclers::iterator ci = _dirty_cyclers.find(cycler);
|
||||
nassertv(ci != _dirty_cyclers.end());
|
||||
_dirty_cyclers.erase(ci);
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::iterate_all_cycler_types
|
||||
// Access: Public
|
||||
// Description: Walks through the list of all the different
|
||||
// PipelineCycler types in the universe. For each one,
|
||||
// calls the indicated callback function with the
|
||||
// TypeHandle of the respective type (actually, the
|
||||
// result of cycler::get_parent_type()) and the count of
|
||||
// pipeline cyclers of that type. Mainly used for
|
||||
// PStats reporting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
iterate_all_cycler_types(CallbackFunc *func, void *data) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
TypeCount::const_iterator ci;
|
||||
for (ci = _all_cycler_types.begin(); ci != _all_cycler_types.end(); ++ci) {
|
||||
func((*ci).first, (*ci).second, data);
|
||||
}
|
||||
}
|
||||
#endif // THREADED_PIPELINE && DEBUG_THREADS
|
||||
|
||||
#if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::iterate_dirty_cycler_types
|
||||
// Access: Public
|
||||
// Description: Walks through the list of all the different
|
||||
// PipelineCycler types, for only the dirty
|
||||
// PipelineCyclers. See also
|
||||
// iterate_all_cycler_types().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
iterate_dirty_cycler_types(CallbackFunc *func, void *data) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
TypeCount::const_iterator ci;
|
||||
for (ci = _dirty_cycler_types.begin(); ci != _dirty_cycler_types.end(); ++ci) {
|
||||
func((*ci).first, (*ci).second, data);
|
||||
}
|
||||
}
|
||||
#endif // THREADED_PIPELINE && DEBUG_THREADS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::make_render_pipeline
|
||||
// Access: Private, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
make_render_pipeline() {
|
||||
ConfigVariableInt pipeline_stages
|
||||
("pipeline-stages", 1,
|
||||
PRC_DESC("The initial number of stages in the render pipeline. This is "
|
||||
"only meaningful if threaded pipelining is compiled into "
|
||||
"Panda. In most cases, you should not set this at all anyway, "
|
||||
"since the pipeline can automatically grow stages as needed, "
|
||||
"but it will not remove stages automatically, and having more "
|
||||
"pipeline stages than your application requires will incur "
|
||||
"additional runtime overhead."));
|
||||
|
||||
nassertv(_render_pipeline == (Pipeline *)NULL);
|
||||
_render_pipeline = new Pipeline("render", pipeline_stages);
|
||||
}
|
||||
|
||||
#if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::inc_cycler_type
|
||||
// Access: Private, Static
|
||||
// Description: Increments (or decrements, according to added) the
|
||||
// value for TypeHandle in the indicated TypeCount map.
|
||||
// This is used in DEBUG_THREADS mode to track the types
|
||||
// of PipelineCyclers that are coming and going, mainly
|
||||
// for PStats reporting.
|
||||
//
|
||||
// It is assumed the lock is held during this call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
inc_cycler_type(TypeCount &count, TypeHandle type, int addend) {
|
||||
TypeCount::iterator ci = count.find(type);
|
||||
if (ci == count.end()) {
|
||||
ci = count.insert(TypeCount::value_type(type, 0)).first;
|
||||
}
|
||||
(*ci).second += addend;
|
||||
nassertv((*ci).second >= 0);
|
||||
}
|
||||
#endif // THREADED_PIPELINE && DEBUG_THREADS
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Filename: pipeline.h
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PIPELINE_H
|
||||
#define PIPELINE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pipelineCyclerLinks.h"
|
||||
#include "namable.h"
|
||||
#include "pset.h"
|
||||
#include "reMutex.h"
|
||||
#include "reMutexHolder.h"
|
||||
|
||||
struct PipelineCyclerTrueImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : Pipeline
|
||||
// Description : This class manages a staged pipeline of data, for
|
||||
// instance the render pipeline, so that each stage of
|
||||
// the pipeline can simultaneously access different
|
||||
// copies of the same data. It actually maintains a
|
||||
// collection of PipelineCycler objects, and manages the
|
||||
// turning of all of them at once.
|
||||
//
|
||||
// There is one default Pipeline object, the render
|
||||
// pipeline. Other specialty pipelines may be created
|
||||
// as needed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS Pipeline : public PipelineCyclerLinks, public Namable {
|
||||
public:
|
||||
Pipeline(const string &name, int num_stages);
|
||||
~Pipeline();
|
||||
|
||||
INLINE static Pipeline *get_render_pipeline();
|
||||
|
||||
void cycle();
|
||||
|
||||
void set_num_stages(int num_stages);
|
||||
INLINE void set_min_stages(int min_stages);
|
||||
INLINE int get_num_stages() const;
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
void add_cycler(PipelineCyclerTrueImpl *cycler);
|
||||
void add_dirty_cycler(PipelineCyclerTrueImpl *cycler);
|
||||
void remove_cycler(PipelineCyclerTrueImpl *cycler);
|
||||
|
||||
INLINE int get_num_cyclers() const;
|
||||
INLINE int get_num_dirty_cyclers() const;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
typedef void CallbackFunc(TypeHandle type, int count, void *data);
|
||||
void iterate_all_cycler_types(CallbackFunc *func, void *data) const;
|
||||
void iterate_dirty_cycler_types(CallbackFunc *func, void *data) const;
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
private:
|
||||
int _num_stages;
|
||||
|
||||
static void make_render_pipeline();
|
||||
static Pipeline *_render_pipeline;
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
int _num_cyclers;
|
||||
typedef pset<PipelineCyclerTrueImpl *> Cyclers;
|
||||
Cyclers _dirty_cyclers;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
typedef pmap<TypeHandle, int> TypeCount;
|
||||
TypeCount _all_cycler_types, _dirty_cycler_types;
|
||||
|
||||
static void inc_cycler_type(TypeCount &count, TypeHandle type, int addend);
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
// This is true only during cycle().
|
||||
bool _cycling;
|
||||
|
||||
ReMutex _lock;
|
||||
#endif // THREADED_PIPELINE
|
||||
};
|
||||
|
||||
#include "pipeline.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
// Filename: pipelineCycler.I
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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
|
||||
// The following implementations are to support the
|
||||
// PipelineCyclerDummyImpl or the PipelineCyclerTrueImpl.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Constructor (dummy or true)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE PipelineCycler<CycleDataType>::
|
||||
PipelineCycler(Pipeline *pipeline) :
|
||||
PipelineCyclerBase(new CycleDataType, pipeline)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Copy Constructor (dummy or true)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE PipelineCycler<CycleDataType>::
|
||||
PipelineCycler(const PipelineCycler<CycleDataType> ©) :
|
||||
PipelineCyclerBase(copy)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Copy Assignment (dummy or true)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void PipelineCycler<CycleDataType>::
|
||||
operator = (const PipelineCycler<CycleDataType> ©) {
|
||||
PipelineCyclerBase::operator = (copy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *PipelineCycler<CycleDataType>::
|
||||
read() const {
|
||||
return (const CycleDataType *)PipelineCyclerBase::read();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *PipelineCycler<CycleDataType>::
|
||||
read_stage(int n) const {
|
||||
return (const CycleDataType *)PipelineCyclerBase::read_stage(n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
write() {
|
||||
return (CycleDataType *)PipelineCyclerBase::write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::elevate_read (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::elevate_read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
elevate_read(const CycleDataType *pointer) {
|
||||
return (CycleDataType *)PipelineCyclerBase::elevate_read(pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::elevate_read_upstream (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::elevate_read_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
elevate_read_upstream(const CycleDataType *pointer, bool force_to_0) {
|
||||
return (CycleDataType *)PipelineCyclerBase::elevate_read_upstream(pointer, force_to_0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::elevate_read_stage (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::elevate_read_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
elevate_read_stage(int n, const CycleDataType *pointer) {
|
||||
return (CycleDataType *)PipelineCyclerBase::elevate_read_stage(n, pointer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write_upstream (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
write_upstream(bool force_to_0) {
|
||||
return (CycleDataType *)PipelineCyclerBase::write_upstream(force_to_0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write_stage (dummy or true)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
write_stage(int n) {
|
||||
return (CycleDataType *)PipelineCyclerBase::write_stage(n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::cheat (dummy or true)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
cheat() const {
|
||||
return (CycleDataType *)PipelineCyclerBase::cheat();
|
||||
}
|
||||
|
||||
#else // !DO_PIPELINING
|
||||
// The following implementations are provided for when pipelining is
|
||||
// not compiled in. They are trivial functions that do as little as
|
||||
// possible.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE PipelineCycler<CycleDataType>::
|
||||
PipelineCycler(Pipeline *pipeline) :
|
||||
PipelineCyclerBase(&_typed_data, pipeline)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Copy Constructor (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE PipelineCycler<CycleDataType>::
|
||||
PipelineCycler(const PipelineCycler<CycleDataType> ©) :
|
||||
PipelineCyclerBase(&_typed_data),
|
||||
_typed_data(copy._typed_data)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::Copy Assignment (trivial)
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE void PipelineCycler<CycleDataType>::
|
||||
operator = (const PipelineCycler<CycleDataType> ©) {
|
||||
_typed_data = copy._typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::read (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE const CycleDataType *PipelineCycler<CycleDataType>::
|
||||
read() const {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
write() {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::elevate_read (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::elevate_read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
elevate_read(const CycleDataType *) {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::elevate_read_upstream (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::elevate_read_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
elevate_read_upstream(const CycleDataType *, bool) {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write_upstream (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
write_upstream(bool) {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::write_stage (trivial)
|
||||
// Access: Public
|
||||
// Description: See PipelineCyclerBase::write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
write_stage(int) {
|
||||
return &_typed_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCycler::cheat (trivial)
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataType *PipelineCycler<CycleDataType>::
|
||||
cheat() const {
|
||||
return (CycleDataType *)&_typed_data;
|
||||
}
|
||||
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: pipelineCycler.cxx
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "pipelineCycler.h"
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
// Filename: pipelineCycler.h
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PIPELINECYCLER_H
|
||||
#define PIPELINECYCLER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pipelineCyclerBase.h"
|
||||
#include "cyclerHolder.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCycler
|
||||
// Description : This class maintains different copies of a page of
|
||||
// data between stages of the graphics pipeline (or any
|
||||
// other pipelining context).
|
||||
//
|
||||
// The class object maintains up to n copies of a
|
||||
// CycleData structure, one for each stage of the
|
||||
// pipeline. The head of the pipeline is responsible
|
||||
// for making changes to its copy, which are then cycled
|
||||
// through the pipeline at each frame.
|
||||
//
|
||||
// To access the data, you must first ask for a readable
|
||||
// pointer. In order to make changes to the data, you
|
||||
// must ask for a writable pointer. Both kinds of
|
||||
// pointers should be released when you are done, as a
|
||||
// sanity check. The CycleDataReader and
|
||||
// CycleDataWriter classes transparently handle this.
|
||||
//
|
||||
// If pipelining support is not enabled at compile time
|
||||
// (that is, SUPPORT_PIPELINING is not defined), this
|
||||
// object compiles to a minimum object that presents the
|
||||
// same interface but with minimal runtime overhead.
|
||||
// (Actually, this isn't true yet, but it will be one
|
||||
// day.)
|
||||
//
|
||||
// We define this as a struct instead of a class to
|
||||
// guarantee byte placement within the object, so that
|
||||
// (particularly for the trivial implementation) the
|
||||
// inherited struct's data is likely to be placed by the
|
||||
// compiler at the "this" pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class CycleDataType>
|
||||
struct PipelineCycler : public PipelineCyclerBase {
|
||||
public:
|
||||
INLINE PipelineCycler(Pipeline *pipeline = NULL);
|
||||
INLINE PipelineCycler(const PipelineCycler<CycleDataType> ©);
|
||||
INLINE void operator = (const PipelineCycler<CycleDataType> ©);
|
||||
|
||||
INLINE const CycleDataType *read() const;
|
||||
INLINE const CycleDataType *read_stage(int n) const;
|
||||
INLINE CycleDataType *write();
|
||||
INLINE CycleDataType *elevate_read(const CycleDataType *pointer);
|
||||
INLINE CycleDataType *elevate_read_upstream(const CycleDataType *pointer, bool force_to_0);
|
||||
INLINE CycleDataType *elevate_read_stage(int n, const CycleDataType *pointer);
|
||||
INLINE CycleDataType *write_upstream(bool force_to_0);
|
||||
INLINE CycleDataType *write_stage(int n);
|
||||
|
||||
INLINE CycleDataType *cheat() const;
|
||||
|
||||
#ifndef DO_PIPELINING
|
||||
private:
|
||||
// If we are *not* compiling in support for pipelining, we just
|
||||
// store the CycleData object right here. No pointers needed.
|
||||
CycleDataType _typed_data;
|
||||
#endif // !DO_PIPELINING
|
||||
};
|
||||
|
||||
// These macros are handy for iterating through the set of pipeline
|
||||
// stages. They're particularly useful for updating cache values
|
||||
// upstream of the current stage, or for removing bad pointers from
|
||||
// all stages of the pipeline. In each case, the variable
|
||||
// pipeline_stage is defined within the loop to be the current stage
|
||||
// of the pipeline traversed by the loop.
|
||||
#ifdef DO_PIPELINING
|
||||
|
||||
// Iterates through all of the pipeline stages upstream of the current
|
||||
// stage, but not including the current stage.
|
||||
#define OPEN_ITERATE_UPSTREAM_ONLY(cycler) { \
|
||||
CyclerHolder cholder(cycler); \
|
||||
int pipeline_stage; \
|
||||
for (pipeline_stage = Thread::get_current_pipeline_stage() - 1; \
|
||||
pipeline_stage >= 0; \
|
||||
--pipeline_stage)
|
||||
|
||||
#define CLOSE_ITERATE_UPSTREAM_ONLY(cycler) \
|
||||
}
|
||||
|
||||
// Iterates through all of the pipeline stages upstream of the current
|
||||
// stage, and including the current stage.
|
||||
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler) { \
|
||||
CyclerHolder cholder(cycler); \
|
||||
int pipeline_stage; \
|
||||
for (pipeline_stage = Thread::get_current_pipeline_stage(); \
|
||||
pipeline_stage >= 0; \
|
||||
--pipeline_stage)
|
||||
|
||||
#define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler) \
|
||||
}
|
||||
|
||||
// As above, but without holding the cycler lock during the loop.
|
||||
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) { \
|
||||
int pipeline_stage; \
|
||||
for (pipeline_stage = Thread::get_current_pipeline_stage(); \
|
||||
pipeline_stage >= 0; \
|
||||
--pipeline_stage)
|
||||
|
||||
#define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) \
|
||||
}
|
||||
|
||||
// Iterates through all of the pipeline stages.
|
||||
#define OPEN_ITERATE_ALL_STAGES(cycler) { \
|
||||
int pipeline_stage; \
|
||||
for (pipeline_stage = (cycler).get_num_stages() - 1; \
|
||||
pipeline_stage >= 0; \
|
||||
--pipeline_stage)
|
||||
|
||||
#define CLOSE_ITERATE_ALL_STAGES(cycler) \
|
||||
}
|
||||
|
||||
#else // DO_PIPELINING
|
||||
|
||||
// These are trivial implementations of the above macros, defined when
|
||||
// pipelining is not enabled, that simply operate on stage 0 without
|
||||
// bothering to create a for loop.
|
||||
#define OPEN_ITERATE_UPSTREAM_ONLY(cycler) \
|
||||
if (false) { \
|
||||
const int pipeline_stage = -1;
|
||||
|
||||
#define CLOSE_ITERATE_UPSTREAM_ONLY(cycler) \
|
||||
}
|
||||
|
||||
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler) { \
|
||||
const int pipeline_stage = 0; \
|
||||
|
||||
#define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler) \
|
||||
}
|
||||
|
||||
#define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) { \
|
||||
const int pipeline_stage = 0; \
|
||||
|
||||
#define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) \
|
||||
}
|
||||
|
||||
#define OPEN_ITERATE_ALL_STAGES(cycler) { \
|
||||
const int pipeline_stage = 0; \
|
||||
|
||||
#define CLOSE_ITERATE_ALL_STAGES(cycler) \
|
||||
}
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
#include "pipelineCycler.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// Filename: pipelineCyclerBase.h
|
||||
// Created by: drose (21Feb02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PIPELINECYCLERBASE_H
|
||||
#define PIPELINECYCLERBASE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
|
||||
// With DO_PIPELINING and threads available, we want the true cycler
|
||||
// implementation.
|
||||
#include "pipelineCyclerTrueImpl.h"
|
||||
typedef PipelineCyclerTrueImpl PipelineCyclerBase;
|
||||
|
||||
#else // HAVE_THREADS
|
||||
|
||||
// With DO_PIPELINING but no threads available, we want the dummy,
|
||||
// self-validating cycler implementation.
|
||||
#include "pipelineCyclerDummyImpl.h"
|
||||
typedef PipelineCyclerDummyImpl PipelineCyclerBase;
|
||||
|
||||
#endif // HAVE_THREADS
|
||||
|
||||
#else // DO_PIPELINING
|
||||
|
||||
// Without DO_PIPELINING, we only want the trivial, do-nothing
|
||||
// implementation.
|
||||
#include "pipelineCyclerTrivialImpl.h"
|
||||
typedef PipelineCyclerTrivialImpl PipelineCyclerBase;
|
||||
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,420 @@
|
|||
// Filename: pipelineCyclerDummyImpl.I
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: PipelineCyclerDummyImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerDummyImpl::
|
||||
PipelineCyclerDummyImpl(CycleData *initial_data, Pipeline *pipeline) :
|
||||
_data(initial_data),
|
||||
_pipeline(pipeline),
|
||||
_read_count(0),
|
||||
_write_count(0),
|
||||
_locked(false)
|
||||
{
|
||||
if (_pipeline == (Pipeline *)NULL) {
|
||||
_pipeline = Pipeline::get_render_pipeline();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerDummyImpl::
|
||||
PipelineCyclerDummyImpl(const PipelineCyclerDummyImpl ©) :
|
||||
_data(copy._data->make_copy()),
|
||||
_pipeline(copy._pipeline),
|
||||
_read_count(0),
|
||||
_write_count(0),
|
||||
_locked(false)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
operator = (const PipelineCyclerDummyImpl ©) {
|
||||
nassertv(_read_count == 0 && _write_count == 0);
|
||||
_data = copy._data->make_copy();
|
||||
_pipeline = copy._pipeline;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerDummyImpl::
|
||||
~PipelineCyclerDummyImpl() {
|
||||
nassertv(_read_count == 0 && _write_count == 0 && !_locked);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::lock
|
||||
// Access: Public
|
||||
// Description: Grabs an overall lock on the cycler. Release it with
|
||||
// a call to release(). This lock should be held while
|
||||
// walking the list of stages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
lock() {
|
||||
nassertv(!_locked);
|
||||
_locked = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release
|
||||
// Access: Public
|
||||
// Description: Release the overall lock on the cycler that was
|
||||
// grabbed via lock().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release() {
|
||||
nassertv(_locked);
|
||||
_locked = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::read
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
//
|
||||
// There should be no outstanding write pointers on the
|
||||
// data when this function is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerDummyImpl::
|
||||
read() const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count++;
|
||||
|
||||
// It's not an error to grab a read pointer while someone else holds
|
||||
// a read or a write pointer.
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::increment_read
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
increment_read(const CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_read_count > 0);
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release_read
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release_read(const CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_read_count > 0);
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::write
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagated to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
write() {
|
||||
_write_count++;
|
||||
|
||||
// It's an error to grab a write pointer while someone else holds a
|
||||
// read pointer, because doing so may invalidate the read pointer.
|
||||
nassertr(_read_count == 0, _data);
|
||||
|
||||
// It's not an error to do this while someone else holds a write
|
||||
// pointer, however.
|
||||
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::elevate_read
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
elevate_read(const CycleData *pointer) {
|
||||
release_read(pointer);
|
||||
return write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::elevate_read_upstream
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer, like elevate_read(), but also propagates the
|
||||
// pointer back to upstream stages, like
|
||||
// write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
elevate_read_upstream(const CycleData *pointer, bool force_to_0) {
|
||||
release_read(pointer);
|
||||
return write_upstream(force_to_0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::increment_write
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by write(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
increment_write(CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_write_count > 0);
|
||||
((PipelineCyclerDummyImpl *)this)->_write_count++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release_write
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release_write(CycleData *pointer) {
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_write_count > 0);
|
||||
_write_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_num_stages
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerDummyImpl::
|
||||
get_num_stages() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::read_stage
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the indicated stage of the pipeline. This
|
||||
// pointer should eventually be released by calling
|
||||
// release_read_stage().
|
||||
//
|
||||
// There should be no outstanding write pointers on the
|
||||
// data when this function is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerDummyImpl::
|
||||
read_stage(int n) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertr(n == 0, NULL);
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count++;
|
||||
|
||||
// It's not an error to grab a read pointer while someone else holds
|
||||
// a read or a write pointer.
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release_read_stage
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release_read_stage(int n, const CycleData *pointer) const {
|
||||
// This function isn't truly const, but it doesn't change the data
|
||||
// in any meaningful way, so we pretend it is.
|
||||
nassertv(n == 0);
|
||||
nassertv(pointer == _data);
|
||||
nassertv(_read_count > 0);
|
||||
((PipelineCyclerDummyImpl *)this)->_read_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::write_upstream
|
||||
// Access: Public
|
||||
// Description: This special variant on write() will automatically
|
||||
// propagate changes back to upstream pipeline stages.
|
||||
// If force_to_0 is false, then it propagates back only
|
||||
// as long as the CycleData pointers are equivalent,
|
||||
// guaranteeing that it does not modify upstream data
|
||||
// (other than the modification that will be performed
|
||||
// by the code that returns this pointer). This is
|
||||
// particularly appropriate for minor updates, where it
|
||||
// doesn't matter much if the update is lost, such as
|
||||
// storing a cached value.
|
||||
//
|
||||
// If force_to_0 is dummy, then the CycleData pointer for
|
||||
// the current pipeline stage is propagated all the way
|
||||
// back up to stage 0; after this call, there will be
|
||||
// only one CycleData pointer that is duplicated in all
|
||||
// stages between stage 0 and the current stage. This
|
||||
// may undo some recent changes that were made
|
||||
// independently at pipeline stage 0 (or any other
|
||||
// upstream stage). However, it guarantees that the
|
||||
// change that is to be applied at this pipeline stage
|
||||
// will stick. This is slightly dangerous because of
|
||||
// the risk of losing upstream changes; generally, this
|
||||
// should only be done when you are confident that there
|
||||
// are no upstream changes to be lost (for instance, for
|
||||
// an object that has been recently created).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *PipelineCyclerDummyImpl::
|
||||
write_upstream(bool) {
|
||||
_write_count++;
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::write_stage
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
write_stage(int n) {
|
||||
nassertr(n == 0, (CycleData *)NULL);
|
||||
_write_count++;
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::elevate_read_stage
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
elevate_read_stage(int n, const CycleData *pointer) {
|
||||
nassertr(n == 0, NULL);
|
||||
release_read(pointer);
|
||||
return write();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::release_write_stage
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerDummyImpl::
|
||||
release_write_stage(int n, CycleData *pointer) {
|
||||
nassertv(n == 0 && pointer == _data);
|
||||
nassertv(_write_count > 0);
|
||||
_write_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_parent_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of object that owns this cycler, as
|
||||
// reported by CycleData::get_parent_type().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle PipelineCyclerDummyImpl::
|
||||
get_parent_type() const {
|
||||
return _data->get_parent_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::cheat
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerDummyImpl::
|
||||
cheat() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_read_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerDummyImpl::
|
||||
get_read_count() const {
|
||||
return _read_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_write_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerDummyImpl::
|
||||
get_write_count() const {
|
||||
return _write_count;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: pipelineCyclerDummyImpl.cxx
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "pipelineCyclerDummyImpl.h"
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// Filename: pipelineCyclerDummyImpl.h
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PIPELINECYCLERDUMMYIMPL_H
|
||||
#define PIPELINECYCLERDUMMYIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#if defined(DO_PIPELINING) && !defined(HAVE_THREADS)
|
||||
|
||||
#include "cycleData.h"
|
||||
#include "pipeline.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerDummyImpl
|
||||
// Description : This is a simple, single-threaded-only implementation
|
||||
// of PipelineCyclerBase. It is only compiled when
|
||||
// DO_PIPELINING is defined, but threading is not
|
||||
// available, which is usually the case only in
|
||||
// development mode.
|
||||
//
|
||||
// This implmentation is similar in principle to
|
||||
// PipelineCyclerTrivialImpl, except it does basic
|
||||
// sanity checking to ensure that you use the interface
|
||||
// in a reasonable way consistent with its design (e.g.,
|
||||
// read() is balanced with release_read(), etc.).
|
||||
//
|
||||
// This is defined as a struct instead of a class,
|
||||
// mainly to be consistent with
|
||||
// PipelineCyclerTrivialImpl.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
struct EXPCL_PANDAEXPRESS PipelineCyclerDummyImpl {
|
||||
public:
|
||||
INLINE PipelineCyclerDummyImpl(CycleData *initial_data, Pipeline *pipeline = NULL);
|
||||
INLINE PipelineCyclerDummyImpl(const PipelineCyclerDummyImpl ©);
|
||||
INLINE void operator = (const PipelineCyclerDummyImpl ©);
|
||||
INLINE ~PipelineCyclerDummyImpl();
|
||||
|
||||
INLINE void lock();
|
||||
INLINE void release();
|
||||
|
||||
INLINE const CycleData *read() const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
||||
INLINE CycleData *write();
|
||||
INLINE CycleData *elevate_read(const CycleData *pointer);
|
||||
INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0);
|
||||
INLINE void increment_write(CycleData *pointer) const;
|
||||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE const CycleData *read_stage(int n) const;
|
||||
INLINE void release_read_stage(int n, const CycleData *pointer) const;
|
||||
INLINE CycleData *write_upstream(bool force_to_0);
|
||||
INLINE CycleData *write_stage(int n);
|
||||
INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE TypeHandle get_parent_type() const;
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
||||
private:
|
||||
PT(CycleData) _data;
|
||||
Pipeline *_pipeline;
|
||||
short _read_count, _write_count;
|
||||
short _locked;
|
||||
};
|
||||
|
||||
#include "pipelineCyclerDummyImpl.I"
|
||||
|
||||
#endif // DO_PIPELINING && !HAVE_THREADS
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// Filename: pipelineCyclerLinks.I
|
||||
// Created by: drose (16Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerLinks::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerLinks::
|
||||
PipelineCyclerLinks() {
|
||||
#ifndef NDEBUG
|
||||
_next = NULL;
|
||||
_prev = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerLinks::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerLinks::
|
||||
~PipelineCyclerLinks() {
|
||||
nassertv(_next == NULL && _prev == NULL);
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerLinks::remove_from_list
|
||||
// Access: Private
|
||||
// Description: Removes a PipelineCyclerLinks record from the
|
||||
// doubly-linked list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerLinks::
|
||||
remove_from_list() {
|
||||
nassertv(_prev->_next == this && _next->_prev == this);
|
||||
_prev->_next = _next;
|
||||
_next->_prev = _prev;
|
||||
#ifndef NDEBUG
|
||||
_next = NULL;
|
||||
_prev = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerLinks::insert_before
|
||||
// Access: Private
|
||||
// Description: Adds a PipelineCyclerLinks record before the indicated
|
||||
// node in the doubly-linked list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerLinks::
|
||||
insert_before(PipelineCyclerLinks *node) {
|
||||
nassertv(node->_prev->_next == node && node->_next->_prev == node);
|
||||
nassertv(_prev == (PipelineCyclerLinks *)NULL &&
|
||||
_next == (PipelineCyclerLinks *)NULL);
|
||||
_prev = node->_prev;
|
||||
_next = node;
|
||||
_prev->_next = this;
|
||||
node->_prev = this;
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Filename: pipelineCyclerLinks.h
|
||||
// Created by: drose (16Feb06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PIPELINECYCLERLINKS_H
|
||||
#define PIPELINECYCLERLINKS_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h" // for THREADED_PIPELINE definition
|
||||
#include "notify.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerLinks
|
||||
// Description : This just stores the pointers to implement a
|
||||
// doubly-linked list of PipelineCyclers for a
|
||||
// particular Pipeline object. We use a hand-rolled
|
||||
// linked list rather than any STL container, because we
|
||||
// want PipelineCyclers to be able to add and remove
|
||||
// themselves from this list very quickly.
|
||||
//
|
||||
// These pointers are inherited from this separate class
|
||||
// so the Pipeline object itself can be the root of the
|
||||
// linked list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS PipelineCyclerLinks {
|
||||
protected:
|
||||
#ifdef THREADED_PIPELINE
|
||||
INLINE PipelineCyclerLinks();
|
||||
INLINE ~PipelineCyclerLinks();
|
||||
|
||||
INLINE void remove_from_list();
|
||||
INLINE void insert_before(PipelineCyclerLinks *node);
|
||||
|
||||
PipelineCyclerLinks *_prev, *_next;
|
||||
#endif
|
||||
friend class Pipeline;
|
||||
};
|
||||
|
||||
#include "pipelineCyclerLinks.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
// Filename: pipelineCyclerTrivialImpl.I
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: PipelineCyclerTrivialImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerTrivialImpl::
|
||||
PipelineCyclerTrivialImpl(CycleData *initial_data, Pipeline *) {
|
||||
// In the trivial implementation, a derived class (the
|
||||
// PipelineCycler template class) stores the CycleData object
|
||||
// directly within itself, and since we have no data members or
|
||||
// virtual functions, we get away with assuming the pointer is the
|
||||
// same as the 'this' pointer.
|
||||
|
||||
// If this turns out not to be true on a particular platform, we
|
||||
// will have to store the pointer in this class, for a little bit of
|
||||
// extra overhead.
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
nassertv(initial_data == (CycleData *)this);
|
||||
#else
|
||||
_data = initial_data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::Copy Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerTrivialImpl::
|
||||
PipelineCyclerTrivialImpl(const PipelineCyclerTrivialImpl &) {
|
||||
// The copy constructor for the PipelineCyclerTrivialImpl case
|
||||
// doesn't work. Don't try to use it. The PipelineCycler template
|
||||
// class is #ifdeffed appropriately to call the normal constructor
|
||||
// instead.
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::Copy Assignment
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
operator = (const PipelineCyclerTrivialImpl &) {
|
||||
// The copy assignment operator for the PipelineCyclerTrivialImpl
|
||||
// case doesn't work. Don't try to use it. The PipelineCycler
|
||||
// template class is #ifdeffed appropriately not to call this
|
||||
// method.
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerTrivialImpl::
|
||||
~PipelineCyclerTrivialImpl() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::lock
|
||||
// Access: Public
|
||||
// Description: Grabs an overall lock on the cycler. Release it with
|
||||
// a call to release(). This lock should be held while
|
||||
// walking the list of stages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
lock() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release
|
||||
// Access: Public
|
||||
// Description: Release the overall lock on the cycler that was
|
||||
// grabbed via lock().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::read
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrivialImpl::
|
||||
read() const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (const CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::increment_read
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
increment_read(const CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release_read
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release_read(const CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::write
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagated to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
write() {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::elevate_read
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
elevate_read(const CycleData *) {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::elevate_read_upstream
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer, like elevate_read(), but also propagates the
|
||||
// pointer back to upstream stages, like
|
||||
// write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
elevate_read_upstream(const CycleData *, bool) {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::increment_write
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by write(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
increment_write(CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release_write
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release_write(CycleData *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_num_stages
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrivialImpl::
|
||||
get_num_stages() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::read_stage
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the indicated pipeline stage. This pointer
|
||||
// should eventually be released by calling
|
||||
// release_read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrivialImpl::
|
||||
read_stage(int) const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (const CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release_read_stage
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release_read_stage(int, const CycleData *) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::write_upstream
|
||||
// Access: Public
|
||||
// Description: This special variant on write() will automatically
|
||||
// propagate changes back to upstream pipeline stages.
|
||||
// If force_to_0 is false, then it propagates back only
|
||||
// as long as the CycleData pointers are equivalent,
|
||||
// guaranteeing that it does not modify upstream data
|
||||
// (other than the modification that will be performed
|
||||
// by the code that returns this pointer). This is
|
||||
// particularly appropriate for minor updates, where it
|
||||
// doesn't matter much if the update is lost, such as
|
||||
// storing a cached value.
|
||||
//
|
||||
// If force_to_0 is trivial, then the CycleData pointer for
|
||||
// the current pipeline stage is propagated all the way
|
||||
// back up to stage 0; after this call, there will be
|
||||
// only one CycleData pointer that is duplicated in all
|
||||
// stages between stage 0 and the current stage. This
|
||||
// may undo some recent changes that were made
|
||||
// independently at pipeline stage 0 (or any other
|
||||
// upstream stage). However, it guarantees that the
|
||||
// change that is to be applied at this pipeline stage
|
||||
// will stick. This is slightly dangerous because of
|
||||
// the risk of losing upstream changes; generally, this
|
||||
// should only be done when you are confident that there
|
||||
// are no upstream changes to be lost (for instance, for
|
||||
// an object that has been recently created).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *PipelineCyclerTrivialImpl::
|
||||
write_upstream(bool) {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::write_stage
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
write_stage(int) {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::elevate_read_stage
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
elevate_read_stage(int, const CycleData *) {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::release_write_stage
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrivialImpl::
|
||||
release_write_stage(int, CycleData *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_parent_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of object that owns this cycler, as
|
||||
// reported by CycleData::get_parent_type().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle PipelineCyclerTrivialImpl::
|
||||
get_parent_type() const {
|
||||
return cheat()->get_parent_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::cheat
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrivialImpl::
|
||||
cheat() const {
|
||||
#ifdef SIMPLE_STRUCT_POINTERS
|
||||
return (CycleData *)this;
|
||||
#else
|
||||
return _data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_read_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrivialImpl::
|
||||
get_read_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_write_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrivialImpl::
|
||||
get_write_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Filename: pipelineCyclerTrivialImpl.cxx
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "pipelineCyclerTrivialImpl.h"
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
// Filename: pipelineCyclerTrivialImpl.h
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PIPELINECYCLERTRIVIALIMPL_H
|
||||
#define PIPELINECYCLERTRIVIALIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifndef DO_PIPELINING
|
||||
|
||||
#include "cycleData.h"
|
||||
|
||||
class Pipeline;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerTrivialImpl
|
||||
// Description : This is the trivial, non-threaded implementation of
|
||||
// PipelineCyclerBase. It is only compiled when
|
||||
// DO_PIPELINING is not defined (which usually implies
|
||||
// that threading is not available).
|
||||
//
|
||||
// This implementation is designed to do as little as
|
||||
// possible, and to compile to nothing, or almost
|
||||
// nothing. It doesn't actually support pipelining in
|
||||
// any way. It doesn't even perform any sanity checks
|
||||
// to speak of. It's designed for a strictly
|
||||
// single-threaded application, and its purpose is to be
|
||||
// as low-overhead as possible.
|
||||
//
|
||||
// We define this as a struct instead of a class to
|
||||
// emphasize the importance of byte placement within the
|
||||
// object, so that the inherited struct's data is likely
|
||||
// to be placed by the compiler at the "this" pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
struct EXPCL_PANDAEXPRESS PipelineCyclerTrivialImpl {
|
||||
public:
|
||||
INLINE PipelineCyclerTrivialImpl(CycleData *initial_data, Pipeline *pipeline = NULL);
|
||||
private:
|
||||
INLINE PipelineCyclerTrivialImpl(const PipelineCyclerTrivialImpl ©);
|
||||
INLINE void operator = (const PipelineCyclerTrivialImpl ©);
|
||||
public:
|
||||
INLINE ~PipelineCyclerTrivialImpl();
|
||||
|
||||
INLINE void lock();
|
||||
INLINE void release();
|
||||
|
||||
INLINE const CycleData *read() const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
||||
INLINE CycleData *write();
|
||||
INLINE CycleData *elevate_read(const CycleData *pointer);
|
||||
INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0);
|
||||
INLINE void increment_write(CycleData *pointer) const;
|
||||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE const CycleData *read_stage(int n) const;
|
||||
INLINE void release_read_stage(int n, const CycleData *pointer) const;
|
||||
INLINE CycleData *write_upstream(bool force_to_0);
|
||||
INLINE CycleData *write_stage(int n);
|
||||
INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE TypeHandle get_parent_type() const;
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
||||
// In a trivial implementation, we only need to store the CycleData
|
||||
// pointer. Actually, we don't even need to do that, if we're lucky
|
||||
// and the compiler doesn't do anything funny with the struct
|
||||
// layout.
|
||||
#ifndef SIMPLE_STRUCT_POINTERS
|
||||
CycleData *_data;
|
||||
#endif // SIMPLE_STRUCT_POINTERS
|
||||
};
|
||||
|
||||
#include "pipelineCyclerTrivialImpl.I"
|
||||
|
||||
#endif // !DO_PIPELINING
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,381 @@
|
|||
// Filename: pipelineCyclerTrueImpl.I
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: PipelineCyclerTrueImpl::lock
|
||||
// Access: Public
|
||||
// Description: Grabs an overall lock on the cycler. Release it with
|
||||
// a call to release(). This lock should be held while
|
||||
// walking the list of stages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
lock() {
|
||||
_lock.lock();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release
|
||||
// Access: Public
|
||||
// Description: Release the overall lock on the cycler that was
|
||||
// grabbed via lock().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release() {
|
||||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::read
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the current stage of the pipeline as seen by
|
||||
// this thread. This pointer should eventually be
|
||||
// released by calling release_read().
|
||||
//
|
||||
// There should be no outstanding write pointers on the
|
||||
// data when this function is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrueImpl::
|
||||
read() const {
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
_lock.lock();
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::increment_read
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by read(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
increment_read(const CycleData *pointer) const {
|
||||
#ifndef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
||||
nassertv(_data[pipeline_stage] == pointer);
|
||||
#endif
|
||||
_lock.lock();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release_read
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_read(const CycleData *pointer) const {
|
||||
#ifndef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
||||
nassertv(_data[pipeline_stage] == pointer);
|
||||
#endif
|
||||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::write
|
||||
// Access: Public
|
||||
// Description: Returns a non-const CycleData pointer, filled with a
|
||||
// unique copy of the data for the current stage of the
|
||||
// pipeline as seen by this thread. This pointer may
|
||||
// now be used to write to the data, and that copy of
|
||||
// the data will be propagated to all later stages of the
|
||||
// pipeline. This pointer should eventually be released
|
||||
// by calling release_write().
|
||||
//
|
||||
// There may only be one outstanding write pointer on a
|
||||
// given stage at a time, and if there is a write
|
||||
// pointer there may be no read pointers on the same
|
||||
// stage (but see elevate_read).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
write() {
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
return write_stage(pipeline_stage);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::elevate_read
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// current stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
elevate_read(const CycleData *pointer) {
|
||||
#ifndef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
nassertr(_data[pipeline_stage] == pointer, NULL);
|
||||
#endif
|
||||
CycleData *new_pointer = write();
|
||||
_lock.release();
|
||||
return new_pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::elevate_read_upstream
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer, like elevate_read(), but also propagates the
|
||||
// pointer back to upstream stages, like
|
||||
// write_upstream().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
elevate_read_upstream(const CycleData *pointer, bool force_to_0) {
|
||||
#ifndef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
nassertr(_data[pipeline_stage] == pointer, NULL);
|
||||
#endif
|
||||
CycleData *new_pointer = write_upstream(force_to_0);
|
||||
_lock.release();
|
||||
return new_pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::increment_write
|
||||
// Access: Public
|
||||
// Description: Increments the count on a pointer previously
|
||||
// retrieved by write(); now the pointer will need to be
|
||||
// released twice.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
increment_write(CycleData *pointer) const {
|
||||
#ifndef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
||||
nassertv(_data[pipeline_stage] == pointer);
|
||||
#endif
|
||||
_lock.lock();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release_write
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_write(CycleData *pointer) {
|
||||
#ifdef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
return release_write_stage(pipeline_stage, pointer);
|
||||
#else
|
||||
_lock.release();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_num_stages
|
||||
// Access: Public
|
||||
// Description: Returns the number of stages in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_num_stages() {
|
||||
return _num_stages;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::read_stage
|
||||
// Access: Public
|
||||
// Description: Returns a const CycleData pointer, filled with the
|
||||
// data for the indicated stage of the pipeline. This
|
||||
// pointer should eventually be released by calling
|
||||
// release_read_stage().
|
||||
//
|
||||
// There should be no outstanding write pointers on the
|
||||
// data when this function is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const CycleData *PipelineCyclerTrueImpl::
|
||||
read_stage(int n) const {
|
||||
nassertr(n >= 0 && n < _num_stages, NULL);
|
||||
_lock.lock();
|
||||
return _data[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release_read_stage
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// read_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_read_stage(int n, const CycleData *pointer) const {
|
||||
#ifndef NDEBUG
|
||||
nassertv(n >= 0 && n < _num_stages);
|
||||
nassertv(_data[n] == pointer);
|
||||
#endif
|
||||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::elevate_read_stage
|
||||
// Access: Public
|
||||
// Description: Elevates a currently-held read pointer into a write
|
||||
// pointer. This may or may not change the value of the
|
||||
// pointer. It is only valid to do this if this is the
|
||||
// only currently-outstanding read pointer on the
|
||||
// indicated stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
elevate_read_stage(int n, const CycleData *pointer) {
|
||||
#ifndef NDEBUG
|
||||
nassertr(n >= 0 && n < _num_stages, NULL);
|
||||
nassertr(_data[n] == pointer, NULL);
|
||||
#endif
|
||||
CycleData *new_pointer = write_stage(n);
|
||||
_lock.release();
|
||||
return new_pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::release_write_stage
|
||||
// Access: Public
|
||||
// Description: Releases a pointer previously obtained via a call to
|
||||
// write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_write_stage(int n, CycleData *pointer) {
|
||||
#ifndef NDEBUG
|
||||
nassertv(n >= 0 && n < _num_stages);
|
||||
nassertv(_data[n] == pointer);
|
||||
#endif
|
||||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_parent_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of object that owns this cycler, as
|
||||
// reported by CycleData::get_parent_type().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle PipelineCyclerTrueImpl::
|
||||
get_parent_type() const {
|
||||
return _data[0]->get_parent_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cheat
|
||||
// Access: Public
|
||||
// Description: Returns a pointer without counting it. This is only
|
||||
// intended for use as the return value for certain
|
||||
// nassertr() functions, so the application can recover
|
||||
// after a failure to manage the read and write pointers
|
||||
// correctly. You should never call this function
|
||||
// directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
cheat() const {
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_read_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This should
|
||||
// only be used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_read_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_write_count
|
||||
// Access: Public
|
||||
// Description: Returns the number of handles currently outstanding
|
||||
// to read the current stage of the data. This will
|
||||
// normally only be either 0 or 1. This should only be
|
||||
// used for debugging purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_write_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cycle_2
|
||||
// Access: Private
|
||||
// Description: This is a special implementation of cycle() for the
|
||||
// special case of just two stages to the pipeline. It
|
||||
// does the same thing as cycle(), but is a little bit
|
||||
// faster because it knows there are exactly two stages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PT(CycleData) PipelineCyclerTrueImpl::
|
||||
cycle_2() {
|
||||
PT(CycleData) last_val = _data[1];
|
||||
nassertr(_lock.debug_is_locked(), last_val);
|
||||
nassertr(_dirty, last_val);
|
||||
nassertr(_num_stages == 2, last_val);
|
||||
|
||||
_data[1] = _data[0];
|
||||
|
||||
// No longer dirty.
|
||||
_dirty = false;
|
||||
return last_val;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cycle_3
|
||||
// Access: Private
|
||||
// Description: This is a special implementation of cycle() for the
|
||||
// special case of exactly three stages to the pipeline.
|
||||
// It does the same thing as cycle(), but is a little
|
||||
// bit faster because it knows there are exactly three
|
||||
// stages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PT(CycleData) PipelineCyclerTrueImpl::
|
||||
cycle_3() {
|
||||
PT(CycleData) last_val = _data[2];
|
||||
nassertr(_lock.debug_is_locked(), last_val);
|
||||
nassertr(_dirty, last_val);
|
||||
nassertr(_num_stages == 3, last_val);
|
||||
|
||||
_data[2] = _data[1];
|
||||
_data[1] = _data[0];
|
||||
|
||||
if (_data[2] == _data[1]) {
|
||||
// No longer dirty.
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
return last_val;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::CyclerMutex::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PipelineCyclerTrueImpl::CyclerMutex::
|
||||
CyclerMutex(PipelineCyclerTrueImpl *cycler) {
|
||||
#ifdef DEBUG_THREADS
|
||||
_cycler = cycler;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,350 @@
|
|||
// Filename: pipelineCyclerTrueImpl.cxx
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "pipelineCyclerTrueImpl.h"
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
|
||||
#include "config_express.h"
|
||||
#include "pipeline.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PipelineCyclerTrueImpl::
|
||||
PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
||||
_pipeline(pipeline),
|
||||
_dirty(false),
|
||||
_lock(this)
|
||||
{
|
||||
if (_pipeline == (Pipeline *)NULL) {
|
||||
_pipeline = Pipeline::get_render_pipeline();
|
||||
}
|
||||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
_data = new PT(CycleData)[_num_stages];
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i] = initial_data;
|
||||
}
|
||||
|
||||
_pipeline->add_cycler(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PipelineCyclerTrueImpl::
|
||||
PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
||||
_pipeline(copy._pipeline),
|
||||
_dirty(false),
|
||||
_lock(this)
|
||||
{
|
||||
ReMutexHolder holder(_lock);
|
||||
ReMutexHolder holder2(copy._lock);
|
||||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
_data = new PT(CycleData)[_num_stages];
|
||||
|
||||
// It's no longer critically important that we preserve pointerwise
|
||||
// equivalence between different stages in the copy, but it doesn't
|
||||
// cost much and might be a little more efficient, so we do it
|
||||
// anyway.
|
||||
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
||||
Pointers pointers;
|
||||
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
PT(CycleData) &new_pt = pointers[copy._data[i]];
|
||||
if (new_pt == NULL) {
|
||||
new_pt = copy._data[i]->make_copy();
|
||||
}
|
||||
_data[i] = new_pt;
|
||||
}
|
||||
|
||||
_pipeline->add_cycler(this);
|
||||
if (copy._dirty) {
|
||||
_pipeline->add_dirty_cycler(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
operator = (const PipelineCyclerTrueImpl ©) {
|
||||
ReMutexHolder holder1(_lock);
|
||||
ReMutexHolder holder2(copy._lock);
|
||||
nassertv(get_parent_type() == copy.get_parent_type());
|
||||
|
||||
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
||||
Pointers pointers;
|
||||
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
PT(CycleData) &new_pt = pointers[copy._data[i]];
|
||||
if (new_pt == NULL) {
|
||||
new_pt = copy._data[i]->make_copy();
|
||||
}
|
||||
_data[i] = new_pt;
|
||||
}
|
||||
|
||||
if (copy._dirty && !_dirty) {
|
||||
_pipeline->add_dirty_cycler(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PipelineCyclerTrueImpl::
|
||||
~PipelineCyclerTrueImpl() {
|
||||
ReMutexHolder holder(_lock);
|
||||
|
||||
_pipeline->remove_cycler(this);
|
||||
|
||||
delete[] _data;
|
||||
_data = NULL;
|
||||
_num_stages = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::write_upstream
|
||||
// Access: Public
|
||||
// Description: This special variant on write() will automatically
|
||||
// propagate changes back to upstream pipeline stages.
|
||||
// If force_to_0 is false, then it propagates back only
|
||||
// as long as the CycleData pointers are equivalent,
|
||||
// guaranteeing that it does not modify upstream data
|
||||
// (other than the modification that will be performed
|
||||
// by the code that returns this pointer). This is
|
||||
// particularly appropriate for minor updates, where it
|
||||
// doesn't matter much if the update is lost, such as
|
||||
// storing a cached value.
|
||||
//
|
||||
// If force_to_0 is true, then the CycleData pointer for
|
||||
// the current pipeline stage is propagated all the way
|
||||
// back up to stage 0; after this call, there will be
|
||||
// only one CycleData pointer that is duplicated in all
|
||||
// stages between stage 0 and the current stage. This
|
||||
// may undo some recent changes that were made
|
||||
// independently at pipeline stage 0 (or any other
|
||||
// upstream stage). However, it guarantees that the
|
||||
// change that is to be applied at this pipeline stage
|
||||
// will stick. This is slightly dangerous because of
|
||||
// the risk of losing upstream changes; generally, this
|
||||
// should only be done when you are confident that there
|
||||
// are no upstream changes to be lost (for instance, for
|
||||
// an object that has been recently created).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *PipelineCyclerTrueImpl::
|
||||
write_upstream(bool force_to_0) {
|
||||
_lock.lock();
|
||||
|
||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||
|
||||
#ifndef NDEBUG
|
||||
nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
|
||||
_lock.release();
|
||||
return NULL;
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
CycleData *old_data = _data[pipeline_stage];
|
||||
|
||||
if (old_data->get_ref_count() != 1 || force_to_0) {
|
||||
// Count the number of references before the current stage, and
|
||||
// the number of references remaining other than those.
|
||||
int external_count = old_data->get_ref_count() - 1;
|
||||
int k = pipeline_stage - 1;
|
||||
while (k >= 0 && _data[k] == old_data) {
|
||||
--k;
|
||||
--external_count;
|
||||
}
|
||||
|
||||
if (external_count > 0) {
|
||||
// There are references other than the ones before this stage in
|
||||
// the pipeline; perform a copy-on-write.
|
||||
PT(CycleData) new_data = old_data->make_copy();
|
||||
|
||||
k = pipeline_stage - 1;
|
||||
while (k >= 0 && (_data[k] == old_data || force_to_0)) {
|
||||
_data[k] = new_data;
|
||||
--k;
|
||||
}
|
||||
|
||||
_data[pipeline_stage] = new_data;
|
||||
|
||||
if (k >= 0 || pipeline_stage + 1 < _num_stages) {
|
||||
// Now we have differences between some of the data pointers,
|
||||
// which makes us "dirty".
|
||||
if (!_dirty) {
|
||||
_pipeline->add_dirty_cycler(this);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (k >= 0 && force_to_0) {
|
||||
// There are no external pointers, so no need to copy-on-write,
|
||||
// but the current pointer doesn't go all the way back. Make it
|
||||
// do so.
|
||||
while (k >= 0) {
|
||||
_data[k] = old_data;
|
||||
--k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::write_stage
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *PipelineCyclerTrueImpl::
|
||||
write_stage(int pipeline_stage) {
|
||||
_lock.lock();
|
||||
|
||||
#ifndef NDEBUG
|
||||
nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
|
||||
_lock.release();
|
||||
return NULL;
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
CycleData *old_data = _data[pipeline_stage];
|
||||
|
||||
if (old_data->get_ref_count() != 1) {
|
||||
// Copy-on-write.
|
||||
_data[pipeline_stage] = old_data->make_copy();
|
||||
|
||||
// Now we have differences between some of the data pointers, so
|
||||
// we're "dirty". Mark it so.
|
||||
if (!_dirty) {
|
||||
_pipeline->add_dirty_cycler(this);
|
||||
}
|
||||
}
|
||||
|
||||
return _data[pipeline_stage];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cycle
|
||||
// Access: Private
|
||||
// Description: Cycles the data between frames. This is only called
|
||||
// from Pipeline::cycle(), and presumably it is only
|
||||
// called if the cycler is "dirty".
|
||||
//
|
||||
// At the conclusion of this method, the cycler should
|
||||
// clear its dirty flag if it is no longer "dirty"--that
|
||||
// is, if all of the pipeline pointers are the same.
|
||||
//
|
||||
// The return value is the CycleData pointer which fell
|
||||
// off the end of the cycle. If this is allowed to
|
||||
// destruct immediately, there may be side-effects that
|
||||
// cascade through the system, so the caller may choose
|
||||
// to hold the pointer until it can safely be released
|
||||
// later.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(CycleData) PipelineCyclerTrueImpl::
|
||||
cycle() {
|
||||
PT(CycleData) last_val = _data[_num_stages - 1];
|
||||
nassertr(_lock.debug_is_locked(), last_val);
|
||||
nassertr(_dirty, last_val);
|
||||
|
||||
int i;
|
||||
for (i = _num_stages - 1; i > 0; --i) {
|
||||
_data[i] = _data[i - 1];
|
||||
}
|
||||
|
||||
for (i = 1; i < _num_stages; ++i) {
|
||||
if (_data[i] != _data[i - 1]) {
|
||||
// Still dirty.
|
||||
return last_val;
|
||||
}
|
||||
}
|
||||
|
||||
// No longer dirty.
|
||||
_dirty = false;
|
||||
return last_val;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::set_num_stages
|
||||
// Access: Private
|
||||
// Description: Changes the number of stages in the cycler. This is
|
||||
// only called from Pipeline::set_num_stages();
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
set_num_stages(int num_stages) {
|
||||
nassertv(_lock.debug_is_locked());
|
||||
|
||||
if (num_stages <= _num_stages) {
|
||||
// Don't bother to reallocate the array smaller; we just won't use
|
||||
// the rest of the array.
|
||||
for (int i = _num_stages; i < num_stages; ++i) {
|
||||
_data[i].clear();
|
||||
}
|
||||
|
||||
_num_stages = num_stages;
|
||||
|
||||
|
||||
} else {
|
||||
// To increase the array, we must reallocate it larger.
|
||||
PT(CycleData) *new_data = new PT(CycleData)[num_stages];
|
||||
int i;
|
||||
for (i = 0; i < _num_stages; ++i) {
|
||||
new_data[i] = _data[i];
|
||||
}
|
||||
for (i = _num_stages; i < num_stages; ++i) {
|
||||
new_data[i] = _data[_num_stages - 1];
|
||||
}
|
||||
delete[] _data;
|
||||
|
||||
_num_stages = num_stages;
|
||||
_data = new_data;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::CyclerMutex::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::CyclerMutex::
|
||||
output(ostream &out) const {
|
||||
_cycler->cheat()->output(out);
|
||||
}
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
// Filename: pipelineCyclerTrueImpl.h
|
||||
// Created by: drose (31Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 PIPELINECYCLERTRUEIMPL_H
|
||||
#define PIPELINECYCLERTRUEIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
|
||||
#include "pipelineCyclerLinks.h"
|
||||
#include "cycleData.h"
|
||||
#include "pointerTo.h"
|
||||
#include "thread.h"
|
||||
#include "reMutex.h"
|
||||
#include "reMutexHolder.h"
|
||||
|
||||
class Pipeline;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PipelineCyclerTrueImpl
|
||||
// Description : This is the true, threaded implementation of
|
||||
// PipelineCyclerBase. It is only compiled when
|
||||
// threading is available and DO_PIPELINING is defined.
|
||||
//
|
||||
// This implementation is designed to do the actual work
|
||||
// of cycling the data through a pipeline, and returning
|
||||
// the actual CycleData appropriate to the current
|
||||
// thread's pipeline stage.
|
||||
//
|
||||
// This is defined as a struct instead of a class,
|
||||
// mainly to be consistent with
|
||||
// PipelineCyclerTrivialImpl.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
struct EXPCL_PANDAEXPRESS PipelineCyclerTrueImpl : public PipelineCyclerLinks {
|
||||
private:
|
||||
PipelineCyclerTrueImpl();
|
||||
public:
|
||||
PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline = NULL);
|
||||
PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©);
|
||||
void operator = (const PipelineCyclerTrueImpl ©);
|
||||
~PipelineCyclerTrueImpl();
|
||||
|
||||
INLINE void lock();
|
||||
INLINE void release();
|
||||
|
||||
INLINE const CycleData *read() const;
|
||||
INLINE void increment_read(const CycleData *pointer) const;
|
||||
INLINE void release_read(const CycleData *pointer) const;
|
||||
|
||||
INLINE CycleData *write();
|
||||
INLINE CycleData *elevate_read(const CycleData *pointer);
|
||||
INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0);
|
||||
INLINE void increment_write(CycleData *pointer) const;
|
||||
INLINE void release_write(CycleData *pointer);
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE const CycleData *read_stage(int n) const;
|
||||
INLINE void release_read_stage(int n, const CycleData *pointer) const;
|
||||
CycleData *write_upstream(bool force_to_0);
|
||||
CycleData *write_stage(int pipeline_stage);
|
||||
INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE TypeHandle get_parent_type() const;
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
||||
public:
|
||||
// We redefine the ReMutex class, solely so we can define the
|
||||
// output() operator. This is only useful for debugging, but does
|
||||
// no harm in the production case.
|
||||
class CyclerMutex : public ReMutex {
|
||||
public:
|
||||
INLINE CyclerMutex(PipelineCyclerTrueImpl *cycler);
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
virtual void output(ostream &out) const;
|
||||
PipelineCyclerTrueImpl *_cycler;
|
||||
#endif // DEBUG_THREADS
|
||||
};
|
||||
|
||||
private:
|
||||
PT(CycleData) cycle();
|
||||
INLINE PT(CycleData) cycle_2();
|
||||
INLINE PT(CycleData) cycle_3();
|
||||
void set_num_stages(int num_stages);
|
||||
|
||||
private:
|
||||
Pipeline *_pipeline;
|
||||
|
||||
// An array of PT(CycleData) objects.
|
||||
PT(CycleData) *_data;
|
||||
int _num_stages;
|
||||
bool _dirty;
|
||||
|
||||
CyclerMutex _lock;
|
||||
|
||||
friend class Pipeline;
|
||||
};
|
||||
|
||||
#include "pipelineCyclerTrueImpl.I"
|
||||
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue