mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -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
|
||||
|
||||
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?
|
||||
nassertr(_cache_ref_count > 0, 0);
|
||||
|
||||
AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
|
||||
AtomicAdjust::dec(_cache_ref_count);
|
||||
return ReferenceCount::unref();
|
||||
}
|
||||
|
||||
@ -164,6 +164,19 @@ test_ref_count_integrity() const {
|
||||
#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
|
||||
* 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?
|
||||
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);
|
||||
|
||||
protected:
|
||||
INLINE void cache_ref_only() const;
|
||||
INLINE void cache_unref_only() const;
|
||||
bool do_test_ref_count_integrity() const;
|
||||
|
||||
private:
|
||||
AtomicAdjust::Integer _cache_ref_count;
|
||||
mutable AtomicAdjust::Integer _cache_ref_count;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
@ -35,4 +35,21 @@ unref() const {
|
||||
}
|
||||
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
|
||||
|
@ -49,6 +49,9 @@ PUBLISHED:
|
||||
virtual bool unref() const;
|
||||
INLINE void cache_ref() const;
|
||||
INLINE bool cache_unref() const;
|
||||
|
||||
public:
|
||||
void cache_ref_only() const;
|
||||
#endif // COW_THREADED
|
||||
|
||||
protected:
|
||||
|
@ -74,23 +74,58 @@ INLINE CopyOnWritePointer::
|
||||
*
|
||||
*/
|
||||
INLINE CopyOnWritePointer::
|
||||
CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT :
|
||||
_cow_object(move._cow_object)
|
||||
CopyOnWritePointer(CopyOnWritePointer &&from) NOEXCEPT :
|
||||
_cow_object(from._cow_object)
|
||||
{
|
||||
// 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::
|
||||
operator = (CopyOnWritePointer &&move) NOEXCEPT {
|
||||
operator = (CopyOnWritePointer &&from) NOEXCEPT {
|
||||
// Protect against self-move-assignment.
|
||||
if (move._cow_object != _cow_object) {
|
||||
if (from._cow_object != _cow_object) {
|
||||
CopyOnWriteObject *old_object = _cow_object;
|
||||
_cow_object = move._cow_object;
|
||||
move._cow_object = NULL;
|
||||
_cow_object = from._cow_object;
|
||||
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) {
|
||||
cache_unref_delete(old_object);
|
||||
@ -262,20 +297,60 @@ operator = (To *object) {
|
||||
*/
|
||||
template<class T>
|
||||
INLINE CopyOnWritePointerTo<T>::
|
||||
CopyOnWritePointerTo(CopyOnWritePointerTo<T> &&move) NOEXCEPT :
|
||||
CopyOnWritePointer((CopyOnWritePointer &&)move)
|
||||
CopyOnWritePointerTo(CopyOnWritePointerTo<T> &&from) NOEXCEPT :
|
||||
CopyOnWritePointer((CopyOnWritePointer &&)from)
|
||||
{
|
||||
}
|
||||
#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
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class T>
|
||||
INLINE void CopyOnWritePointerTo<T>::
|
||||
operator = (CopyOnWritePointerTo<T> &&move) NOEXCEPT {
|
||||
CopyOnWritePointer::operator = ((CopyOnWritePointer &&)move);
|
||||
operator = (CopyOnWritePointerTo<T> &&from) NOEXCEPT {
|
||||
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 // USE_MOVE_SEMANTICS
|
||||
|
@ -90,19 +90,17 @@ get_write_pointer() {
|
||||
}
|
||||
|
||||
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.
|
||||
if (!_cow_object->CachedTypedWritableReferenceCount::cache_unref()) {
|
||||
_cow_object->_lock_mutex.release();
|
||||
delete _cow_object;
|
||||
} else {
|
||||
_cow_object->_lock_mutex.release();
|
||||
}
|
||||
MutexHolder holder(new_object->_lock_mutex);
|
||||
_cow_object = new_object;
|
||||
_cow_object->cache_ref();
|
||||
_cow_object->CachedTypedWritableReferenceCount::cache_ref();
|
||||
_cow_object->_lock_status = CopyOnWriteObject::LS_locked_write;
|
||||
_cow_object->_locking_thread = current_thread;
|
||||
|
||||
return new_object;
|
||||
|
||||
} else if (_cow_object->get_cache_ref_count() > 1) {
|
||||
// No one else has it specifically read-locked, but there are other
|
||||
// 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();
|
||||
_cow_object->CachedTypedWritableReferenceCount::cache_unref();
|
||||
_cow_object->_lock_mutex.release();
|
||||
|
||||
// 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();
|
||||
}
|
||||
MutexHolder holder(new_object->_lock_mutex);
|
||||
_cow_object = new_object;
|
||||
_cow_object->cache_ref();
|
||||
_cow_object->CachedTypedWritableReferenceCount::cache_ref();
|
||||
_cow_object->_lock_status = CopyOnWriteObject::LS_locked_write;
|
||||
_cow_object->_locking_thread = current_thread;
|
||||
|
||||
return new_object;
|
||||
|
||||
} else {
|
||||
// No other thread has the pointer locked, and we're the only
|
||||
// CopyOnWritePointer with this object. We can safely write to it without
|
||||
|
@ -37,8 +37,10 @@ public:
|
||||
INLINE ~CopyOnWritePointer();
|
||||
|
||||
#ifdef USE_MOVE_SEMANTICS
|
||||
INLINE CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT;
|
||||
INLINE void operator = (CopyOnWritePointer &&move) NOEXCEPT;
|
||||
INLINE CopyOnWritePointer(CopyOnWritePointer &&from) NOEXCEPT;
|
||||
INLINE CopyOnWritePointer(PointerTo<CopyOnWriteObject> &&from) NOEXCEPT;
|
||||
INLINE void operator = (CopyOnWritePointer &&from) NOEXCEPT;
|
||||
INLINE void operator = (PointerTo<CopyOnWriteObject> &&from) NOEXCEPT;
|
||||
#endif
|
||||
|
||||
INLINE bool operator == (const CopyOnWritePointer &other) const;
|
||||
@ -61,7 +63,7 @@ public:
|
||||
INLINE bool test_ref_count_integrity() const;
|
||||
INLINE bool test_ref_count_nonzero() const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
CopyOnWriteObject *_cow_object;
|
||||
};
|
||||
|
||||
@ -84,8 +86,10 @@ public:
|
||||
INLINE void operator = (To *object);
|
||||
|
||||
#ifdef USE_MOVE_SEMANTICS
|
||||
INLINE CopyOnWritePointerTo(CopyOnWritePointerTo &&move) NOEXCEPT;
|
||||
INLINE void operator = (CopyOnWritePointerTo &&move) NOEXCEPT;
|
||||
INLINE CopyOnWritePointerTo(CopyOnWritePointerTo &&from) NOEXCEPT;
|
||||
INLINE CopyOnWritePointerTo(PointerTo<T> &&from) NOEXCEPT;
|
||||
INLINE void operator = (CopyOnWritePointerTo &&from) NOEXCEPT;
|
||||
INLINE void operator = (PointerTo<T> &&from) NOEXCEPT;
|
||||
#endif
|
||||
|
||||
#ifdef COW_THREADED
|
||||
|
Loading…
x
Reference in New Issue
Block a user