further debugging in TransformState (and one important bugfix)

This commit is contained in:
David Rose 2011-09-07 23:44:36 +00:00
parent 212ed1e510
commit e552c230a0
2 changed files with 156 additions and 48 deletions

View File

@ -768,6 +768,66 @@ unref() const {
return false; return false;
} }
////////////////////////////////////////////////////////////////////
// Function: TransformState::validate_composition_cache
// Access: Published
// Description: Returns true if the composition cache and invert
// composition cache for this particular TransformState
// are self-consistent and valid, false otherwise.
////////////////////////////////////////////////////////////////////
bool TransformState::
validate_composition_cache() const {
LightReMutexHolder holder(*_states_lock);
int size = _composition_cache.get_size();
for (int i = 0; i < size; ++i) {
if (!_composition_cache.has_element(i)) {
continue;
}
const TransformState *source = _composition_cache.get_key(i);
if (source != (TransformState *)NULL) {
// Check that the source also has a pointer back to this one. We
// always add entries to the composition cache in pairs.
int ri = source->_composition_cache.find(this);
if (ri == -1) {
// Failure! There is no back-pointer.
pgraph_cat.error()
<< "TransformState::composition cache is inconsistent!\n";
pgraph_cat.error(false)
<< *this << " compose " << *source << "\n";
pgraph_cat.error(false)
<< "but no reverse\n";
return false;
}
}
}
size = _invert_composition_cache.get_size();
for (int i = 0; i < size; ++i) {
if (!_invert_composition_cache.has_element(i)) {
continue;
}
const TransformState *source = _invert_composition_cache.get_key(i);
if (source != (TransformState *)NULL) {
// Check that the source also has a pointer back to this one. We
// always add entries to the composition cache in pairs.
int ri = source->_invert_composition_cache.find(this);
if (ri == -1) {
// Failure! There is no back-pointer.
pgraph_cat.error()
<< "TransformState::invert composition cache is inconsistent!\n";
pgraph_cat.error(false)
<< *this << " invert compose " << *source << "\n";
pgraph_cat.error(false)
<< "but no reverse\n";
return false;
}
}
}
return true;
}
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TransformState::get_composition_cache // Function: TransformState::get_composition_cache
@ -787,43 +847,47 @@ PyObject *TransformState::
get_composition_cache() const { get_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
LightReMutexHolder holder(*_states_lock); LightReMutexHolder holder(*_states_lock);
size_t cache_size = _composition_cache.get_size();
PyObject *list = PyList_New(cache_size);
for (size_t i = 0; i < cache_size; ++i) { size_t num_states = _composition_cache.get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _composition_cache.get_size();
for (int si = 0; si < size; ++si) {
if (!_composition_cache.has_element(si)) {
continue;
}
PyObject *tuple = PyTuple_New(2); PyObject *tuple = PyTuple_New(2);
PyObject *a, *b; PyObject *a, *b;
if (!_composition_cache.has_element(i)) {
const TransformState *source = _composition_cache.get_key(si);
if (source == (TransformState *)NULL) {
a = Py_None; a = Py_None;
Py_INCREF(a); Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _composition_cache.get_data(si)._result;
if (result == (TransformState *)NULL) {
b = Py_None; b = Py_None;
Py_INCREF(b); Py_INCREF(b);
} else { } else {
const TransformState *source = _composition_cache.get_key(i); result->ref();
if (source == (TransformState *)NULL) { b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
a = Py_None; true, true, result->get_type_index());
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _composition_cache.get_data(i)._result;
if (result == (TransformState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
true, true, result->get_type_index());
}
} }
PyTuple_SET_ITEM(tuple, 0, a); PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b); PyTuple_SET_ITEM(tuple, 1, b);
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, tuple); PyList_SET_ITEM(list, i, tuple);
++i;
} }
nassertr(i == num_states, list);
return list; return list;
} }
#endif // HAVE_PYTHON #endif // HAVE_PYTHON
@ -847,43 +911,47 @@ PyObject *TransformState::
get_invert_composition_cache() const { get_invert_composition_cache() const {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
LightReMutexHolder holder(*_states_lock); LightReMutexHolder holder(*_states_lock);
size_t cache_size = _invert_composition_cache.get_size();
PyObject *list = PyList_New(cache_size);
for (size_t i = 0; i < cache_size; ++i) { size_t num_states = _invert_composition_cache.get_num_entries();
PyObject *list = PyList_New(num_states);
size_t i = 0;
int size = _invert_composition_cache.get_size();
for (int si = 0; si < size; ++si) {
if (!_invert_composition_cache.has_element(si)) {
continue;
}
PyObject *tuple = PyTuple_New(2); PyObject *tuple = PyTuple_New(2);
PyObject *a, *b; PyObject *a, *b;
if (!_invert_composition_cache.has_element(i)) {
const TransformState *source = _invert_composition_cache.get_key(si);
if (source == (TransformState *)NULL) {
a = Py_None; a = Py_None;
Py_INCREF(a); Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _invert_composition_cache.get_data(si)._result;
if (result == (TransformState *)NULL) {
b = Py_None; b = Py_None;
Py_INCREF(b); Py_INCREF(b);
} else { } else {
const TransformState *source = _invert_composition_cache.get_key(i); result->ref();
if (source == (TransformState *)NULL) { b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
a = Py_None; true, true, result->get_type_index());
Py_INCREF(a);
} else {
source->ref();
a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState,
true, true, source->get_type_index());
}
const TransformState *result = _invert_composition_cache.get_data(i)._result;
if (result == (TransformState *)NULL) {
b = Py_None;
Py_INCREF(b);
} else {
result->ref();
b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState,
true, true, result->get_type_index());
}
} }
PyTuple_SET_ITEM(tuple, 0, a); PyTuple_SET_ITEM(tuple, 0, a);
PyTuple_SET_ITEM(tuple, 1, b); PyTuple_SET_ITEM(tuple, 1, b);
nassertr(i < num_states, list);
PyList_SET_ITEM(list, i, tuple); PyList_SET_ITEM(list, i, tuple);
++i;
} }
nassertr(i == num_states, list);
return list; return list;
} }
#endif // HAVE_PYTHON #endif // HAVE_PYTHON
@ -1441,6 +1509,9 @@ validate_states() {
while (snext < size) { while (snext < size) {
nassertr(_states->get_key(snext)->get_ref_count() >= 0, false); nassertr(_states->get_key(snext)->get_ref_count() >= 0, false);
const TransformState *ssi = _states->get_key(si); const TransformState *ssi = _states->get_key(si);
if (!ssi->validate_composition_cache()) {
return false;
}
const TransformState *ssnext = _states->get_key(snext); const TransformState *ssnext = _states->get_key(snext);
int c = ssi->compare_to(*ssnext); int c = ssi->compare_to(*ssnext);
int ci = ssnext->compare_to(*ssi); int ci = ssnext->compare_to(*ssi);
@ -1506,6 +1577,42 @@ get_states() {
} }
#endif // HAVE_PYTHON #endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: TransformState::get_unused_states
// Access: Published, Static
// Description: Returns a list of all of the "unused" TransformState
// objects in the state cache. See
// get_num_unused_states().
////////////////////////////////////////////////////////////////////
PyObject *TransformState::
get_unused_states() {
IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState;
if (_states == (States *)NULL) {
return PyList_New(0);
}
LightReMutexHolder holder(*_states_lock);
PyObject *list = PyList_New(0);
int size = _states->get_size();
for (int si = 0; si < size; ++si) {
if (!_states->has_element(si)) {
continue;
}
const TransformState *state = _states->get_key(si);
if (state->get_cache_ref_count() == state->get_ref_count()) {
state->ref();
PyObject *a =
DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState,
true, true, state->get_type_index());
PyList_Append(list, a);
Py_DECREF(a);
}
}
return list;
}
#endif // HAVE_PYTHON
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TransformState::init_states // Function: TransformState::init_states
// Access: Public, Static // Access: Public, Static
@ -2322,8 +2429,7 @@ do_calc_hash() {
// Only bother to put the rest of the stuff in the hash if the // Only bother to put the rest of the stuff in the hash if the
// transform is not invalid or empty. // transform is not invalid or empty.
if ((_flags & (F_components_given | F_hpr_given | F_quat_given)) == if ((_flags & F_components_given) != 0) {
(F_components_given | F_hpr_given | F_quat_given)) {
// If the transform was specified componentwise, hash it // If the transform was specified componentwise, hash it
// componentwise. // componentwise.
_hash = _pos.add_hash(_hash); _hash = _pos.add_hash(_hash);

View File

@ -189,6 +189,7 @@ PUBLISHED:
INLINE int get_invert_composition_cache_size() const; INLINE int get_invert_composition_cache_size() const;
INLINE const TransformState *get_invert_composition_cache_source(int n) const; INLINE const TransformState *get_invert_composition_cache_source(int n) const;
INLINE const TransformState *get_invert_composition_cache_result(int n) const; INLINE const TransformState *get_invert_composition_cache_result(int n) const;
bool validate_composition_cache() const;
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
PyObject *get_composition_cache() const; PyObject *get_composition_cache() const;
PyObject *get_invert_composition_cache() const; PyObject *get_invert_composition_cache() const;
@ -207,6 +208,7 @@ PUBLISHED:
static bool validate_states(); static bool validate_states();
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
static PyObject *get_states(); static PyObject *get_states();
static PyObject *get_unused_states();
#endif // HAVE_PYTHON #endif // HAVE_PYTHON