mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 15:53:55 -04:00
pipeline: Avoid dynamic allocation in PipelineCycler when using 1 stage
Eliminates a level of indirection at cost of 8 bytes per cycler
This commit is contained in:
parent
9bd66baa1c
commit
f02a3156ca
@ -157,7 +157,7 @@ cycle() {
|
|||||||
saved_cdatas.push_back(cycler->cycle_2());
|
saved_cdatas.push_back(cycler->cycle_2());
|
||||||
|
|
||||||
// cycle_2() won't leave a cycler dirty. Add it to the clean list.
|
// cycle_2() won't leave a cycler dirty. Add it to the clean list.
|
||||||
nassertd(!cycler->_dirty) break;
|
nassertd(!cycler->is_dirty()) break;
|
||||||
cycler->insert_before(&_clean);
|
cycler->insert_before(&_clean);
|
||||||
#ifdef DEBUG_THREADS
|
#ifdef DEBUG_THREADS
|
||||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||||
@ -193,11 +193,11 @@ cycle() {
|
|||||||
|
|
||||||
saved_cdatas.push_back(cycler->cycle_3());
|
saved_cdatas.push_back(cycler->cycle_3());
|
||||||
|
|
||||||
if (cycler->_dirty) {
|
if (cycler->is_dirty()) {
|
||||||
// The cycler is still dirty. Add it back to the dirty list.
|
// The cycler is still dirty. Add it back to the dirty list.
|
||||||
nassertd(cycler->_dirty == prev_seq) break;
|
nassertd(!cycler->is_dirty(prev_seq));
|
||||||
cycler->insert_before(&_dirty);
|
cycler->insert_before(&_dirty);
|
||||||
cycler->_dirty = next_seq;
|
cycler->mark_dirty(next_seq);
|
||||||
++_num_dirty_cyclers;
|
++_num_dirty_cyclers;
|
||||||
} else {
|
} else {
|
||||||
// The cycler is now clean. Add it back to the clean list.
|
// The cycler is now clean. Add it back to the clean list.
|
||||||
@ -237,11 +237,11 @@ cycle() {
|
|||||||
|
|
||||||
saved_cdatas.push_back(cycler->cycle());
|
saved_cdatas.push_back(cycler->cycle());
|
||||||
|
|
||||||
if (cycler->_dirty) {
|
if (cycler->is_dirty()) {
|
||||||
// The cycler is still dirty. Add it back to the dirty list.
|
// The cycler is still dirty. Add it back to the dirty list.
|
||||||
nassertd(cycler->_dirty == prev_seq) break;
|
nassertd(!cycler->is_dirty(prev_seq)) break;
|
||||||
cycler->insert_before(&_dirty);
|
cycler->insert_before(&_dirty);
|
||||||
cycler->_dirty = next_seq;
|
cycler->mark_dirty(next_seq);
|
||||||
++_num_dirty_cyclers;
|
++_num_dirty_cyclers;
|
||||||
} else {
|
} else {
|
||||||
// The cycler is now clean. Add it back to the clean list.
|
// The cycler is now clean. Add it back to the clean list.
|
||||||
@ -346,7 +346,7 @@ add_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||||||
// It's safe to add it to the list while cycling, since the _clean list is
|
// It's safe to add it to the list while cycling, since the _clean list is
|
||||||
// not touched during the cycle loop.
|
// not touched during the cycle loop.
|
||||||
MutexHolder holder(_lock);
|
MutexHolder holder(_lock);
|
||||||
nassertv(!cycler->_dirty);
|
nassertv(!cycler->is_dirty());
|
||||||
|
|
||||||
cycler->insert_before(&_clean);
|
cycler->insert_before(&_clean);
|
||||||
++_num_cyclers;
|
++_num_cyclers;
|
||||||
@ -370,7 +370,7 @@ add_cycler(PipelineCyclerTrueImpl *cycler, bool dirty) {
|
|||||||
// It's safe to add it to the list while cycling, since the _clean list is
|
// It's safe to add it to the list while cycling, since the _clean list is
|
||||||
// not touched during the cycle loop.
|
// not touched during the cycle loop.
|
||||||
MutexHolder holder(_lock);
|
MutexHolder holder(_lock);
|
||||||
nassertv(!cycler->_dirty);
|
nassertv(!cycler->is_dirty());
|
||||||
|
|
||||||
if (!dirty) {
|
if (!dirty) {
|
||||||
cycler->insert_before(&_clean);
|
cycler->insert_before(&_clean);
|
||||||
@ -378,7 +378,7 @@ add_cycler(PipelineCyclerTrueImpl *cycler, bool dirty) {
|
|||||||
else {
|
else {
|
||||||
nassertv(_num_stages != 1);
|
nassertv(_num_stages != 1);
|
||||||
cycler->insert_before(&_dirty);
|
cycler->insert_before(&_dirty);
|
||||||
cycler->_dirty = _next_cycle_seq;
|
cycler->mark_dirty(_next_cycle_seq);
|
||||||
++_num_dirty_cyclers;
|
++_num_dirty_cyclers;
|
||||||
|
|
||||||
#ifdef DEBUG_THREADS
|
#ifdef DEBUG_THREADS
|
||||||
@ -407,13 +407,13 @@ add_dirty_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||||||
// It's safe to add it to the list while cycling, since it's not currently
|
// It's safe to add it to the list while cycling, since it's not currently
|
||||||
// on the dirty list.
|
// on the dirty list.
|
||||||
MutexHolder holder(_lock);
|
MutexHolder holder(_lock);
|
||||||
nassertv(!cycler->_dirty);
|
nassertv(!cycler->is_dirty());
|
||||||
nassertv(_num_stages != 1);
|
nassertv(_num_stages != 1);
|
||||||
|
|
||||||
// Remove it from the "clean" list and add it to the "dirty" list.
|
// Remove it from the "clean" list and add it to the "dirty" list.
|
||||||
cycler->remove_from_list();
|
cycler->remove_from_list();
|
||||||
cycler->insert_before(&_dirty);
|
cycler->insert_before(&_dirty);
|
||||||
cycler->_dirty = _next_cycle_seq;
|
cycler->mark_dirty(_next_cycle_seq);
|
||||||
++_num_dirty_cyclers;
|
++_num_dirty_cyclers;
|
||||||
|
|
||||||
#ifdef DEBUG_THREADS
|
#ifdef DEBUG_THREADS
|
||||||
@ -437,7 +437,7 @@ remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||||||
// careful not to cause a race condition. It's safe for us to remove it
|
// careful not to cause a race condition. It's safe for us to remove it
|
||||||
// during cycle only if it's 0 (clean) or _next_cycle_seq (scheduled for the
|
// during cycle only if it's 0 (clean) or _next_cycle_seq (scheduled for the
|
||||||
// next cycle, so not owned by the current one).
|
// next cycle, so not owned by the current one).
|
||||||
while (cycler->_dirty != 0 && cycler->_dirty != _next_cycle_seq) {
|
while (cycler->is_dirty(_next_cycle_seq)) {
|
||||||
if (_cycle_lock.try_lock()) {
|
if (_cycle_lock.try_lock()) {
|
||||||
// OK, great, we got the lock, so it finished cycling already.
|
// OK, great, we got the lock, so it finished cycling already.
|
||||||
nassertv(!_cycling);
|
nassertv(!_cycling);
|
||||||
@ -445,7 +445,7 @@ remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||||||
--_num_cyclers;
|
--_num_cyclers;
|
||||||
cycler->remove_from_list();
|
cycler->remove_from_list();
|
||||||
|
|
||||||
cycler->_dirty = false;
|
cycler->clear_dirty();
|
||||||
--_num_dirty_cyclers;
|
--_num_dirty_cyclers;
|
||||||
|
|
||||||
#ifdef DEBUG_THREADS
|
#ifdef DEBUG_THREADS
|
||||||
@ -474,8 +474,8 @@ remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||||||
inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), -1);
|
inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), -1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cycler->_dirty) {
|
if (cycler->is_dirty()) {
|
||||||
cycler->_dirty = 0;
|
cycler->clear_dirty();
|
||||||
--_num_dirty_cyclers;
|
--_num_dirty_cyclers;
|
||||||
#ifdef DEBUG_THREADS
|
#ifdef DEBUG_THREADS
|
||||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||||
|
@ -54,7 +54,7 @@ read_unlocked(Thread *current_thread) const {
|
|||||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_unlocked(Thread *)", " ", TAU_USER);
|
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_unlocked(Thread *)", " ", TAU_USER);
|
||||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
#endif
|
#endif
|
||||||
return _data[pipeline_stage]._cdata;
|
return _data[pipeline_stage]._cdata;
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ read(Thread *current_thread) const {
|
|||||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read(Thread *)", " ", TAU_USER);
|
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read(Thread *)", " ", TAU_USER);
|
||||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
#endif
|
#endif
|
||||||
_lock.acquire(current_thread);
|
_lock.acquire(current_thread);
|
||||||
return _data[pipeline_stage]._cdata;
|
return _data[pipeline_stage]._cdata;
|
||||||
@ -87,7 +87,7 @@ increment_read(const CycleData *pointer) const {
|
|||||||
TAU_PROFILE("void PipelineCyclerTrueImpl::increment_read(const CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("void PipelineCyclerTrueImpl::increment_read(const CycleData *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
nassertv(pipeline_stage >= 0 && pipeline_stage < get_num_stages());
|
||||||
nassertv(_data[pipeline_stage]._cdata == pointer);
|
nassertv(_data[pipeline_stage]._cdata == pointer);
|
||||||
#endif
|
#endif
|
||||||
_lock.elevate_lock();
|
_lock.elevate_lock();
|
||||||
@ -101,7 +101,7 @@ release_read(const CycleData *pointer) const {
|
|||||||
TAU_PROFILE("void PipelineCyclerTrueImpl::release_read(const CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("void PipelineCyclerTrueImpl::release_read(const CycleData *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
nassertv(pipeline_stage >= 0 && pipeline_stage < get_num_stages());
|
||||||
nassertv(_data[pipeline_stage]._cdata == pointer);
|
nassertv(_data[pipeline_stage]._cdata == pointer);
|
||||||
#endif
|
#endif
|
||||||
_lock.release();
|
_lock.release();
|
||||||
@ -161,7 +161,7 @@ elevate_read(const CycleData *pointer, Thread *current_thread) {
|
|||||||
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read(const CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read(const CycleData *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
||||||
#endif
|
#endif
|
||||||
CycleData *new_pointer = write(current_thread);
|
CycleData *new_pointer = write(current_thread);
|
||||||
@ -179,7 +179,7 @@ elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *current
|
|||||||
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
|
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
||||||
#endif
|
#endif
|
||||||
CycleData *new_pointer = write_upstream(force_to_0, current_thread);
|
CycleData *new_pointer = write_upstream(force_to_0, current_thread);
|
||||||
@ -196,7 +196,7 @@ increment_write(CycleData *pointer) const {
|
|||||||
TAU_PROFILE("void PipelineCyclerTrueImpl::increment_write(CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("void PipelineCyclerTrueImpl::increment_write(CycleData *)", " ", TAU_USER);
|
||||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
nassertv(pipeline_stage >= 0 && pipeline_stage < get_num_stages());
|
||||||
nassertv(_data[pipeline_stage]._cdata == pointer);
|
nassertv(_data[pipeline_stage]._cdata == pointer);
|
||||||
#endif
|
#endif
|
||||||
++(_data[pipeline_stage]._writes_outstanding);
|
++(_data[pipeline_stage]._writes_outstanding);
|
||||||
@ -213,12 +213,44 @@ release_write(CycleData *pointer) {
|
|||||||
return release_write_stage(pipeline_stage, pointer);
|
return release_write_stage(pipeline_stage, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ALWAYS_INLINE bool PipelineCyclerTrueImpl::
|
||||||
|
is_dirty() const {
|
||||||
|
return _single_data._dirty != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE bool PipelineCyclerTrueImpl::
|
||||||
|
is_dirty(unsigned int seq) const {
|
||||||
|
return _single_data._dirty != 0 && _single_data._dirty != seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE void PipelineCyclerTrueImpl::
|
||||||
|
mark_dirty(unsigned int seq) {
|
||||||
|
_single_data._dirty = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE void PipelineCyclerTrueImpl::
|
||||||
|
clear_dirty() {
|
||||||
|
_single_data._dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of stages in the pipeline.
|
* Returns the number of stages in the pipeline.
|
||||||
*/
|
*/
|
||||||
INLINE int PipelineCyclerTrueImpl::
|
INLINE int PipelineCyclerTrueImpl::
|
||||||
get_num_stages() {
|
get_num_stages() const {
|
||||||
return _num_stages;
|
return (_data == &_single_data) ? 1 : _data[0]._num_stages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -230,7 +262,7 @@ INLINE const CycleData *PipelineCyclerTrueImpl::
|
|||||||
read_stage_unlocked(int pipeline_stage) const {
|
read_stage_unlocked(int pipeline_stage) const {
|
||||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage_unlocked(int)", " ", TAU_USER);
|
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage_unlocked(int)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
||||||
__builtin_assume(pipeline_stage >= 0);
|
__builtin_assume(pipeline_stage >= 0);
|
||||||
#endif
|
#endif
|
||||||
@ -249,7 +281,7 @@ INLINE const CycleData *PipelineCyclerTrueImpl::
|
|||||||
read_stage(int pipeline_stage, Thread *current_thread) const {
|
read_stage(int pipeline_stage, Thread *current_thread) const {
|
||||||
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int, Thread *)", " ", TAU_USER);
|
TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int, Thread *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
||||||
__builtin_assume(pipeline_stage >= 0);
|
__builtin_assume(pipeline_stage >= 0);
|
||||||
#endif
|
#endif
|
||||||
@ -264,7 +296,7 @@ INLINE void PipelineCyclerTrueImpl::
|
|||||||
release_read_stage(int pipeline_stage, const CycleData *pointer) const {
|
release_read_stage(int pipeline_stage, const CycleData *pointer) const {
|
||||||
TAU_PROFILE("void PipelineCyclerTrueImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("void PipelineCyclerTrueImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
nassertv(pipeline_stage >= 0 && pipeline_stage < get_num_stages());
|
||||||
nassertv(_data[pipeline_stage]._cdata == pointer);
|
nassertv(_data[pipeline_stage]._cdata == pointer);
|
||||||
#endif
|
#endif
|
||||||
_lock.release();
|
_lock.release();
|
||||||
@ -280,7 +312,7 @@ elevate_read_stage(int pipeline_stage, const CycleData *pointer,
|
|||||||
Thread *current_thread) {
|
Thread *current_thread) {
|
||||||
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
||||||
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
||||||
__builtin_assume(pipeline_stage >= 0);
|
__builtin_assume(pipeline_stage >= 0);
|
||||||
@ -300,7 +332,7 @@ elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer,
|
|||||||
bool force_to_0, Thread *current_thread) {
|
bool force_to_0, Thread *current_thread) {
|
||||||
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
nassertr(_data[pipeline_stage]._cdata == pointer, nullptr);
|
||||||
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
||||||
__builtin_assume(pipeline_stage >= 0);
|
__builtin_assume(pipeline_stage >= 0);
|
||||||
@ -318,7 +350,7 @@ INLINE void PipelineCyclerTrueImpl::
|
|||||||
release_write_stage(int pipeline_stage, CycleData *pointer) {
|
release_write_stage(int pipeline_stage, CycleData *pointer) {
|
||||||
TAU_PROFILE("void PipelineCyclerTrueImpl::release_write_stage(int, const CycleData *)", " ", TAU_USER);
|
TAU_PROFILE("void PipelineCyclerTrueImpl::release_write_stage(int, const CycleData *)", " ", TAU_USER);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
nassertv(pipeline_stage >= 0 && pipeline_stage < get_num_stages());
|
||||||
nassertv(_data[pipeline_stage]._cdata == pointer);
|
nassertv(_data[pipeline_stage]._cdata == pointer);
|
||||||
nassertv(_data[pipeline_stage]._writes_outstanding > 0);
|
nassertv(_data[pipeline_stage]._writes_outstanding > 0);
|
||||||
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
#elif defined(__has_builtin) && __has_builtin(__builtin_assume)
|
||||||
@ -347,7 +379,9 @@ INLINE CycleData *PipelineCyclerTrueImpl::
|
|||||||
cheat() const {
|
cheat() const {
|
||||||
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::cheat()", " ", TAU_USER);
|
TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::cheat()", " ", TAU_USER);
|
||||||
int pipeline_stage = Thread::get_current_pipeline_stage();
|
int pipeline_stage = Thread::get_current_pipeline_stage();
|
||||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, nullptr);
|
#ifdef _DEBUG
|
||||||
|
nassertr(pipeline_stage >= 0 && pipeline_stage < get_num_stages(), nullptr);
|
||||||
|
#endif
|
||||||
return _data[pipeline_stage]._cdata;
|
return _data[pipeline_stage]._cdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,14 +420,17 @@ cycle_2() {
|
|||||||
last_val->node_unref_only();
|
last_val->node_unref_only();
|
||||||
|
|
||||||
nassertr(_lock.debug_is_locked(), last_val);
|
nassertr(_lock.debug_is_locked(), last_val);
|
||||||
nassertr(_dirty, last_val);
|
nassertr(is_dirty(), last_val);
|
||||||
nassertr(_num_stages == 2, last_val);
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
nassertr(get_num_stages() == 2, last_val);
|
||||||
|
#endif
|
||||||
|
|
||||||
nassertr(_data[1]._writes_outstanding == 0, last_val);
|
nassertr(_data[1]._writes_outstanding == 0, last_val);
|
||||||
_data[1]._cdata = _data[0]._cdata;
|
_data[1]._cdata = _data[0]._cdata;
|
||||||
|
|
||||||
// No longer dirty.
|
// No longer dirty.
|
||||||
_dirty = 0;
|
clear_dirty();
|
||||||
return last_val;
|
return last_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,8 +450,11 @@ cycle_3() {
|
|||||||
last_val->node_unref_only();
|
last_val->node_unref_only();
|
||||||
|
|
||||||
nassertr(_lock.debug_is_locked(), last_val);
|
nassertr(_lock.debug_is_locked(), last_val);
|
||||||
nassertr(_dirty, last_val);
|
nassertr(is_dirty(), last_val);
|
||||||
nassertr(_num_stages == 3, last_val);
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
nassertr(get_num_stages() == 3, last_val);
|
||||||
|
#endif
|
||||||
|
|
||||||
nassertr(_data[2]._writes_outstanding == 0, last_val);
|
nassertr(_data[2]._writes_outstanding == 0, last_val);
|
||||||
nassertr(_data[1]._writes_outstanding == 0, last_val);
|
nassertr(_data[1]._writes_outstanding == 0, last_val);
|
||||||
@ -423,7 +463,7 @@ cycle_3() {
|
|||||||
|
|
||||||
if (_data[2]._cdata == _data[1]._cdata) {
|
if (_data[2]._cdata == _data[1]._cdata) {
|
||||||
// No longer dirty.
|
// No longer dirty.
|
||||||
_dirty = 0;
|
clear_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_val;
|
return last_val;
|
||||||
@ -439,15 +479,6 @@ CyclerMutex(PipelineCyclerTrueImpl *cycler) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
INLINE PipelineCyclerTrueImpl::CycleDataNode::
|
|
||||||
CycleDataNode() :
|
|
||||||
_writes_outstanding(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -24,17 +24,26 @@
|
|||||||
PipelineCyclerTrueImpl::
|
PipelineCyclerTrueImpl::
|
||||||
PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
||||||
_pipeline(pipeline),
|
_pipeline(pipeline),
|
||||||
_dirty(0),
|
|
||||||
_lock(this)
|
_lock(this)
|
||||||
{
|
{
|
||||||
|
clear_dirty();
|
||||||
|
|
||||||
if (_pipeline == nullptr) {
|
if (_pipeline == nullptr) {
|
||||||
_pipeline = Pipeline::get_render_pipeline();
|
_pipeline = Pipeline::get_render_pipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
_num_stages = _pipeline->get_num_stages();
|
int num_stages = _pipeline->get_num_stages();
|
||||||
_data = new CycleDataNode[_num_stages];
|
if (num_stages == 1) {
|
||||||
for (int i = 0; i < _num_stages; ++i) {
|
_single_data._cdata = initial_data;
|
||||||
_data[i]._cdata = initial_data;
|
_data = &_single_data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_data = new CycleDataNode[num_stages];
|
||||||
|
_data[0]._num_stages = num_stages;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_stages; ++i) {
|
||||||
|
_data[i]._cdata = initial_data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_pipeline->add_cycler(this);
|
_pipeline->add_cycler(this);
|
||||||
@ -46,27 +55,31 @@ PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
|||||||
PipelineCyclerTrueImpl::
|
PipelineCyclerTrueImpl::
|
||||||
PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
||||||
_pipeline(copy._pipeline),
|
_pipeline(copy._pipeline),
|
||||||
_dirty(0),
|
|
||||||
_lock(this)
|
_lock(this)
|
||||||
{
|
{
|
||||||
|
clear_dirty();
|
||||||
|
|
||||||
ReMutexHolder holder(_lock);
|
ReMutexHolder holder(_lock);
|
||||||
ReMutexHolder holder2(copy._lock);
|
ReMutexHolder holder2(copy._lock);
|
||||||
|
|
||||||
_num_stages = _pipeline->get_num_stages();
|
int num_stages = _pipeline->get_num_stages();
|
||||||
nassertv(_num_stages == copy._num_stages);
|
nassertv(num_stages == copy.get_num_stages());
|
||||||
_data = new CycleDataNode[_num_stages];
|
|
||||||
|
|
||||||
if (_num_stages == 1) {
|
if (num_stages == 1) {
|
||||||
_data[0]._cdata = copy._data[0]._cdata->make_copy();
|
_single_data._cdata = copy._single_data._cdata->make_copy();
|
||||||
|
_data = &_single_data;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
_data = new CycleDataNode[num_stages];
|
||||||
|
_data[0]._num_stages = num_stages;
|
||||||
|
|
||||||
// It's no longer critically important that we preserve pointerwise
|
// It's no longer critically important that we preserve pointerwise
|
||||||
// equivalence between different stages in the copy, but it doesn't cost
|
// 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.
|
// much and might be a little more efficient, so we do it anyway.
|
||||||
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
||||||
Pointers pointers;
|
Pointers pointers;
|
||||||
|
|
||||||
for (int i = 0; i < _num_stages; ++i) {
|
for (int i = 0; i < num_stages; ++i) {
|
||||||
PT(CycleData) &new_pt = pointers[copy._data[i]._cdata];
|
PT(CycleData) &new_pt = pointers[copy._data[i]._cdata];
|
||||||
if (new_pt == nullptr) {
|
if (new_pt == nullptr) {
|
||||||
new_pt = copy._data[i]._cdata->make_copy();
|
new_pt = copy._data[i]._cdata->make_copy();
|
||||||
@ -75,7 +88,7 @@ PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_pipeline->add_cycler(this, copy._dirty != 0);
|
_pipeline->add_cycler(this, copy.is_dirty());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,19 +100,27 @@ operator = (const PipelineCyclerTrueImpl ©) {
|
|||||||
ReMutexHolder holder2(copy._lock);
|
ReMutexHolder holder2(copy._lock);
|
||||||
nassertv(get_parent_type() == copy.get_parent_type());
|
nassertv(get_parent_type() == copy.get_parent_type());
|
||||||
|
|
||||||
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
if (_data == &_single_data) {
|
||||||
Pointers pointers;
|
_single_data._cdata = copy._single_data._cdata->make_copy();
|
||||||
|
nassertv(!copy.is_dirty());
|
||||||
for (int i = 0; i < _num_stages; ++i) {
|
|
||||||
PT(CycleData) &new_pt = pointers[copy._data[i]._cdata];
|
|
||||||
if (new_pt == nullptr) {
|
|
||||||
new_pt = copy._data[i]._cdata->make_copy();
|
|
||||||
}
|
|
||||||
_data[i]._cdata = new_pt.p();
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
int num_stages = _data[0]._num_stages;
|
||||||
|
|
||||||
if (copy._dirty && !_dirty) {
|
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
||||||
_pipeline->add_dirty_cycler(this);
|
Pointers pointers;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_stages; ++i) {
|
||||||
|
PT(CycleData) &new_pt = pointers[copy._data[i]._cdata];
|
||||||
|
if (new_pt == nullptr) {
|
||||||
|
new_pt = copy._data[i]._cdata->make_copy();
|
||||||
|
}
|
||||||
|
_data[i]._cdata = new_pt.p();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy.is_dirty() && !is_dirty()) {
|
||||||
|
_pipeline->add_dirty_cycler(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,9 +133,10 @@ PipelineCyclerTrueImpl::
|
|||||||
|
|
||||||
_pipeline->remove_cycler(this);
|
_pipeline->remove_cycler(this);
|
||||||
|
|
||||||
delete[] _data;
|
if (_data != &_single_data) {
|
||||||
|
delete[] _data;
|
||||||
|
}
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
_num_stages = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,12 +149,12 @@ CycleData *PipelineCyclerTrueImpl::
|
|||||||
write_stage(int pipeline_stage, Thread *current_thread) {
|
write_stage(int pipeline_stage, Thread *current_thread) {
|
||||||
_lock.acquire(current_thread);
|
_lock.acquire(current_thread);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifdef _DEBUG
|
||||||
nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
|
nassertd(pipeline_stage >= 0 && pipeline_stage < get_num_stages()) {
|
||||||
_lock.release();
|
_lock.release();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif // NDEBUG
|
#endif
|
||||||
|
|
||||||
CycleData *old_data = _data[pipeline_stage]._cdata;
|
CycleData *old_data = _data[pipeline_stage]._cdata;
|
||||||
|
|
||||||
@ -157,7 +179,7 @@ write_stage(int pipeline_stage, Thread *current_thread) {
|
|||||||
|
|
||||||
// Now we have differences between some of the data pointers, so we're
|
// Now we have differences between some of the data pointers, so we're
|
||||||
// "dirty". Mark it so.
|
// "dirty". Mark it so.
|
||||||
if (!_dirty && _num_stages != 1) {
|
if (!is_dirty() && _data != &_single_data) {
|
||||||
_pipeline->add_dirty_cycler(this);
|
_pipeline->add_dirty_cycler(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,12 +197,12 @@ CycleData *PipelineCyclerTrueImpl::
|
|||||||
write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread) {
|
write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread) {
|
||||||
_lock.acquire(current_thread);
|
_lock.acquire(current_thread);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifdef _DEBUG
|
||||||
nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
|
nassertd(pipeline_stage >= 0 && pipeline_stage < get_num_stages()) {
|
||||||
_lock.release();
|
_lock.release();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif // NDEBUG
|
#endif
|
||||||
|
|
||||||
CycleData *old_data = _data[pipeline_stage]._cdata;
|
CycleData *old_data = _data[pipeline_stage]._cdata;
|
||||||
|
|
||||||
@ -218,15 +240,15 @@ write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread
|
|||||||
|
|
||||||
_data[pipeline_stage]._cdata = new_data;
|
_data[pipeline_stage]._cdata = new_data;
|
||||||
|
|
||||||
if (k >= 0 || pipeline_stage + 1 < _num_stages) {
|
if (k >= 0 || pipeline_stage + 1 < get_num_stages()) {
|
||||||
// Now we have differences between some of the data pointers, which
|
// Now we have differences between some of the data pointers, which
|
||||||
// makes us "dirty".
|
// makes us "dirty".
|
||||||
if (!_dirty) {
|
if (!is_dirty()) {
|
||||||
_pipeline->add_dirty_cycler(this);
|
_pipeline->add_dirty_cycler(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (k >= 0 && force_to_0) {
|
else if (k >= 0 && force_to_0) {
|
||||||
// There are no external pointers, so no need to copy-on-write, but the
|
// 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.
|
// current pointer doesn't go all the way back. Make it do so.
|
||||||
while (k >= 0) {
|
while (k >= 0) {
|
||||||
@ -259,20 +281,21 @@ PT(CycleData) PipelineCyclerTrueImpl::
|
|||||||
cycle() {
|
cycle() {
|
||||||
// This trick moves an NPT into a PT without unnecessarily incrementing and
|
// This trick moves an NPT into a PT without unnecessarily incrementing and
|
||||||
// subsequently decrementing the regular reference count.
|
// subsequently decrementing the regular reference count.
|
||||||
|
int num_stages = get_num_stages();
|
||||||
PT(CycleData) last_val;
|
PT(CycleData) last_val;
|
||||||
last_val.swap(_data[_num_stages - 1]._cdata);
|
last_val.swap(_data[num_stages - 1]._cdata);
|
||||||
last_val->node_unref_only();
|
last_val->node_unref_only();
|
||||||
|
|
||||||
nassertr(_lock.debug_is_locked(), last_val);
|
nassertr(_lock.debug_is_locked(), last_val);
|
||||||
nassertr(_dirty, last_val);
|
nassertr(is_dirty(), last_val);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = _num_stages - 1; i > 0; --i) {
|
for (i = num_stages - 1; i > 0; --i) {
|
||||||
nassertr(_data[i]._writes_outstanding == 0, last_val);
|
nassertr(_data[i]._writes_outstanding == 0, last_val);
|
||||||
_data[i]._cdata = _data[i - 1]._cdata;
|
_data[i]._cdata = _data[i - 1]._cdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i < _num_stages; ++i) {
|
for (i = 1; i < num_stages; ++i) {
|
||||||
if (_data[i]._cdata != _data[i - 1]._cdata) {
|
if (_data[i]._cdata != _data[i - 1]._cdata) {
|
||||||
// Still dirty.
|
// Still dirty.
|
||||||
return last_val;
|
return last_val;
|
||||||
@ -280,7 +303,7 @@ cycle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No longer dirty.
|
// No longer dirty.
|
||||||
_dirty = 0;
|
clear_dirty();
|
||||||
return last_val;
|
return last_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,31 +315,57 @@ void PipelineCyclerTrueImpl::
|
|||||||
set_num_stages(int num_stages) {
|
set_num_stages(int num_stages) {
|
||||||
nassertv(_lock.debug_is_locked());
|
nassertv(_lock.debug_is_locked());
|
||||||
|
|
||||||
if (num_stages <= _num_stages) {
|
if (_data == &_single_data) {
|
||||||
|
// We've got only 1 stage. Allocate an array.
|
||||||
|
if (num_stages > 1) {
|
||||||
|
nassertv(_single_data._writes_outstanding == 0);
|
||||||
|
|
||||||
|
CycleDataNode *new_data = new CycleDataNode[num_stages];
|
||||||
|
new_data[0]._num_stages = num_stages;
|
||||||
|
new_data[0]._cdata = std::move(_single_data._cdata);
|
||||||
|
_single_data._cdata.clear();
|
||||||
|
|
||||||
|
for (int i = 1; i < num_stages; ++i) {
|
||||||
|
new_data[i]._cdata = new_data[0]._cdata;
|
||||||
|
}
|
||||||
|
_data = new_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (num_stages == 1) {
|
||||||
|
// Deallocate the array, since we're back to one stage.
|
||||||
|
if (_data != &_single_data) {
|
||||||
|
nassertv(_data[0]._writes_outstanding == 0);
|
||||||
|
_single_data._cdata = std::move(_data[0]._cdata);
|
||||||
|
_data = &_single_data;
|
||||||
|
delete[] _data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (num_stages <= _data[0]._num_stages) {
|
||||||
// Don't bother to reallocate the array smaller; we just won't use the
|
// Don't bother to reallocate the array smaller; we just won't use the
|
||||||
// rest of the array.
|
// rest of the array.
|
||||||
for (int i = _num_stages; i < num_stages; ++i) {
|
int old_stages = _data[0]._num_stages;
|
||||||
|
for (int i = old_stages; i < num_stages; ++i) {
|
||||||
nassertv(_data[i]._writes_outstanding == 0);
|
nassertv(_data[i]._writes_outstanding == 0);
|
||||||
_data[i]._cdata.clear();
|
_data[i]._cdata.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
_num_stages = num_stages;
|
_data[0]._num_stages = num_stages;
|
||||||
|
}
|
||||||
|
else {
|
||||||
} else {
|
|
||||||
// To increase the array, we must reallocate it larger.
|
// To increase the array, we must reallocate it larger.
|
||||||
|
int old_stages = _data[0]._num_stages;
|
||||||
CycleDataNode *new_data = new CycleDataNode[num_stages];
|
CycleDataNode *new_data = new CycleDataNode[num_stages];
|
||||||
|
new_data[0]._num_stages = num_stages;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < _num_stages; ++i) {
|
for (i = 0; i < old_stages; ++i) {
|
||||||
nassertv(_data[i]._writes_outstanding == 0);
|
nassertv(_data[i]._writes_outstanding == 0);
|
||||||
new_data[i]._cdata = _data[i]._cdata;
|
new_data[i]._cdata = _data[i]._cdata;
|
||||||
}
|
}
|
||||||
for (i = _num_stages; i < num_stages; ++i) {
|
for (i = old_stages; i < num_stages; ++i) {
|
||||||
new_data[i]._cdata = _data[_num_stages - 1]._cdata;
|
new_data[i]._cdata = _data[old_stages - 1]._cdata;
|
||||||
}
|
}
|
||||||
delete[] _data;
|
delete[] _data;
|
||||||
|
|
||||||
_num_stages = num_stages;
|
|
||||||
_data = new_data;
|
_data = new_data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,12 @@ public:
|
|||||||
INLINE void increment_write(CycleData *pointer) const;
|
INLINE void increment_write(CycleData *pointer) const;
|
||||||
INLINE void release_write(CycleData *pointer);
|
INLINE void release_write(CycleData *pointer);
|
||||||
|
|
||||||
INLINE int get_num_stages();
|
ALWAYS_INLINE bool is_dirty() const;
|
||||||
|
INLINE bool is_dirty(unsigned int seq) const;
|
||||||
|
INLINE void mark_dirty(unsigned int seq);
|
||||||
|
INLINE void clear_dirty();
|
||||||
|
|
||||||
|
INLINE int get_num_stages() const;
|
||||||
INLINE const CycleData *read_stage_unlocked(int pipeline_stage) const;
|
INLINE const CycleData *read_stage_unlocked(int pipeline_stage) const;
|
||||||
INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
|
INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
|
||||||
INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
|
INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
|
||||||
@ -110,22 +115,32 @@ private:
|
|||||||
|
|
||||||
// An array of PT(CycleData) objects representing the different copies of
|
// An array of PT(CycleData) objects representing the different copies of
|
||||||
// the cycled data, one for each stage.
|
// the cycled data, one for each stage.
|
||||||
class CycleDataNode : public MemoryBase {
|
class CycleDataNode {
|
||||||
public:
|
public:
|
||||||
INLINE CycleDataNode();
|
CycleDataNode() = default;
|
||||||
INLINE CycleDataNode(const CycleDataNode ©);
|
INLINE CycleDataNode(const CycleDataNode ©);
|
||||||
INLINE ~CycleDataNode();
|
INLINE ~CycleDataNode();
|
||||||
INLINE void operator = (const CycleDataNode ©);
|
INLINE void operator = (const CycleDataNode ©);
|
||||||
|
|
||||||
NPT(CycleData) _cdata;
|
NPT(CycleData) _cdata;
|
||||||
int _writes_outstanding;
|
int _writes_outstanding = 0;
|
||||||
};
|
|
||||||
CycleDataNode *_data;
|
|
||||||
int _num_stages;
|
|
||||||
|
|
||||||
// This is 0 if it's clean, or set to Pipeline::_next_cycle_seq if it's
|
// Take advantage of the extra padding space.
|
||||||
// scheduled to be cycled during the next cycle() call.
|
// If used as part of _single_cdata, stores the dirty flag.
|
||||||
unsigned int _dirty;
|
// If used as part of _data[0], stores the number of stages.
|
||||||
|
// Otherwise, this field is unused.
|
||||||
|
union {
|
||||||
|
// This is 0 if it's clean, or set to Pipeline::_next_cycle_seq if it's
|
||||||
|
// scheduled to be cycled during the next cycle() call.
|
||||||
|
unsigned int _dirty;
|
||||||
|
|
||||||
|
int _num_stages;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// Store a single copy on the class, to optimize the common case of only one
|
||||||
|
// stage.
|
||||||
|
CycleDataNode _single_data;
|
||||||
|
CycleDataNode *_data;
|
||||||
|
|
||||||
CyclerMutex _lock;
|
CyclerMutex _lock;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user