enable clearing of old cache items

This commit is contained in:
David Rose 2002-07-15 21:25:32 +00:00
parent 49e157c65d
commit 28dcfa514a
4 changed files with 173 additions and 1 deletions

View File

@ -621,6 +621,89 @@ get_max_priority() {
return 1000000000;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_cache_size
// Access: Published, Static
// Description: Returns the total number of unique RenderState
// objects allocated in the world. This will go up and
// down during normal operations.
////////////////////////////////////////////////////////////////////
int RenderState::
get_cache_size() {
if (_states == (States *)NULL) {
return 0;
}
return _states->size();
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::clear_cache
// Access: Published, Static
// Description: Empties the cache of composed RenderStates. This
// makes every RenderState forget what results when
// it is composed with other RenderStates.
//
// This will eliminate any RenderState objects that
// have been allocated but have no references outside of
// the internal RenderState map. It will not
// eliminate RenderState objects that are still in
// use.
//
// Normally, RenderState objects will remove
// themselves from the interal map when their reference
// counts go to 0, but since circular references are
// possible there may be some cycles that cannot remove
// themselves. Calling this function from time to time
// will ensure there is no wasteful memory leakage, but
// calling it too often may result in decreased
// performance as the cache is forced to be recomputed.
//
// The return value is the number of RenderStates
// freed by this operation.
////////////////////////////////////////////////////////////////////
int RenderState::
clear_cache() {
if (_states == (States *)NULL) {
return 0;
}
int orig_size = _states->size();
// First, we need to copy the entire set of states to a temporary
// vector, reference-counting each object. That way we can walk
// through the copy, without fear of dereferencing (and deleting)
// the objects in the map as we go.
{
typedef pvector< CPT(RenderState) > TempStates;
TempStates temp_states;
temp_states.reserve(orig_size);
copy(_states->begin(), _states->end(),
back_inserter(temp_states));
// Now it's safe to walk through the list, destroying the cache
// within each object as we go. Nothing will be destructed till
// we're done.
TempStates::iterator ti;
for (ti = temp_states.begin(); ti != temp_states.end(); ++ti) {
RenderState *state = (RenderState *)(*ti).p();
state->_composition_cache.clear();
state->_invert_composition_cache.clear();
if (state->_self_compose != (RenderState *)NULL &&
state->_self_compose != state) {
unref_delete((RenderState *)state->_self_compose);
}
}
// Once this block closes and the temp_states object goes away,
// all the destruction will begin. Anything whose reference was
// held only within the various objects' caches will go away.
}
int new_size = _states->size();
return orig_size - new_size;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::issue_delta_modify
// Access: Public

View File

@ -95,6 +95,9 @@ PUBLISHED:
static int get_max_priority();
static int get_cache_size();
static int clear_cache();
public:
INLINE int get_bin_index() const;
INLINE int get_draw_order() const;

View File

@ -40,7 +40,7 @@ TransformState() {
if (_states == (States *)NULL) {
// Make sure the global _states map is allocated. This only has
// to be done once. We could make this map static, but then we
// run into problems if anyone creates a RenderState object at
// run into problems if anyone creates a TransformState object at
// static init time; it also seems to cause problems when the
// Panda shared library is unloaded at application exit time.
_states = new States;
@ -652,6 +652,89 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_cache_size
// Access: Published, Static
// Description: Returns the total number of unique TransformState
// objects allocated in the world. This will go up and
// down during normal operations.
////////////////////////////////////////////////////////////////////
int TransformState::
get_cache_size() {
if (_states == (States *)NULL) {
return 0;
}
return _states->size();
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::clear_cache
// Access: Published, Static
// Description: Empties the cache of composed TransformStates. This
// makes every TransformState forget what results when
// it is composed with other TransformStates.
//
// This will eliminate any TransformState objects that
// have been allocated but have no references outside of
// the internal TransformState map. It will not
// eliminate TransformState objects that are still in
// use.
//
// Normally, TransformState objects will remove
// themselves from the interal map when their reference
// counts go to 0, but since circular references are
// possible there may be some cycles that cannot remove
// themselves. Calling this function from time to time
// will ensure there is no wasteful memory leakage, but
// calling it too often may result in decreased
// performance as the cache is forced to be recomputed.
//
// The return value is the number of TransformStates
// freed by this operation.
////////////////////////////////////////////////////////////////////
int TransformState::
clear_cache() {
if (_states == (States *)NULL) {
return 0;
}
int orig_size = _states->size();
// First, we need to copy the entire set of transforms to a
// temporary vector, reference-counting each object. That way we
// can walk through the copy, without fear of dereferencing (and
// deleting) the objects in the map as we go.
{
typedef pvector< CPT(TransformState) > TempStates;
TempStates temp_states;
temp_states.reserve(orig_size);
copy(_states->begin(), _states->end(),
back_inserter(temp_states));
// Now it's safe to walk through the list, destroying the cache
// within each object as we go. Nothing will be destructed till
// we're done.
TempStates::iterator ti;
for (ti = temp_states.begin(); ti != temp_states.end(); ++ti) {
TransformState *state = (TransformState *)(*ti).p();
state->_composition_cache.clear();
state->_invert_composition_cache.clear();
if (state->_self_compose != (TransformState *)NULL &&
state->_self_compose != state) {
unref_delete((TransformState *)state->_self_compose);
}
}
// Once this block closes and the temp_states object goes away,
// all the destruction will begin. Anything whose reference was
// held only within the various objects' caches will go away.
}
int new_size = _states->size();
return orig_size - new_size;
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::return_new
// Access: Private, Static

View File

@ -115,6 +115,9 @@ PUBLISHED:
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
static int get_cache_size();
static int clear_cache();
private:
static CPT(TransformState) return_new(TransformState *state);
CPT(TransformState) do_compose(const TransformState *other) const;