am 4e37ddff: Fix a crasher with RefBase debugging and vectors of wp<>

* commit '4e37ddff43784a5a784beb4b62ea3f3136e1634b':
  Fix a crasher with RefBase debugging and vectors of wp<>
This commit is contained in:
Mathias Agopian 2013-03-20 00:27:46 +00:00 committed by Android Git Automerger
commit dd3fcd2e58
2 changed files with 71 additions and 48 deletions

View File

@ -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<T>& 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 <typename TYPE>
struct StrongReferenceCast : public ReferenceConverterBase {
virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); }
virtual void* getReferenceBase(void const* p) const {
sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p));
return static_cast<typename TYPE::basetype *>(sptr->get());
}
};
template <typename TYPE>
struct WeakReferenceCast : public ReferenceConverterBase {
virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); }
virtual void* getReferenceBase(void const* p) const {
wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p));
return static_cast<typename TYPE::basetype *>(sptr->unsafe_get());
}
};
public:
// it would be nice if we could make sure no extra code is generated
// for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
// Using a sp<RefBase> override doesn't work; it's a bit like we wanted
// a template<typename TYPE inherits RefBase> template...
template<typename TYPE> static inline
void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
class Renamer : public ReferenceRenamer {
sp<TYPE>* d;
sp<TYPE> 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<TYPE>* d, sp<TYPE> const* s) : s(s), d(d) { }
};
memmove(d, s, n*sizeof(sp<TYPE>));
StrongReferenceCast<TYPE> caster;
TYPE::moveReferences(d, s, n, caster);
TYPE::renameRefs(n, Renamer(d, s));
}
template<typename TYPE> static inline
void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
class Renamer : public ReferenceRenamer {
wp<TYPE>* d;
wp<TYPE> 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<TYPE>* d, wp<TYPE> const* s) : s(s), d(d) { }
};
memmove(d, s, n*sizeof(wp<TYPE>));
WeakReferenceCast<TYPE> caster;
TYPE::moveReferences(d, s, n, caster);
TYPE::renameRefs(n, Renamer(d, s));
}
};

View File

@ -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<n ; i++) {
void* d = reinterpret_cast<void *>(intptr_t(dst) + i*itemSize);
void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize);
RefBase* ref(reinterpret_cast<RefBase*>(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<weakref_impl*>(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)