From 558f84a95f3baa8f2123fe2468dc7912cbedf04b Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 8 Sep 2016 22:52:57 +0200 Subject: [PATCH 1/6] Backport normalized() method to 1.9 branch --- doc/ReleaseNotes | 1 + panda/src/linmath/lpoint2_src.I | 12 ++++++++++++ panda/src/linmath/lpoint2_src.h | 1 + panda/src/linmath/lpoint3_src.I | 12 ++++++++++++ panda/src/linmath/lpoint3_src.h | 1 + panda/src/linmath/lpoint4_src.I | 13 +++++++++++++ panda/src/linmath/lpoint4_src.h | 1 + panda/src/linmath/lvecBase2_src.I | 16 ++++++++++++++++ panda/src/linmath/lvecBase2_src.h | 1 + panda/src/linmath/lvecBase3_src.I | 16 ++++++++++++++++ panda/src/linmath/lvecBase3_src.h | 1 + panda/src/linmath/lvecBase4_src.I | 16 ++++++++++++++++ panda/src/linmath/lvecBase4_src.h | 1 + panda/src/linmath/lvector2_src.I | 12 ++++++++++++ panda/src/linmath/lvector2_src.h | 1 + panda/src/linmath/lvector3_src.I | 13 +++++++++++++ panda/src/linmath/lvector3_src.h | 1 + panda/src/linmath/lvector4_src.I | 13 +++++++++++++ panda/src/linmath/lvector4_src.h | 1 + 19 files changed, 133 insertions(+) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index f3bebcc191..6320ff52a8 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -32,6 +32,7 @@ This issue fixes several bugs that were still found in 1.9.2. * Fix RAM caching of 2D texture arrays * Fix Ctrl+C interrupt propagation to runtime applications * Support for InvSphere, Box and Tube solids in bam2egg +* Add normalized() method to vectors ------------------------ RELEASE 1.9.2 ------------------------ diff --git a/panda/src/linmath/lpoint2_src.I b/panda/src/linmath/lpoint2_src.I index a3f27084f6..ef38d96a96 100644 --- a/panda/src/linmath/lpoint2_src.I +++ b/panda/src/linmath/lpoint2_src.I @@ -186,6 +186,18 @@ operator / (FLOATTYPE scalar) const { } #ifndef FLOATTYPE_IS_INT +//////////////////////////////////////////////////////////////////// +// Function: LPoint2::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LPoint2) FLOATNAME(LPoint2):: +normalized() const { + return FLOATNAME(LVecBase2)::normalized(); +} + //////////////////////////////////////////////////////////////////// // Function: LPoint2::project // Access: Published diff --git a/panda/src/linmath/lpoint2_src.h b/panda/src/linmath/lpoint2_src.h index 5347325800..f426f733ba 100644 --- a/panda/src/linmath/lpoint2_src.h +++ b/panda/src/linmath/lpoint2_src.h @@ -51,6 +51,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint2) operator / (FLOATTYPE scalar) const; #ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATNAME(LPoint2) normalized() const; INLINE_LINMATH FLOATNAME(LPoint2) project(const FLOATNAME(LVecBase2) &onto) const; #endif diff --git a/panda/src/linmath/lpoint3_src.I b/panda/src/linmath/lpoint3_src.I index 9f8143c7d7..21ff1be9f2 100644 --- a/panda/src/linmath/lpoint3_src.I +++ b/panda/src/linmath/lpoint3_src.I @@ -230,6 +230,18 @@ cross(const FLOATNAME(LVecBase3) &other) const { } #ifndef FLOATTYPE_IS_INT +//////////////////////////////////////////////////////////////////// +// Function: LPoint3::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LPoint3) FLOATNAME(LPoint3):: +normalized() const { + return FLOATNAME(LVecBase3)::normalized(); +} + //////////////////////////////////////////////////////////////////// // Function: LPoint3::project // Access: Published diff --git a/panda/src/linmath/lpoint3_src.h b/panda/src/linmath/lpoint3_src.h index e8645529ff..7cb4c4978e 100644 --- a/panda/src/linmath/lpoint3_src.h +++ b/panda/src/linmath/lpoint3_src.h @@ -61,6 +61,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint3) cross(const FLOATNAME(LVecBase3) &other) const; #ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATNAME(LPoint3) normalized() const; INLINE_LINMATH FLOATNAME(LPoint3) project(const FLOATNAME(LVecBase3) &onto) const; #endif diff --git a/panda/src/linmath/lpoint4_src.I b/panda/src/linmath/lpoint4_src.I index d1a7e7b3ab..5bbe378f58 100644 --- a/panda/src/linmath/lpoint4_src.I +++ b/panda/src/linmath/lpoint4_src.I @@ -217,6 +217,19 @@ operator / (FLOATTYPE scalar) const { } #ifndef FLOATTYPE_IS_INT + +//////////////////////////////////////////////////////////////////// +// Function: LPoint4::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LPoint4) FLOATNAME(LPoint4):: +normalized() const { + return FLOATNAME(LVecBase4)::normalized(); +} + //////////////////////////////////////////////////////////////////// // Function: LPoint4::project // Access: Published diff --git a/panda/src/linmath/lpoint4_src.h b/panda/src/linmath/lpoint4_src.h index 50eeb1ce5d..72c874035b 100644 --- a/panda/src/linmath/lpoint4_src.h +++ b/panda/src/linmath/lpoint4_src.h @@ -53,6 +53,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint4) operator / (FLOATTYPE scalar) const; #ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATNAME(LPoint4) normalized() const; INLINE_LINMATH FLOATNAME(LPoint4) project(const FLOATNAME(LVecBase4) &onto) const; #endif diff --git a/panda/src/linmath/lvecBase2_src.I b/panda/src/linmath/lvecBase2_src.I index b561cb0b7a..45cdf2d661 100644 --- a/panda/src/linmath/lvecBase2_src.I +++ b/panda/src/linmath/lvecBase2_src.I @@ -418,6 +418,22 @@ normalize() { return true; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase2) FLOATNAME(LVecBase2):: +normalized() const { + FLOATTYPE l2 = length_squared(); + if (l2 == (FLOATTYPE)0.0f) { + return FLOATNAME(LVecBase2)(0.0f); + } + return (*this) / csqrt(l2); +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase2::project // Access: Published diff --git a/panda/src/linmath/lvecBase2_src.h b/panda/src/linmath/lvecBase2_src.h index f1f6d125e0..4340a6a296 100644 --- a/panda/src/linmath/lvecBase2_src.h +++ b/panda/src/linmath/lvecBase2_src.h @@ -94,6 +94,7 @@ PUBLISHED: #ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATTYPE length() const; INLINE_LINMATH bool normalize(); + INLINE_LINMATH FLOATNAME(LVecBase2) normalized() const; INLINE_LINMATH FLOATNAME(LVecBase2) project(const FLOATNAME(LVecBase2) &onto) const; #endif diff --git a/panda/src/linmath/lvecBase3_src.I b/panda/src/linmath/lvecBase3_src.I index 13310a8af1..ef3c6b8d04 100644 --- a/panda/src/linmath/lvecBase3_src.I +++ b/panda/src/linmath/lvecBase3_src.I @@ -509,6 +509,22 @@ normalize() { return true; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase3) FLOATNAME(LVecBase3):: +normalized() const { + FLOATTYPE l2 = length_squared(); + if (l2 == (FLOATTYPE)0.0f) { + return FLOATNAME(LVecBase3)(0.0f); + } + return (*this) / csqrt(l2); +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase3::project // Access: Published diff --git a/panda/src/linmath/lvecBase3_src.h b/panda/src/linmath/lvecBase3_src.h index 1a4ec5ce97..b51e7c42e4 100644 --- a/panda/src/linmath/lvecBase3_src.h +++ b/panda/src/linmath/lvecBase3_src.h @@ -103,6 +103,7 @@ PUBLISHED: #ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATTYPE length() const; INLINE_LINMATH bool normalize(); + INLINE_LINMATH FLOATNAME(LVecBase3) normalized() const; INLINE_LINMATH FLOATNAME(LVecBase3) project(const FLOATNAME(LVecBase3) &onto) const; #endif diff --git a/panda/src/linmath/lvecBase4_src.I b/panda/src/linmath/lvecBase4_src.I index 5b42095e93..e1b76ccf92 100644 --- a/panda/src/linmath/lvecBase4_src.I +++ b/panda/src/linmath/lvecBase4_src.I @@ -559,6 +559,22 @@ normalize() { return true; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase4) FLOATNAME(LVecBase4):: +normalized() const { + FLOATTYPE l2 = length_squared(); + if (l2 == (FLOATTYPE)0.0f) { + return FLOATNAME(LVecBase4)(0.0f); + } + return (*this) / csqrt(l2); +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase4::project // Access: Published diff --git a/panda/src/linmath/lvecBase4_src.h b/panda/src/linmath/lvecBase4_src.h index 988d31b859..d9511fee0e 100644 --- a/panda/src/linmath/lvecBase4_src.h +++ b/panda/src/linmath/lvecBase4_src.h @@ -113,6 +113,7 @@ PUBLISHED: #ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATTYPE length() const; INLINE_LINMATH bool normalize(); + INLINE_LINMATH FLOATNAME(LVecBase4) normalized() const; INLINE_LINMATH FLOATNAME(LVecBase4) project(const FLOATNAME(LVecBase4) &onto) const; #endif diff --git a/panda/src/linmath/lvector2_src.I b/panda/src/linmath/lvector2_src.I index 45c7975fea..def84b52a1 100644 --- a/panda/src/linmath/lvector2_src.I +++ b/panda/src/linmath/lvector2_src.I @@ -175,6 +175,18 @@ operator / (FLOATTYPE scalar) const { } #ifndef FLOATTYPE_IS_INT +//////////////////////////////////////////////////////////////////// +// Function: LVector2::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVector2) FLOATNAME(LVector2):: +normalized() const { + return FLOATNAME(LVecBase2)::normalized(); +} + //////////////////////////////////////////////////////////////////// // Function: LVector2::project // Access: Published diff --git a/panda/src/linmath/lvector2_src.h b/panda/src/linmath/lvector2_src.h index 2ee50d34ab..c63e11b2aa 100644 --- a/panda/src/linmath/lvector2_src.h +++ b/panda/src/linmath/lvector2_src.h @@ -44,6 +44,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector2) operator / (FLOATTYPE scalar) const; #ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATNAME(LVector2) normalized() const; INLINE_LINMATH FLOATNAME(LVector2) project(const FLOATNAME(LVecBase2) &onto) const; INLINE_LINMATH FLOATTYPE signed_angle_rad(const FLOATNAME(LVector2) &other) const; INLINE_LINMATH FLOATTYPE signed_angle_deg(const FLOATNAME(LVector2) &other) const; diff --git a/panda/src/linmath/lvector3_src.I b/panda/src/linmath/lvector3_src.I index 318d32d2c9..e04e4531f0 100644 --- a/panda/src/linmath/lvector3_src.I +++ b/panda/src/linmath/lvector3_src.I @@ -220,6 +220,19 @@ cross(const FLOATNAME(LVecBase3) &other) const { } #ifndef FLOATTYPE_IS_INT + +//////////////////////////////////////////////////////////////////// +// Function: LVector3::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVector3) FLOATNAME(LVector3):: +normalized() const { + return FLOATNAME(LVecBase3)::normalized(); +} + //////////////////////////////////////////////////////////////////// // Function: LVector3::project // Access: Published diff --git a/panda/src/linmath/lvector3_src.h b/panda/src/linmath/lvector3_src.h index 7e0dd196bb..4d0a6f69c8 100644 --- a/panda/src/linmath/lvector3_src.h +++ b/panda/src/linmath/lvector3_src.h @@ -55,6 +55,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector3) cross(const FLOATNAME(LVecBase3) &other) const; #ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATNAME(LVector3) normalized() const; INLINE_LINMATH FLOATNAME(LVector3) project(const FLOATNAME(LVecBase3) &onto) const; INLINE_LINMATH FLOATTYPE angle_rad(const FLOATNAME(LVector3) &other) const; INLINE_LINMATH FLOATTYPE angle_deg(const FLOATNAME(LVector3) &other) const; diff --git a/panda/src/linmath/lvector4_src.I b/panda/src/linmath/lvector4_src.I index 78333268f4..0423b63cf7 100644 --- a/panda/src/linmath/lvector4_src.I +++ b/panda/src/linmath/lvector4_src.I @@ -207,6 +207,19 @@ operator / (FLOATTYPE scalar) const { } #ifndef FLOATTYPE_IS_INT + +//////////////////////////////////////////////////////////////////// +// Function: LVector4::normalized +// Access: Published +// Description: Normalizes the vector and returns the normalized +// vector as a copy. If the vector was a zero-length +// vector, a zero length vector will be returned. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVector4) FLOATNAME(LVector4):: +normalized() const { + return FLOATNAME(LVecBase4)::normalized(); +} + //////////////////////////////////////////////////////////////////// // Function: LVector4::project // Access: Published diff --git a/panda/src/linmath/lvector4_src.h b/panda/src/linmath/lvector4_src.h index ebf87429f6..5f149d92fe 100644 --- a/panda/src/linmath/lvector4_src.h +++ b/panda/src/linmath/lvector4_src.h @@ -47,6 +47,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector4) operator / (FLOATTYPE scalar) const; #ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATNAME(LVector4) normalized() const; INLINE_LINMATH FLOATNAME(LVector4) project(const FLOATNAME(LVecBase4) &onto) const; #endif From a0b2a981783a63fb91e71fa9599a27d7d7b5b7cd Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 11 Sep 2016 12:23:28 +0200 Subject: [PATCH 2/6] Fix crash that happens when using OdeTriMeshData incorrectly --- panda/src/ode/odeTriMeshData.cxx | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/panda/src/ode/odeTriMeshData.cxx b/panda/src/ode/odeTriMeshData.cxx index cdaed29ae6..a58ed87d74 100644 --- a/panda/src/ode/odeTriMeshData.cxx +++ b/panda/src/ode/odeTriMeshData.cxx @@ -55,25 +55,30 @@ print_data(const string &marker) { void OdeTriMeshData:: remove_data(OdeTriMeshData *data) { - odetrimeshdata_cat.debug() << get_class_type() << "::remove_data(" << data->get_id() << ")" << "\n"; - nassertv(_tri_mesh_data_map != (TriMeshDataMap *)NULL); + if (odetrimeshdata_cat.is_debug()) { + odetrimeshdata_cat.debug() + << get_class_type() << "::remove_data(" << data->get_id() << ")" << "\n"; + } + if (_tri_mesh_data_map == (TriMeshDataMap *)NULL) { + return; + } + TriMeshDataMap::iterator iter; - for (iter = _tri_mesh_data_map->begin(); iter != _tri_mesh_data_map->end(); ++iter) { - if ( iter->second == data ) { + if (iter->second == data) { break; } } - + while (iter != _tri_mesh_data_map->end()) { _tri_mesh_data_map->erase(iter); - + for (iter = _tri_mesh_data_map->begin(); iter != _tri_mesh_data_map->end(); ++iter) { - if ( iter->second == data ) { + if (iter->second == data) { break; } } @@ -154,8 +159,13 @@ operator = (const OdeTriMeshData &other) { void OdeTriMeshData:: process_model(const NodePath& model, bool &use_normals) { // TODO: assert if _vertices is something other than 0. - ostream &out = odetrimeshdata_cat.debug(); - out << "process_model(" << model << ")" << "\n"; + if (odetrimeshdata_cat.is_debug()) { + odetrimeshdata_cat.debug() + << "process_model(" << model << ")" << "\n"; + } + if (model.is_empty()) { + return; + } NodePathCollection geomNodePaths = model.find_all_matches("**/+GeomNode"); if (model.node()->get_type() == GeomNode::get_class_type()) { From 977228c493d6c5b4541b871546ea203e6738dd0b Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 11 Sep 2016 19:44:46 +0200 Subject: [PATCH 3/6] Improve memory consumption of packp3d/ppackage by not caching models/textures in RAM Fixes https://bugs.launchpad.net/panda3d/+bug/1609882 --- direct/src/p3d/Packager.py | 12 +++++++++++- direct/src/p3d/panda3d.pdef | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index 27ff972e63..e317e9a331 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -1853,7 +1853,7 @@ class Packager: def addEggFile(self, file): # Precompile egg files to bam's. - np = self.packager.loader.loadModel(file.filename) + np = self.packager.loader.loadModel(file.filename, self.packager.loaderOptions) if not np: raise StandardError, 'Could not read egg file %s' % (file.filename) @@ -1867,6 +1867,8 @@ class Packager: if not bamFile.openRead(file.filename): raise StandardError, 'Could not read bam file %s' % (file.filename) + bamFile.getReader().setLoaderOptions(self.packager.loaderOptions) + if not bamFile.resolve(): raise StandardError, 'Could not resolve bam file %s' % (file.filename) @@ -2497,6 +2499,14 @@ class Packager: self.sfxManagerList = None self.musicManager = None + # These options will be used when loading models and textures. By + # default we don't load textures beyond the header and don't store + # models in the RAM cache in order to conserve on memory usage. + opts = LoaderOptions() + opts.setFlags(opts.getFlags() | LoaderOptions.LFNoRamCache) + opts.setTextureFlags(opts.getTextureFlags() & ~LoaderOptions.TFPreload) + self.loaderOptions = opts + # This is filled in during readPackageDef(). self.packageList = [] diff --git a/direct/src/p3d/panda3d.pdef b/direct/src/p3d/panda3d.pdef index 6e19a54415..ea9b43e59e 100644 --- a/direct/src/p3d/panda3d.pdef +++ b/direct/src/p3d/panda3d.pdef @@ -433,6 +433,8 @@ class packp3d(p3d): mainModule('direct.p3d.packp3d') + file('packp3d.prc', extract = True, text = "preload-textures false") + class ppackage(p3d): # As above, a packaging utility. This is the fully-general ppackage @@ -446,6 +448,8 @@ class ppackage(p3d): mainModule('direct.p3d.ppackage') + file('ppackage.prc', extract = True, text = "preload-textures false") + class ppatcher(p3d): # A handy utility to go along with ppackage. This builds From 3ce808c705f5621a9eb32b8711347960e75e69c7 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 11 Sep 2016 20:28:33 +0200 Subject: [PATCH 4/6] Fix in-place asyncFlattenStrong --- direct/src/showbase/Loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index adee7fbe2b..f1cf5b91e5 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -915,7 +915,7 @@ class Loader(DirectObject): orig = origModelList[i].node() flat = models[i].node() orig.copyAllProperties(flat) - orig.replaceNode(flat) + flat.replaceNode(orig) if callback: if gotList: From 632ad5e3eff9a00503d964231fa5be68f0ee92a9 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 11 Sep 2016 22:14:18 +0200 Subject: [PATCH 5/6] Acquire mutex in cache_unref() - fixes race cond in async flatten --- panda/src/putil/copyOnWriteObject.I | 11 +++++++++ panda/src/putil/copyOnWriteObject.h | 1 + panda/src/putil/copyOnWritePointer.cxx | 31 +++++++++++++++++++++----- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/panda/src/putil/copyOnWriteObject.I b/panda/src/putil/copyOnWriteObject.I index 3ad239c47a..ee0d5a01b7 100644 --- a/panda/src/putil/copyOnWriteObject.I +++ b/panda/src/putil/copyOnWriteObject.I @@ -83,6 +83,17 @@ cache_ref() const { MutexHolder holder(_lock_mutex); CachedTypedWritableReferenceCount::cache_ref(); } + +//////////////////////////////////////////////////////////////////// +// Function: CopyOnWriteObject::cache_unref +// Access: Published +// Description: See CachedTypedWritableReferenceCount::cache_unref(). +//////////////////////////////////////////////////////////////////// +INLINE bool CopyOnWriteObject:: +cache_unref() const { + MutexHolder holder(_lock_mutex); + return CachedTypedWritableReferenceCount::cache_unref(); +} #endif // COW_THREADED //////////////////////////////////////////////////////////////////// diff --git a/panda/src/putil/copyOnWriteObject.h b/panda/src/putil/copyOnWriteObject.h index e7d1ca7be9..633bbfc08a 100644 --- a/panda/src/putil/copyOnWriteObject.h +++ b/panda/src/putil/copyOnWriteObject.h @@ -51,6 +51,7 @@ PUBLISHED: #ifdef COW_THREADED virtual bool unref() const; INLINE void cache_ref() const; + INLINE bool cache_unref() const; #endif // COW_THREADED protected: diff --git a/panda/src/putil/copyOnWritePointer.cxx b/panda/src/putil/copyOnWritePointer.cxx index 38ba2d63a5..c323cb76c0 100644 --- a/panda/src/putil/copyOnWritePointer.cxx +++ b/panda/src/putil/copyOnWritePointer.cxx @@ -13,7 +13,6 @@ //////////////////////////////////////////////////////////////////// #include "copyOnWritePointer.h" -#include "mutexHolder.h" #include "config_util.h" #include "config_pipeline.h" @@ -78,7 +77,7 @@ get_write_pointer() { Thread *current_thread = Thread::get_current_thread(); - MutexHolder holder(_cow_object->_lock_mutex); + _cow_object->_lock_mutex.acquire(); while (_cow_object->_lock_status == CopyOnWriteObject::LS_locked_write && _cow_object->_locking_thread != current_thread) { if (util_cat.is_debug()) { @@ -98,10 +97,20 @@ get_write_pointer() { << "Making copy of " << _cow_object->get_type() << " because it is locked in read mode.\n"; } + PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy(); - cache_unref_delete(_cow_object); + + // We can't call cache_unref_delete, because we hold the lock. + if (!_cow_object->CachedTypedWritableReferenceCount::cache_unref()) { + _cow_object->_lock_mutex.release(); + delete _cow_object; + } else { + _cow_object->_lock_mutex.release(); + } _cow_object = new_object; _cow_object->cache_ref(); + _cow_object->_lock_status = CopyOnWriteObject::LS_locked_write; + _cow_object->_locking_thread = current_thread; } else if (_cow_object->get_cache_ref_count() > 1) { // No one else has it specifically read-locked, but there are @@ -115,9 +124,18 @@ get_write_pointer() { } PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy(); - cache_unref_delete(_cow_object); + + // We can't call cache_unref_delete, because we hold the lock. + if (!_cow_object->CachedTypedWritableReferenceCount::cache_unref()) { + _cow_object->_lock_mutex.release(); + delete _cow_object; + } else { + _cow_object->_lock_mutex.release(); + } _cow_object = new_object; _cow_object->cache_ref(); + _cow_object->_lock_status = CopyOnWriteObject::LS_locked_write; + _cow_object->_locking_thread = current_thread; } else { // No other thread has the pointer locked, and we're the only @@ -127,9 +145,10 @@ get_write_pointer() { // We can't assert that there are no outstanding ordinary // references to it, though, since the creator of the object might // have saved himself a reference. + _cow_object->_lock_status = CopyOnWriteObject::LS_locked_write; + _cow_object->_locking_thread = current_thread; + _cow_object->_lock_mutex.release(); } - _cow_object->_lock_status = CopyOnWriteObject::LS_locked_write; - _cow_object->_locking_thread = current_thread; return _cow_object; } From 18085a7cb1abba76dbb4ffd0d5206b9dea40f7af Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 12 Sep 2016 00:38:18 +0200 Subject: [PATCH 6/6] Update ReleaseNotes --- doc/ReleaseNotes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 6320ff52a8..37f755d200 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -6,6 +6,7 @@ This issue fixes several bugs that were still found in 1.9.2. * Fix crash using wx/tkinter on Mac as long as want-wx/tk is set * Fix loading models from 'models' package with models/ prefix * Fix random crashes in task system +* Fix various race conditions causing threading issues * Fix memory leaks in BulletTriangleMesh * Fix loading old models with MovingPart * Improve performance of CPU vertex animation somewhat @@ -26,13 +27,13 @@ This issue fixes several bugs that were still found in 1.9.2. * Fix issues with certain Cg shader inputs in DX9 * Support uint8 index buffers in DX9 * Fix occasional frame lag when loading a big model asynchronously -* Fix race condition reading string config var * Fix interrogate parsing issue with "const static" * Add back missing libp3pystub.a to Mac OS X SDK * Fix RAM caching of 2D texture arrays * Fix Ctrl+C interrupt propagation to runtime applications * Support for InvSphere, Box and Tube solids in bam2egg * Add normalized() method to vectors +* asyncFlattenStrong with inPlace=True caused node to disappear ------------------------ RELEASE 1.9.2 ------------------------