mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
COW performance tweaks; also somehow fixes Bullet soft body issue
This commit is contained in:
parent
9eb04a533d
commit
b21e8fdf32
@ -126,7 +126,7 @@ cache_ref() const {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ref();
|
ref();
|
||||||
AtomicAdjust::inc(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
|
AtomicAdjust::inc(_cache_ref_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,7 +147,7 @@ cache_unref() const {
|
|||||||
// you can't use PointerTo's?
|
// you can't use PointerTo's?
|
||||||
nassertr(_cache_ref_count > 0, 0);
|
nassertr(_cache_ref_count > 0, 0);
|
||||||
|
|
||||||
AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
|
AtomicAdjust::dec(_cache_ref_count);
|
||||||
return ReferenceCount::unref();
|
return ReferenceCount::unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +164,19 @@ test_ref_count_integrity() const {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrements the cache reference count without affecting the normal reference
|
||||||
|
* count. Don't use this.
|
||||||
|
*/
|
||||||
|
INLINE void CachedTypedWritableReferenceCount::
|
||||||
|
cache_ref_only() const {
|
||||||
|
#ifdef _DEBUG
|
||||||
|
nassertv(test_ref_count_integrity());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
AtomicAdjust::inc(_cache_ref_count);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrements the cache reference count without affecting the normal reference
|
* Decrements the cache reference count without affecting the normal reference
|
||||||
* count. Intended to be called by derived classes only, presumably to
|
* count. Intended to be called by derived classes only, presumably to
|
||||||
@ -180,7 +193,7 @@ cache_unref_only() const {
|
|||||||
// you can't use PointerTo's?
|
// you can't use PointerTo's?
|
||||||
nassertv(_cache_ref_count > 0);
|
nassertv(_cache_ref_count > 0);
|
||||||
|
|
||||||
AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
|
AtomicAdjust::dec(_cache_ref_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,11 +47,12 @@ PUBLISHED:
|
|||||||
MAKE_PROPERTY(cache_ref_count, get_cache_ref_count);
|
MAKE_PROPERTY(cache_ref_count, get_cache_ref_count);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
INLINE void cache_ref_only() const;
|
||||||
INLINE void cache_unref_only() const;
|
INLINE void cache_unref_only() const;
|
||||||
bool do_test_ref_count_integrity() const;
|
bool do_test_ref_count_integrity() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AtomicAdjust::Integer _cache_ref_count;
|
mutable AtomicAdjust::Integer _cache_ref_count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
@ -35,4 +35,21 @@ unref() const {
|
|||||||
}
|
}
|
||||||
return is_zero;
|
return is_zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly increments the cache reference count only. Don't use this.
|
||||||
|
*
|
||||||
|
* In the case of a CopyOnWriteObject, when the reference count decrements
|
||||||
|
* down to the cache reference count, the object is implicitly unlocked.
|
||||||
|
*/
|
||||||
|
void CopyOnWriteObject::
|
||||||
|
cache_ref_only() const {
|
||||||
|
MutexHolder holder(_lock_mutex);
|
||||||
|
CachedTypedWritableReferenceCount::cache_ref_only();
|
||||||
|
if (get_ref_count() == get_cache_ref_count()) {
|
||||||
|
((CopyOnWriteObject *)this)->_lock_status = LS_unlocked;
|
||||||
|
((CopyOnWriteObject *)this)->_locking_thread = NULL;
|
||||||
|
((CopyOnWriteObject *)this)->_lock_cvar.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // COW_THREADED
|
#endif // COW_THREADED
|
||||||
|
@ -49,6 +49,9 @@ PUBLISHED:
|
|||||||
virtual bool unref() const;
|
virtual bool unref() const;
|
||||||
INLINE void cache_ref() const;
|
INLINE void cache_ref() const;
|
||||||
INLINE bool cache_unref() const;
|
INLINE bool cache_unref() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void cache_ref_only() const;
|
||||||
#endif // COW_THREADED
|
#endif // COW_THREADED
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -74,23 +74,58 @@ INLINE CopyOnWritePointer::
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
INLINE CopyOnWritePointer::
|
INLINE CopyOnWritePointer::
|
||||||
CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT :
|
CopyOnWritePointer(CopyOnWritePointer &&from) NOEXCEPT :
|
||||||
_cow_object(move._cow_object)
|
_cow_object(from._cow_object)
|
||||||
{
|
{
|
||||||
// Steal the other's reference count.
|
// Steal the other's reference count.
|
||||||
move._cow_object = (CopyOnWriteObject *)NULL;
|
from._cow_object = (CopyOnWriteObject *)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE CopyOnWritePointer::
|
||||||
|
CopyOnWritePointer(PointerTo<CopyOnWriteObject> &&from) NOEXCEPT :
|
||||||
|
_cow_object(from.p())
|
||||||
|
{
|
||||||
|
// Steal the other's reference count, but because it is a regular pointer,
|
||||||
|
// we do need to include the cache reference count.
|
||||||
|
if (_cow_object != (CopyOnWriteObject *)NULL) {
|
||||||
|
_cow_object->cache_ref_only();
|
||||||
|
}
|
||||||
|
from.cheat() = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
INLINE void CopyOnWritePointer::
|
INLINE void CopyOnWritePointer::
|
||||||
operator = (CopyOnWritePointer &&move) NOEXCEPT {
|
operator = (CopyOnWritePointer &&from) NOEXCEPT {
|
||||||
// Protect against self-move-assignment.
|
// Protect against self-move-assignment.
|
||||||
if (move._cow_object != _cow_object) {
|
if (from._cow_object != _cow_object) {
|
||||||
CopyOnWriteObject *old_object = _cow_object;
|
CopyOnWriteObject *old_object = _cow_object;
|
||||||
_cow_object = move._cow_object;
|
_cow_object = from._cow_object;
|
||||||
move._cow_object = NULL;
|
from._cow_object = NULL;
|
||||||
|
|
||||||
|
if (old_object != (CopyOnWriteObject *)NULL) {
|
||||||
|
cache_unref_delete(old_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE void CopyOnWritePointer::
|
||||||
|
operator = (PointerTo<CopyOnWriteObject> &&from) NOEXCEPT {
|
||||||
|
if (from.p() != _cow_object) {
|
||||||
|
CopyOnWriteObject *old_object = _cow_object;
|
||||||
|
|
||||||
|
// Steal the other's reference count, but because it is a regular pointer,
|
||||||
|
// we do need to include the cache reference count.
|
||||||
|
_cow_object = from.p();
|
||||||
|
_cow_object->cache_ref_only();
|
||||||
|
from.cheat() = NULL;
|
||||||
|
|
||||||
if (old_object != (CopyOnWriteObject *)NULL) {
|
if (old_object != (CopyOnWriteObject *)NULL) {
|
||||||
cache_unref_delete(old_object);
|
cache_unref_delete(old_object);
|
||||||
@ -262,20 +297,60 @@ operator = (To *object) {
|
|||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
INLINE CopyOnWritePointerTo<T>::
|
INLINE CopyOnWritePointerTo<T>::
|
||||||
CopyOnWritePointerTo(CopyOnWritePointerTo<T> &&move) NOEXCEPT :
|
CopyOnWritePointerTo(CopyOnWritePointerTo<T> &&from) NOEXCEPT :
|
||||||
CopyOnWritePointer((CopyOnWritePointer &&)move)
|
CopyOnWritePointer((CopyOnWritePointer &&)from)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif // CPPPARSER
|
#endif // CPPPARSER
|
||||||
|
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
INLINE CopyOnWritePointerTo<T>::
|
||||||
|
CopyOnWritePointerTo(PointerTo<T> &&from) NOEXCEPT {
|
||||||
|
// Steal the other's reference count, but because it is a regular pointer,
|
||||||
|
// we do need to include the cache reference count.
|
||||||
|
_cow_object = from.p();
|
||||||
|
if (_cow_object != (CopyOnWriteObject *)NULL) {
|
||||||
|
_cow_object->cache_ref_only();
|
||||||
|
}
|
||||||
|
from.cheat() = NULL;
|
||||||
|
}
|
||||||
|
#endif // CPPPARSER
|
||||||
|
|
||||||
#ifndef CPPPARSER
|
#ifndef CPPPARSER
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
INLINE void CopyOnWritePointerTo<T>::
|
INLINE void CopyOnWritePointerTo<T>::
|
||||||
operator = (CopyOnWritePointerTo<T> &&move) NOEXCEPT {
|
operator = (CopyOnWritePointerTo<T> &&from) NOEXCEPT {
|
||||||
CopyOnWritePointer::operator = ((CopyOnWritePointer &&)move);
|
CopyOnWritePointer::operator = ((CopyOnWritePointer &&)from);
|
||||||
|
}
|
||||||
|
#endif // CPPPARSER
|
||||||
|
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
INLINE void CopyOnWritePointerTo<T>::
|
||||||
|
operator = (PointerTo<T> &&from) NOEXCEPT {
|
||||||
|
if (from.p() != _cow_object) {
|
||||||
|
CopyOnWriteObject *old_object = _cow_object;
|
||||||
|
|
||||||
|
// Steal the other's reference count, but because it is a regular pointer,
|
||||||
|
// we do need to include the cache reference count.
|
||||||
|
_cow_object = from.p();
|
||||||
|
_cow_object->cache_ref_only();
|
||||||
|
from.cheat() = NULL;
|
||||||
|
|
||||||
|
if (old_object != (CopyOnWriteObject *)NULL) {
|
||||||
|
cache_unref_delete(old_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // CPPPARSER
|
#endif // CPPPARSER
|
||||||
#endif // USE_MOVE_SEMANTICS
|
#endif // USE_MOVE_SEMANTICS
|
||||||
|
@ -90,19 +90,17 @@ get_write_pointer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy();
|
PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy();
|
||||||
|
_cow_object->CachedTypedWritableReferenceCount::cache_unref();
|
||||||
|
_cow_object->_lock_mutex.release();
|
||||||
|
|
||||||
// We can't call cache_unref_delete, because we hold the lock.
|
MutexHolder holder(new_object->_lock_mutex);
|
||||||
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 = new_object;
|
||||||
_cow_object->cache_ref();
|
_cow_object->CachedTypedWritableReferenceCount::cache_ref();
|
||||||
_cow_object->_lock_status = CopyOnWriteObject::LS_locked_write;
|
_cow_object->_lock_status = CopyOnWriteObject::LS_locked_write;
|
||||||
_cow_object->_locking_thread = current_thread;
|
_cow_object->_locking_thread = current_thread;
|
||||||
|
|
||||||
|
return new_object;
|
||||||
|
|
||||||
} else if (_cow_object->get_cache_ref_count() > 1) {
|
} else if (_cow_object->get_cache_ref_count() > 1) {
|
||||||
// No one else has it specifically read-locked, but there are other
|
// No one else has it specifically read-locked, but there are other
|
||||||
// CopyOnWritePointers holding the same object, so we should make our own
|
// CopyOnWritePointers holding the same object, so we should make our own
|
||||||
@ -115,19 +113,17 @@ get_write_pointer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy();
|
PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy();
|
||||||
|
_cow_object->CachedTypedWritableReferenceCount::cache_unref();
|
||||||
|
_cow_object->_lock_mutex.release();
|
||||||
|
|
||||||
// We can't call cache_unref_delete, because we hold the lock.
|
MutexHolder holder(new_object->_lock_mutex);
|
||||||
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 = new_object;
|
||||||
_cow_object->cache_ref();
|
_cow_object->CachedTypedWritableReferenceCount::cache_ref();
|
||||||
_cow_object->_lock_status = CopyOnWriteObject::LS_locked_write;
|
_cow_object->_lock_status = CopyOnWriteObject::LS_locked_write;
|
||||||
_cow_object->_locking_thread = current_thread;
|
_cow_object->_locking_thread = current_thread;
|
||||||
|
|
||||||
|
return new_object;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// No other thread has the pointer locked, and we're the only
|
// No other thread has the pointer locked, and we're the only
|
||||||
// CopyOnWritePointer with this object. We can safely write to it without
|
// CopyOnWritePointer with this object. We can safely write to it without
|
||||||
|
@ -37,8 +37,10 @@ public:
|
|||||||
INLINE ~CopyOnWritePointer();
|
INLINE ~CopyOnWritePointer();
|
||||||
|
|
||||||
#ifdef USE_MOVE_SEMANTICS
|
#ifdef USE_MOVE_SEMANTICS
|
||||||
INLINE CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT;
|
INLINE CopyOnWritePointer(CopyOnWritePointer &&from) NOEXCEPT;
|
||||||
INLINE void operator = (CopyOnWritePointer &&move) NOEXCEPT;
|
INLINE CopyOnWritePointer(PointerTo<CopyOnWriteObject> &&from) NOEXCEPT;
|
||||||
|
INLINE void operator = (CopyOnWritePointer &&from) NOEXCEPT;
|
||||||
|
INLINE void operator = (PointerTo<CopyOnWriteObject> &&from) NOEXCEPT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
INLINE bool operator == (const CopyOnWritePointer &other) const;
|
INLINE bool operator == (const CopyOnWritePointer &other) const;
|
||||||
@ -61,7 +63,7 @@ public:
|
|||||||
INLINE bool test_ref_count_integrity() const;
|
INLINE bool test_ref_count_integrity() const;
|
||||||
INLINE bool test_ref_count_nonzero() const;
|
INLINE bool test_ref_count_nonzero() const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
CopyOnWriteObject *_cow_object;
|
CopyOnWriteObject *_cow_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,8 +86,10 @@ public:
|
|||||||
INLINE void operator = (To *object);
|
INLINE void operator = (To *object);
|
||||||
|
|
||||||
#ifdef USE_MOVE_SEMANTICS
|
#ifdef USE_MOVE_SEMANTICS
|
||||||
INLINE CopyOnWritePointerTo(CopyOnWritePointerTo &&move) NOEXCEPT;
|
INLINE CopyOnWritePointerTo(CopyOnWritePointerTo &&from) NOEXCEPT;
|
||||||
INLINE void operator = (CopyOnWritePointerTo &&move) NOEXCEPT;
|
INLINE CopyOnWritePointerTo(PointerTo<T> &&from) NOEXCEPT;
|
||||||
|
INLINE void operator = (CopyOnWritePointerTo &&from) NOEXCEPT;
|
||||||
|
INLINE void operator = (PointerTo<T> &&from) NOEXCEPT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef COW_THREADED
|
#ifdef COW_THREADED
|
||||||
|
Loading…
x
Reference in New Issue
Block a user