diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index 0a8e10a47..033fe67f8 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -52,12 +52,16 @@ inline bool operator _op_ (const U* o) const { \ } // --------------------------------------------------------------------------- -class ReferenceMover; -class ReferenceConverterBase { + +class ReferenceRenamer { +protected: + // destructor is purposedly not virtual so we avoid code overhead from + // subclasses; we have to make it protected to guarantee that it + // cannot be called from this base class (and to make strict compilers + // happy). + ~ReferenceRenamer() { } public: - virtual size_t getReferenceTypeSize() const = 0; - virtual void* getReferenceBase(void const*) const = 0; - inline virtual ~ReferenceConverterBase() { } + virtual void operator()(size_t i) const = 0; }; // --------------------------------------------------------------------------- @@ -143,11 +147,6 @@ protected: virtual bool onIncStrongAttempted(uint32_t flags, const void* id); virtual void onLastWeakRef(const void* id); -private: - friend class ReferenceMover; - static void moveReferences(void* d, void const* s, size_t n, - const ReferenceConverterBase& caster); - private: friend class weakref_type; class weakref_impl; @@ -155,6 +154,17 @@ private: RefBase(const RefBase& o); RefBase& operator=(const RefBase& o); +private: + friend class ReferenceMover; + + static void renameRefs(size_t n, const ReferenceRenamer& renamer); + + static void renameRefId(weakref_type* ref, + const void* old_id, const void* new_id); + + static void renameRefId(RefBase* ref, + const void* old_id, const void* new_id); + weakref_impl* const mRefs; }; @@ -185,8 +195,9 @@ protected: private: friend class ReferenceMover; - inline static void moveReferences(void* d, void const* s, size_t n, - const ReferenceConverterBase& caster) { } + inline static void renameRefs(size_t n, const ReferenceRenamer& renamer) { } + inline static void renameRefId(T* ref, + const void* old_id, const void* new_id) { } private: mutable volatile int32_t mCount; @@ -455,42 +466,48 @@ inline TextOutput& operator<<(TextOutput& to, const wp& val) // this class just serves as a namespace so TYPE::moveReferences can stay // private. - class ReferenceMover { - // StrongReferenceCast and WeakReferenceCast do the impedance matching - // between the generic (void*) implementation in Refbase and the strongly typed - // template specializations below. - - template - struct StrongReferenceCast : public ReferenceConverterBase { - virtual size_t getReferenceTypeSize() const { return sizeof( sp ); } - virtual void* getReferenceBase(void const* p) const { - sp const* sptr(reinterpret_cast const*>(p)); - return static_cast(sptr->get()); - } - }; - - template - struct WeakReferenceCast : public ReferenceConverterBase { - virtual size_t getReferenceTypeSize() const { return sizeof( wp ); } - virtual void* getReferenceBase(void const* p) const { - wp const* sptr(reinterpret_cast const*>(p)); - return static_cast(sptr->unsafe_get()); - } - }; - public: + // it would be nice if we could make sure no extra code is generated + // for sp or wp when TYPE is a descendant of RefBase: + // Using a sp override doesn't work; it's a bit like we wanted + // a template template... + template static inline void move_references(sp* d, sp const* s, size_t n) { + + class Renamer : public ReferenceRenamer { + sp* d; + sp const* s; + virtual void operator()(size_t i) const { + // The id are known to be the sp<>'s this pointer + TYPE::renameRefId(d[i].get(), &s[i], &d[i]); + } + public: + Renamer(sp* d, sp const* s) : s(s), d(d) { } + }; + memmove(d, s, n*sizeof(sp)); - StrongReferenceCast caster; - TYPE::moveReferences(d, s, n, caster); + TYPE::renameRefs(n, Renamer(d, s)); } + + template static inline void move_references(wp* d, wp const* s, size_t n) { + + class Renamer : public ReferenceRenamer { + wp* d; + wp const* s; + virtual void operator()(size_t i) const { + // The id are known to be the wp<>'s this pointer + TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]); + } + public: + Renamer(wp* d, wp const* s) : s(s), d(d) { } + }; + memmove(d, s, n*sizeof(wp)); - WeakReferenceCast caster; - TYPE::moveReferences(d, s, n, caster); + TYPE::renameRefs(n, Renamer(d, s)); } }; diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp index ef87131ad..abaf3c0ca 100644 --- a/libs/utils/RefBase.cpp +++ b/libs/utils/RefBase.cpp @@ -631,21 +631,27 @@ void RefBase::onLastWeakRef(const void* /*id*/) // --------------------------------------------------------------------------- -void RefBase::moveReferences(void* dst, void const* src, size_t n, - const ReferenceConverterBase& caster) -{ +void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) { #if DEBUG_REFS - const size_t itemSize = caster.getReferenceTypeSize(); for (size_t i=0 ; i(intptr_t(dst) + i*itemSize); - void const* s = reinterpret_cast(intptr_t(src) + i*itemSize); - RefBase* ref(reinterpret_cast(caster.getReferenceBase(d))); - ref->mRefs->renameStrongRefId(s, d); - ref->mRefs->renameWeakRefId(s, d); + renamer(i); } #endif } +void RefBase::renameRefId(weakref_type* ref, + const void* old_id, const void* new_id) { + weakref_impl* const impl = static_cast(ref); + impl->renameStrongRefId(old_id, new_id); + impl->renameWeakRefId(old_id, new_id); +} + +void RefBase::renameRefId(RefBase* ref, + const void* old_id, const void* new_id) { + ref->mRefs->renameStrongRefId(old_id, new_id); + ref->mRefs->renameWeakRefId(old_id, new_id); +} + // --------------------------------------------------------------------------- TextOutput& printStrongPointer(TextOutput& to, const void* val)