fix deadlock with reset_prev_transform()

This commit is contained in:
David Rose 2011-11-17 19:20:38 +00:00
parent 8aae06ec43
commit b8497a0478
5 changed files with 48 additions and 29 deletions

View File

@ -848,36 +848,34 @@ verify_child_no_cycles(PandaNode *child_node) {
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_dirty_prev_transform
// Function: PandaNode::do_set_dirty_prev_transform
// Access: Private
// Description: Sets the dirty_prev_transform flag, and adds the node
// to the _dirty_prev_transforms chain.
// to the _dirty_prev_transforms chain. Assumes
// _dirty_prev_transforms._lock is already held.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_dirty_prev_transform() {
do_set_dirty_prev_transform() {
nassertv(_dirty_prev_transforms._lock.debug_is_locked());
if (!_dirty_prev_transform) {
LightMutexHolder holder(_dirty_prev_transforms._lock);
if (!_dirty_prev_transform) {
LinkedListNode::insert_before(&_dirty_prev_transforms);
_dirty_prev_transform = true;
}
LinkedListNode::insert_before(&_dirty_prev_transforms);
_dirty_prev_transform = true;
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_dirty_prev_transform
// Function: PandaNode::do_clear_dirty_prev_transform
// Access: Private
// Description: Clears the dirty_prev_transform flag, and removes the node
// from the _dirty_prev_transforms chain.
// from the _dirty_prev_transforms chain. Assumes
// _dirty_prev_transforms._lock is already held.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_dirty_prev_transform() {
do_clear_dirty_prev_transform() {
nassertv(_dirty_prev_transforms._lock.debug_is_locked());
if (_dirty_prev_transform) {
LightMutexHolder holder(_dirty_prev_transforms._lock);
if (_dirty_prev_transform) {
LinkedListNode::remove_from_list();
_dirty_prev_transform = false;
}
LinkedListNode::remove_from_list();
_dirty_prev_transform = false;
}
}

View File

@ -38,7 +38,7 @@ TypeHandle PandaNode::BamReaderAuxDataDown::_type_handle;
PandaNode::SceneRootFunc *PandaNode::_scene_root_func;
PandaNodeChain PandaNode::_dirty_prev_transforms;
PandaNodeChain PandaNode::_dirty_prev_transforms("_dirty_prev_transforms");
DrawMask PandaNode::_overall_bit = DrawMask::bit(31);
PStatCollector PandaNode::_reset_prev_pcollector("App:Collisions:Reset");
@ -108,7 +108,12 @@ PandaNode::
pgraph_cat.debug()
<< "Destructing " << (void *)this << ", " << get_name() << "\n";
}
clear_dirty_prev_transform();
if (_dirty_prev_transform) {
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
do_clear_dirty_prev_transform();
}
// We shouldn't have any parents left by the time we destruct, or
// there's a refcount fault somewhere.
@ -155,6 +160,9 @@ PandaNode(const PandaNode &copy) :
_unexpected_change_flags = 0;
#endif // !NDEBUG
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
// Copy the other node's state.
{
CDReader copy_cdata(copy._cycler);
@ -163,7 +171,7 @@ PandaNode(const PandaNode &copy) :
cdata->_transform = copy_cdata->_transform;
cdata->_prev_transform = copy_cdata->_prev_transform;
if (cdata->_transform != cdata->_prev_transform) {
set_dirty_prev_transform();
do_set_dirty_prev_transform();
}
cdata->_effects = copy_cdata->_effects;
@ -1336,6 +1344,9 @@ set_effects(const RenderEffects *effects, Thread *current_thread) {
////////////////////////////////////////////////////////////////////
void PandaNode::
set_transform(const TransformState *transform, Thread *current_thread) {
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
// Apply this operation to the current stage as well as to all
// upstream stages.
bool any_changed = false;
@ -1348,7 +1359,7 @@ set_transform(const TransformState *transform, Thread *current_thread) {
if (pipeline_stage == 0) {
if (cdata->_transform != cdata->_prev_transform) {
set_dirty_prev_transform();
do_set_dirty_prev_transform();
}
}
}
@ -1372,6 +1383,9 @@ set_transform(const TransformState *transform, Thread *current_thread) {
////////////////////////////////////////////////////////////////////
void PandaNode::
set_prev_transform(const TransformState *transform, Thread *current_thread) {
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
// Apply this operation to the current stage as well as to all
// upstream stages.
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
@ -1379,9 +1393,9 @@ set_prev_transform(const TransformState *transform, Thread *current_thread) {
cdata->_prev_transform = transform;
if (pipeline_stage == 0) {
if (cdata->_transform != cdata->_prev_transform) {
set_dirty_prev_transform();
do_set_dirty_prev_transform();
} else {
clear_dirty_prev_transform();
do_clear_dirty_prev_transform();
}
}
}
@ -1399,9 +1413,12 @@ set_prev_transform(const TransformState *transform, Thread *current_thread) {
////////////////////////////////////////////////////////////////////
void PandaNode::
reset_prev_transform(Thread *current_thread) {
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
do_clear_dirty_prev_transform();
// Apply this operation to the current stage as well as to all
// upstream stages.
clear_dirty_prev_transform();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
@ -1800,6 +1817,9 @@ copy_all_properties(PandaNode *other) {
return;
}
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
bool any_transform_changed = false;
bool any_state_changed = false;
bool any_draw_mask_changed = false;
@ -1871,7 +1891,7 @@ copy_all_properties(PandaNode *other) {
if (pipeline_stage == 0) {
if (cdataw->_transform != cdataw->_prev_transform) {
set_dirty_prev_transform();
do_set_dirty_prev_transform();
}
}
}

View File

@ -416,8 +416,8 @@ private:
void fix_path_lengths(int pipeline_stage, Thread *current_thread);
void r_list_descendants(ostream &out, int indent_level) const;
INLINE void set_dirty_prev_transform();
INLINE void clear_dirty_prev_transform();
INLINE void do_set_dirty_prev_transform();
INLINE void do_clear_dirty_prev_transform();
public:
// This must be declared public so that VC6 will allow the nested

View File

@ -19,8 +19,9 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNodeChain::
PandaNodeChain() :
LinkedListNode(true) // This object is the root of a list of PandaNodes.
PandaNodeChain(const char *lock_name) :
LinkedListNode(true), // This object is the root of a list of PandaNodes.
_lock(lock_name)
{
}

View File

@ -30,7 +30,7 @@ class PandaNode;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_PGRAPH PandaNodeChain : private LinkedListNode {
public:
INLINE PandaNodeChain();
INLINE PandaNodeChain(const char *lock_name);
INLINE ~PandaNodeChain();
LightMutex _lock;