From 7c14d1872a23f429f2f7d4f22c804ba400923f68 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 4 Feb 2015 00:06:14 +0100 Subject: [PATCH] Fix race condition when manipulating node transform in thread (LP #1417715) --- panda/src/pgraph/nodePath.cxx | 92 +++++++++++++++++------------------ panda/src/pgraph/pandaNode.I | 20 ++++---- panda/src/pgraph/pandaNode.h | 14 +++--- 3 files changed, 63 insertions(+), 63 deletions(-) diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 051dd2b3ef..ef6a626906 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -1714,21 +1714,21 @@ set_hpr(const NodePath &other, const LVecBase3 &hpr) { CPT(TransformState) rel_transform = get_transform(other); nassertv(rel_transform->has_hpr()); - CPT(TransformState) orig_transform = get_transform(); - if (orig_transform->has_components()) { + CPT(TransformState) transform = get_transform(); + if (transform->has_components()) { // If we had a componentwise transform before we started, we // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. - const LVecBase3 &orig_pos = orig_transform->get_pos(); - const LVecBase3 &orig_scale = orig_transform->get_scale(); - const LVecBase3 &orig_shear = orig_transform->get_shear(); + const LVecBase3 &orig_pos = transform->get_pos(); + const LVecBase3 &orig_scale = transform->get_scale(); + const LVecBase3 &orig_shear = transform->get_shear(); set_transform(other, rel_transform->set_hpr(hpr)); - const TransformState *new_transform = get_transform(); - if (new_transform->has_components()) { + transform = get_transform(); + if (transform->has_components()) { set_transform(TransformState::make_pos_hpr_scale_shear - (orig_pos, new_transform->get_hpr(), orig_scale, orig_shear)); + (orig_pos, transform->get_hpr(), orig_scale, orig_shear)); } } else { @@ -1787,21 +1787,21 @@ set_quat(const NodePath &other, const LQuaternion &quat) { nassertv_always(!is_empty()); CPT(TransformState) rel_transform = get_transform(other); - CPT(TransformState) orig_transform = get_transform(); - if (orig_transform->has_components()) { + CPT(TransformState) transform = get_transform(); + if (transform->has_components()) { // If we had a componentwise transform before we started, we // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. - const LVecBase3 &orig_pos = orig_transform->get_pos(); - const LVecBase3 &orig_scale = orig_transform->get_scale(); - const LVecBase3 &orig_shear = orig_transform->get_shear(); + const LVecBase3 &orig_pos = transform->get_pos(); + const LVecBase3 &orig_scale = transform->get_scale(); + const LVecBase3 &orig_shear = transform->get_shear(); set_transform(other, rel_transform->set_quat(quat)); - const TransformState *new_transform = get_transform(); - if (new_transform->has_components()) { + transform = get_transform(); + if (transform->has_components()) { set_transform(TransformState::make_pos_quat_scale_shear - (orig_pos, new_transform->get_quat(), orig_scale, orig_shear)); + (orig_pos, transform->get_quat(), orig_scale, orig_shear)); } } else { @@ -1835,21 +1835,21 @@ set_scale(const NodePath &other, const LVecBase3 &scale) { nassertv_always(!is_empty()); CPT(TransformState) rel_transform = get_transform(other); - CPT(TransformState) orig_transform = get_transform(); - if (orig_transform->has_components()) { + CPT(TransformState) transform = get_transform(); + if (transform->has_components()) { // If we had a componentwise transform before we started, we // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. - const LVecBase3 &orig_pos = orig_transform->get_pos(); - const LVecBase3 &orig_hpr = orig_transform->get_hpr(); - const LVecBase3 &orig_shear = orig_transform->get_shear(); + const LVecBase3 &orig_pos = transform->get_pos(); + const LVecBase3 &orig_hpr = transform->get_hpr(); + const LVecBase3 &orig_shear = transform->get_shear(); set_transform(other, rel_transform->set_scale(scale)); - const TransformState *new_transform = get_transform(); - if (new_transform->has_components()) { + transform = get_transform(); + if (transform->has_components()) { set_transform(TransformState::make_pos_hpr_scale_shear - (orig_pos, orig_hpr, new_transform->get_scale(), orig_shear)); + (orig_pos, orig_hpr, transform->get_scale(), orig_shear)); } } else { @@ -1907,21 +1907,21 @@ set_shear(const NodePath &other, const LVecBase3 &shear) { nassertv_always(!is_empty()); CPT(TransformState) rel_transform = get_transform(other); - CPT(TransformState) orig_transform = get_transform(); - if (orig_transform->has_components()) { + CPT(TransformState) transform = get_transform(); + if (transform->has_components()) { // If we had a componentwise transform before we started, we // should be careful to preserve the other three components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. - const LVecBase3 &orig_pos = orig_transform->get_pos(); - const LVecBase3 &orig_hpr = orig_transform->get_hpr(); - const LVecBase3 &orig_scale = orig_transform->get_scale(); + const LVecBase3 &orig_pos = transform->get_pos(); + const LVecBase3 &orig_hpr = transform->get_hpr(); + const LVecBase3 &orig_scale = transform->get_scale(); set_transform(other, rel_transform->set_shear(shear)); - const TransformState *new_transform = get_transform(); - if (new_transform->has_components()) { + transform = get_transform(); + if (transform->has_components()) { set_transform(TransformState::make_pos_hpr_scale_shear - (orig_pos, orig_hpr, orig_scale, new_transform->get_shear())); + (orig_pos, orig_hpr, orig_scale, transform->get_shear())); } } else { @@ -1980,20 +1980,20 @@ set_pos_hpr(const NodePath &other, const LVecBase3 &pos, nassertv_always(!is_empty()); CPT(TransformState) rel_transform = get_transform(other); - CPT(TransformState) orig_transform = get_transform(); - if (orig_transform->has_components()) { + CPT(TransformState) transform = get_transform(); + if (transform->has_components()) { // If we had a componentwise transform before we started, we // should be careful to preserve the other two components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. - const LVecBase3 &orig_scale = orig_transform->get_scale(); - const LVecBase3 &orig_shear = orig_transform->get_shear(); + const LVecBase3 &orig_scale = transform->get_scale(); + const LVecBase3 &orig_shear = transform->get_shear(); set_transform(other, TransformState::make_pos_hpr_scale_shear (pos, hpr, rel_transform->get_scale(), rel_transform->get_shear())); - const TransformState *new_transform = get_transform(); - if (new_transform->has_components()) { - set_pos_hpr_scale_shear(new_transform->get_pos(), new_transform->get_hpr(), + transform = get_transform(); + if (transform->has_components()) { + set_pos_hpr_scale_shear(transform->get_pos(), transform->get_hpr(), orig_scale, orig_shear); } @@ -2018,20 +2018,20 @@ set_pos_quat(const NodePath &other, const LVecBase3 &pos, nassertv_always(!is_empty()); CPT(TransformState) rel_transform = get_transform(other); - CPT(TransformState) orig_transform = get_transform(); - if (orig_transform->has_components()) { + CPT(TransformState) transform = get_transform(); + if (transform->has_components()) { // If we had a componentwise transform before we started, we // should be careful to preserve the other two components. We // wouldn't need to do this, except for the possibility of // numerical error or decompose ambiguity. - const LVecBase3 &orig_scale = orig_transform->get_scale(); - const LVecBase3 &orig_shear = orig_transform->get_shear(); + const LVecBase3 &orig_scale = transform->get_scale(); + const LVecBase3 &orig_shear = transform->get_shear(); set_transform(other, TransformState::make_pos_quat_scale_shear (pos, quat, rel_transform->get_scale(), rel_transform->get_shear())); - const TransformState *new_transform = get_transform(); - if (new_transform->has_components()) { - set_pos_quat_scale_shear(new_transform->get_pos(), new_transform->get_quat(), + transform = get_transform(); + if (transform->has_components()) { + set_pos_quat_scale_shear(transform->get_pos(), transform->get_quat(), orig_scale, orig_shear); } diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index 83dc54ba31..162f08e03b 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -231,7 +231,7 @@ find_stashed(PandaNode *node, Thread *current_thread) const { // level, and has nothing to do with what render // attributes may be inherited from parent nodes. //////////////////////////////////////////////////////////////////// -INLINE const RenderAttrib *PandaNode:: +INLINE CPT(RenderAttrib) PandaNode:: get_attrib(TypeHandle type) const { CDReader cdata(_cycler); return cdata->_state->get_attrib(type); @@ -246,7 +246,7 @@ get_attrib(TypeHandle type) const { // level, and has nothing to do with what render // attributes may be inherited from parent nodes. //////////////////////////////////////////////////////////////////// -INLINE const RenderAttrib *PandaNode:: +INLINE CPT(RenderAttrib) PandaNode:: get_attrib(int slot) const { CDReader cdata(_cycler); return cdata->_state->get_attrib(slot); @@ -299,7 +299,7 @@ clear_attrib(TypeHandle type) { // Description: Returns the render effect of the indicated type, // if it is defined on the node, or NULL if it is not. //////////////////////////////////////////////////////////////////// -INLINE const RenderEffect *PandaNode:: +INLINE CPT(RenderEffect) PandaNode:: get_effect(TypeHandle type) const { CDReader cdata(_cycler); int index = cdata->_effects->find_effect(type); @@ -332,10 +332,10 @@ has_effect(TypeHandle type) const { // particular node, and has nothing to do with state // that might be inherited from above. //////////////////////////////////////////////////////////////////// -INLINE const RenderState *PandaNode:: +INLINE CPT(RenderState) PandaNode:: get_state(Thread *current_thread) const { CDReader cdata(_cycler, current_thread); - return cdata->_state; + return cdata->_state.p(); } //////////////////////////////////////////////////////////////////// @@ -357,7 +357,7 @@ clear_state(Thread *current_thread) { // Description: Returns the complete RenderEffects that will be // applied to this node. //////////////////////////////////////////////////////////////////// -INLINE const RenderEffects *PandaNode:: +INLINE CPT(RenderEffects) PandaNode:: get_effects(Thread *current_thread) const { CDReader cdata(_cycler, current_thread); return cdata->_effects; @@ -381,10 +381,10 @@ clear_effects(Thread *current_thread) { // the root, but simply the transform on this particular // node. //////////////////////////////////////////////////////////////////// -INLINE const TransformState *PandaNode:: +INLINE CPT(TransformState) PandaNode:: get_transform(Thread *current_thread) const { CDReader cdata(_cycler, current_thread); - return cdata->_transform; + return cdata->_transform.p(); } //////////////////////////////////////////////////////////////////// @@ -405,10 +405,10 @@ clear_transform(Thread *current_thread) { // node's "previous" position. See // set_prev_transform(). //////////////////////////////////////////////////////////////////// -const TransformState *PandaNode:: +INLINE CPT(TransformState) PandaNode:: get_prev_transform(Thread *current_thread) const { CDReader cdata(_cycler, current_thread); - return cdata->_prev_transform; + return cdata->_prev_transform.p(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index 0a1c60d491..c1719a7658 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -163,32 +163,32 @@ PUBLISHED: void copy_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread()); void set_attrib(const RenderAttrib *attrib, int override = 0); - INLINE const RenderAttrib *get_attrib(TypeHandle type) const; - INLINE const RenderAttrib *get_attrib(int slot) const; + INLINE CPT(RenderAttrib) get_attrib(TypeHandle type) const; + INLINE CPT(RenderAttrib) get_attrib(int slot) const; INLINE bool has_attrib(TypeHandle type) const; INLINE bool has_attrib(int slot) const; INLINE void clear_attrib(TypeHandle type); void clear_attrib(int slot); void set_effect(const RenderEffect *effect); - INLINE const RenderEffect *get_effect(TypeHandle type) const; + INLINE CPT(RenderEffect) get_effect(TypeHandle type) const; INLINE bool has_effect(TypeHandle type) const; void clear_effect(TypeHandle type); void set_state(const RenderState *state, Thread *current_thread = Thread::get_current_thread()); - INLINE const RenderState *get_state(Thread *current_thread = Thread::get_current_thread()) const; + INLINE CPT(RenderState) get_state(Thread *current_thread = Thread::get_current_thread()) const; INLINE void clear_state(Thread *current_thread = Thread::get_current_thread()); void set_effects(const RenderEffects *effects, Thread *current_thread = Thread::get_current_thread()); - INLINE const RenderEffects *get_effects(Thread *current_thread = Thread::get_current_thread()) const; + INLINE CPT(RenderEffects) get_effects(Thread *current_thread = Thread::get_current_thread()) const; INLINE void clear_effects(Thread *current_thread = Thread::get_current_thread()); void set_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread()); - INLINE const TransformState *get_transform(Thread *current_thread = Thread::get_current_thread()) const; + INLINE CPT(TransformState) get_transform(Thread *current_thread = Thread::get_current_thread()) const; INLINE void clear_transform(Thread *current_thread = Thread::get_current_thread()); void set_prev_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread()); - INLINE const TransformState *get_prev_transform(Thread *current_thread = Thread::get_current_thread()) const; + INLINE CPT(TransformState) get_prev_transform(Thread *current_thread = Thread::get_current_thread()) const; void reset_prev_transform(Thread *current_thread = Thread::get_current_thread()); INLINE bool has_dirty_prev_transform() const; static void reset_all_prev_transform(Thread *current_thread = Thread::get_current_thread());