Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ffbe8268 authored by Mathias Agopian's avatar Mathias Agopian Committed by Android (Google) Code Review
Browse files

Merge "Fix some issues with RefBase debugging."

parents a28f6f11 ec122eb4
Loading
Loading
Loading
Loading
+101 −176
Original line number Original line Diff line number Diff line
@@ -22,16 +22,16 @@
#include <stdint.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>

#include <utils/StrongPointer.h>


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
namespace android {
namespace android {


class TextOutput;
class TextOutput;
TextOutput& printStrongPointer(TextOutput& to, const void* val);
TextOutput& printWeakPointer(TextOutput& to, const void* val);
TextOutput& printWeakPointer(TextOutput& to, const void* val);


template<typename T> class wp;

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


#define COMPARE_WEAK(_op_)                                      \
#define COMPARE_WEAK(_op_)                                      \
@@ -50,15 +50,15 @@ inline bool operator _op_ (const U* o) const { \
    return m_ptr _op_ o;                                        \
    return m_ptr _op_ o;                                        \
}
}


#define COMPARE(_op_)                                           \
// ---------------------------------------------------------------------------
COMPARE_WEAK(_op_)                                              \

inline bool operator _op_ (const wp<T>& o) const {              \
class ReferenceMover;
    return m_ptr _op_ o.m_ptr;                                  \
class ReferenceConverterBase {
}                                                               \
public:
template<typename U>                                            \
    virtual size_t getReferenceTypeSize() const = 0;
inline bool operator _op_ (const wp<U>& o) const {              \
    virtual void* getReferenceBase(void const*) const = 0;
    return m_ptr _op_ o.m_ptr;                                  \
    inline virtual ~ReferenceConverterBase() { }
}
};


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


@@ -115,6 +115,8 @@ public:
        getWeakRefs()->trackMe(enable, retain); 
        getWeakRefs()->trackMe(enable, retain); 
    }
    }


    typedef RefBase basetype;

protected:
protected:
                            RefBase();
                            RefBase();
    virtual                 ~RefBase();
    virtual                 ~RefBase();
@@ -137,6 +139,11 @@ protected:
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
    virtual void            onLastWeakRef(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:
private:
    friend class weakref_type;
    friend class weakref_type;
    class weakref_impl;
    class weakref_impl;
@@ -167,73 +174,20 @@ public:
        return mCount;
        return mCount;
    }
    }


    typedef LightRefBase<T> basetype;

protected:
protected:
    inline ~LightRefBase() { }
    inline ~LightRefBase() { }


private:
private:
    mutable volatile int32_t mCount;
    friend class ReferenceMover;
};
    inline static void moveReferences(void* d, void const* s, size_t n,

            const ReferenceConverterBase& caster) { }
// ---------------------------------------------------------------------------

template <typename T>
class sp
{
public:
    typedef typename RefBase::weakref_type weakref_type;
    
    inline sp() : m_ptr(0) { }

    sp(T* other);
    sp(const sp<T>& other);
    template<typename U> sp(U* other);
    template<typename U> sp(const sp<U>& other);

    ~sp();
    
    // Assignment

    sp& operator = (T* other);
    sp& operator = (const sp<T>& other);
    
    template<typename U> sp& operator = (const sp<U>& other);
    template<typename U> sp& operator = (U* other);
    
    //! Special optimization for use by ProcessState (and nobody else).
    void force_set(T* other);
    
    // Reset
    
    void clear();
    
    // Accessors

    inline  T&      operator* () const  { return *m_ptr; }
    inline  T*      operator-> () const { return m_ptr;  }
    inline  T*      get() const         { return m_ptr; }

    // Operators
        
    COMPARE(==)
    COMPARE(!=)
    COMPARE(>)
    COMPARE(<)
    COMPARE(<=)
    COMPARE(>=)


private:
private:
    template<typename Y> friend class sp;
    mutable volatile int32_t mCount;
    template<typename Y> friend class wp;

    // Optimization for wp::promote().
    sp(T* p, weakref_type* refs);
    
    T*              m_ptr;
};
};


template <typename T>
TextOutput& operator<<(TextOutput& to, const sp<T>& val);

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


template <typename T>
template <typename T>
@@ -329,112 +283,11 @@ private:
template <typename T>
template <typename T>
TextOutput& operator<<(TextOutput& to, const wp<T>& val);
TextOutput& operator<<(TextOutput& to, const wp<T>& val);


#undef COMPARE
#undef COMPARE_WEAK
#undef COMPARE_WEAK


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
// No user serviceable parts below here.


template<typename T>
sp<T>::sp(T* other)
    : m_ptr(other)
{
    if (other) other->incStrong(this);
}

template<typename T>
sp<T>::sp(const sp<T>& other)
    : m_ptr(other.m_ptr)
{
    if (m_ptr) m_ptr->incStrong(this);
}

template<typename T> template<typename U>
sp<T>::sp(U* other) : m_ptr(other)
{
    if (other) other->incStrong(this);
}

template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
    : m_ptr(other.m_ptr)
{
    if (m_ptr) m_ptr->incStrong(this);
}

template<typename T>
sp<T>::~sp()
{
    if (m_ptr) m_ptr->decStrong(this);
}

template<typename T>
sp<T>& sp<T>::operator = (const sp<T>& other) {
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = otherPtr;
    return *this;
}

template<typename T>
sp<T>& sp<T>::operator = (T* other)
{
    if (other) other->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = other;
    return *this;
}

template<typename T> template<typename U>
sp<T>& sp<T>::operator = (const sp<U>& other)
{
    U* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = otherPtr;
    return *this;
}

template<typename T> template<typename U>
sp<T>& sp<T>::operator = (U* other)
{
    if (other) other->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = other;
    return *this;
}

template<typename T>    
void sp<T>::force_set(T* other)
{
    other->forceIncStrong(this);
    m_ptr = other;
}

template<typename T>
void sp<T>::clear()
{
    if (m_ptr) {
        m_ptr->decStrong(this);
        m_ptr = 0;
    }
}

template<typename T>
sp<T>::sp(T* p, weakref_type* refs)
    : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
{
}

template <typename T>
inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
{
   return printStrongPointer(to, val.get());
}

// ---------------------------------------------------------------------------

template<typename T>
template<typename T>
wp<T>::wp(T* other)
wp<T>::wp(T* other)
    : m_ptr(other)
    : m_ptr(other)
@@ -572,7 +425,8 @@ void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
template<typename T>
template<typename T>
sp<T> wp<T>::promote() const
sp<T> wp<T>::promote() const
{
{
    return sp<T>(m_ptr, m_refs);
    T* p = (m_ptr && m_refs->attemptIncStrong(this)) ? m_ptr : 0;
    return sp<T>(p, true);
}
}


template<typename T>
template<typename T>
@@ -590,6 +444,77 @@ inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
    return printWeakPointer(to, val.unsafe_get());
    return printWeakPointer(to, val.unsafe_get());
}
}


// ---------------------------------------------------------------------------

// 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:
    template<typename TYPE> static inline
    void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
        memmove(d, s, n*sizeof(sp<TYPE>));
        StrongReferenceCast<TYPE> caster;
        TYPE::moveReferences(d, s, n, caster);
    }
    template<typename TYPE> static inline
    void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
        memmove(d, s, n*sizeof(wp<TYPE>));
        WeakReferenceCast<TYPE> caster;
        TYPE::moveReferences(d, s, n, caster);
    }
};

// specialization for moving sp<> and wp<> types.
// these are used by the [Sorted|Keyed]Vector<> implementations
// sp<> and wp<> need to be handled specially, because they do not
// have trivial copy operation in the general case (see RefBase.cpp
// when DEBUG ops are enabled), but can be implemented very
// efficiently in most cases.

template<typename TYPE> inline
void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
    ReferenceMover::move_references(d, s, n);
}

template<typename TYPE> inline
void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
    ReferenceMover::move_references(d, s, n);
}

template<typename TYPE> inline
void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
    ReferenceMover::move_references(d, s, n);
}

template<typename TYPE> inline
void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
    ReferenceMover::move_references(d, s, n);
}


}; // namespace android
}; // namespace android


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
+224 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2005 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H

#include <cutils/atomic.h>

#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>

// ---------------------------------------------------------------------------
namespace android {

class TextOutput;
TextOutput& printStrongPointer(TextOutput& to, const void* val);

template<typename T> class wp;

// ---------------------------------------------------------------------------

#define COMPARE(_op_)                                           \
inline bool operator _op_ (const sp<T>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
inline bool operator _op_ (const T* o) const {                  \
    return m_ptr _op_ o;                                        \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const sp<U>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const U* o) const {                  \
    return m_ptr _op_ o;                                        \
}                                                               \
inline bool operator _op_ (const wp<T>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const wp<U>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}

// ---------------------------------------------------------------------------

template <typename T>
class sp
{
public:
    inline sp() : m_ptr(0) { }

    sp(T* other);
    sp(const sp<T>& other);
    template<typename U> sp(U* other);
    template<typename U> sp(const sp<U>& other);

    ~sp();

    // Assignment

    sp& operator = (T* other);
    sp& operator = (const sp<T>& other);

    template<typename U> sp& operator = (const sp<U>& other);
    template<typename U> sp& operator = (U* other);

    //! Special optimization for use by ProcessState (and nobody else).
    void force_set(T* other);

    // Reset

    void clear();

    // Accessors

    inline  T&      operator* () const  { return *m_ptr; }
    inline  T*      operator-> () const { return m_ptr;  }
    inline  T*      get() const         { return m_ptr; }

    // Operators

    COMPARE(==)
    COMPARE(!=)
    COMPARE(>)
    COMPARE(<)
    COMPARE(<=)
    COMPARE(>=)

private:    
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;

    // Optimization for wp::promote().
    sp(T* p, bool);

    T*              m_ptr;
};

#undef COMPARE

template <typename T>
TextOutput& operator<<(TextOutput& to, const sp<T>& val);

// ---------------------------------------------------------------------------
// No user serviceable parts below here.

template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
  {
    if (other) other->incStrong(this);
  }

template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
  {
    if (m_ptr) m_ptr->incStrong(this);
  }

template<typename T> template<typename U>
sp<T>::sp(U* other) : m_ptr(other)
{
    if (other) other->incStrong(this);
}

template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr)
  {
    if (m_ptr) m_ptr->incStrong(this);
  }

template<typename T>
sp<T>::~sp()
{
    if (m_ptr) m_ptr->decStrong(this);
}

template<typename T>
sp<T>& sp<T>::operator = (const sp<T>& other) {
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = otherPtr;
    return *this;
}

template<typename T>
sp<T>& sp<T>::operator = (T* other)
{
    if (other) other->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = other;
    return *this;
}

template<typename T> template<typename U>
sp<T>& sp<T>::operator = (const sp<U>& other)
{
    U* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = otherPtr;
    return *this;
}

template<typename T> template<typename U>
sp<T>& sp<T>::operator = (U* other)
{
    if (other) other->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = other;
    return *this;
}

template<typename T>    
void sp<T>::force_set(T* other)
{
    other->forceIncStrong(this);
    m_ptr = other;
}

template<typename T>
void sp<T>::clear()
{
    if (m_ptr) {
        m_ptr->decStrong(this);
        m_ptr = 0;
    }
}

template<typename T>
sp<T>::sp(T* p, bool)
: m_ptr(p)
  {
  }

template <typename T>
inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
{
    return printStrongPointer(to, val.get());
}

}; // namespace android

// ---------------------------------------------------------------------------

#endif // ANDROID_STRONG_POINTER_H
+0 −13
Original line number Original line Diff line number Diff line
@@ -37,18 +37,6 @@ template <typename T> struct trait_trivial_move { enum { value = false }; };
template <typename T> struct trait_pointer      { enum { value = false }; };    
template <typename T> struct trait_pointer      { enum { value = false }; };    
template <typename T> struct trait_pointer<T*>  { enum { value = true }; };
template <typename T> struct trait_pointer<T*>  { enum { value = true }; };


// sp<> can be trivially moved
template <typename T> class sp;
template <typename T> struct trait_trivial_move< sp<T> >{
    enum { value = true }; 
};

// wp<> can be trivially moved
template <typename T> class wp;
template <typename T> struct trait_trivial_move< wp<T> >{ 
    enum { value = true }; 
};

template <typename TYPE>
template <typename TYPE>
struct traits {
struct traits {
    enum {
    enum {
@@ -217,7 +205,6 @@ void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
    }
    }
}
}



// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


/*
/*
+101 −70
Original line number Original line Diff line number Diff line
@@ -20,7 +20,6 @@


#include <utils/Atomic.h>
#include <utils/Atomic.h>
#include <utils/CallStack.h>
#include <utils/CallStack.h>
#include <utils/KeyedVector.h>
#include <utils/Log.h>
#include <utils/Log.h>
#include <utils/threads.h>
#include <utils/threads.h>
#include <utils/TextOutput.h>
#include <utils/TextOutput.h>
@@ -35,6 +34,7 @@


// compile with refcounting debugging enabled
// compile with refcounting debugging enabled
#define DEBUG_REFS                      0
#define DEBUG_REFS                      0
#define DEBUG_REFS_FATAL_SANITY_CHECKS  0
#define DEBUG_REFS_ENABLED_BY_DEFAULT   1
#define DEBUG_REFS_ENABLED_BY_DEFAULT   1
#define DEBUG_REFS_CALLSTACK_ENABLED    1
#define DEBUG_REFS_CALLSTACK_ENABLED    1


@@ -70,8 +70,10 @@ public:


    void addStrongRef(const void* /*id*/) { }
    void addStrongRef(const void* /*id*/) { }
    void removeStrongRef(const void* /*id*/) { }
    void removeStrongRef(const void* /*id*/) { }
    void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void addWeakRef(const void* /*id*/) { }
    void addWeakRef(const void* /*id*/) { }
    void removeWeakRef(const void* /*id*/) { }
    void removeWeakRef(const void* /*id*/) { }
    void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
    void printRefs() const { }
    void printRefs() const { }
    void trackMe(bool, bool) { }
    void trackMe(bool, bool) { }


@@ -87,40 +89,74 @@ public:
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
        , mRetain(false)
        , mRetain(false)
    {
    {
        //LOGI("NEW weakref_impl %p for RefBase %p", this, base);
    }
    }
    
    
    ~weakref_impl()
    ~weakref_impl()
    {
    {
        LOG_ALWAYS_FATAL_IF(!mRetain && mStrongRefs != NULL, "Strong references remain!");
        bool dumpStack = false;
        LOG_ALWAYS_FATAL_IF(!mRetain && mWeakRefs != NULL, "Weak references remain!");
        if (!mRetain && mStrongRefs != NULL) {
            dumpStack = true;
#if DEBUG_REFS_FATAL_SANITY_CHECKS
            LOG_ALWAYS_FATAL("Strong references remain!");
#else
            LOGE("Strong references remain!");
#endif
        }
        }


    void addStrongRef(const void* id)
        if (!mRetain && mWeakRefs != NULL) {
    {
            dumpStack = true;
#if DEBUG_REFS_FATAL_SANITY_CHECKS
            LOG_ALWAYS_FATAL("Weak references remain!");
#else
            LOGE("Weak references remain!");
#endif
        }

        if (dumpStack) {
            CallStack stack;
            stack.update();
            stack.dump();
        }
    }

    void addStrongRef(const void* id) {
        //LOGD_IF(mTrackEnabled,
        //        "addStrongRef: RefBase=%p, id=%p", mBase, id);
        addRef(&mStrongRefs, id, mStrong);
        addRef(&mStrongRefs, id, mStrong);
    }
    }


    void removeStrongRef(const void* id)
    void removeStrongRef(const void* id) {
    {
        //LOGD_IF(mTrackEnabled,
        if (!mRetain)
        //        "removeStrongRef: RefBase=%p, id=%p", mBase, id);
        if (!mRetain) {
            removeRef(&mStrongRefs, id);
            removeRef(&mStrongRefs, id);
        else
        } else {
            addRef(&mStrongRefs, id, -mStrong);
            addRef(&mStrongRefs, id, -mStrong);
        }
        }
    }


    void addWeakRef(const void* id)
    void renameStrongRefId(const void* old_id, const void* new_id) {
    {
        //LOGD_IF(mTrackEnabled,
        //        "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
        //        mBase, old_id, new_id);
        renameRefsId(mStrongRefs, old_id, new_id);
    }

    void addWeakRef(const void* id) {
        addRef(&mWeakRefs, id, mWeak);
        addRef(&mWeakRefs, id, mWeak);
    }
    }


    void removeWeakRef(const void* id)
    void removeWeakRef(const void* id) {
    {
        if (!mRetain) {
        if (!mRetain)
            removeRef(&mWeakRefs, id);
            removeRef(&mWeakRefs, id);
        else
        } else {
            addRef(&mWeakRefs, id, -mWeak);
            addRef(&mWeakRefs, id, -mWeak);
        }
        }
    }

    void renameWeakRefId(const void* old_id, const void* new_id) {
        renameRefsId(mWeakRefs, old_id, new_id);
    }


    void trackMe(bool track, bool retain)
    void trackMe(bool track, bool retain)
    { 
    { 
@@ -133,8 +169,7 @@ public:
        String8 text;
        String8 text;


        {
        {
            AutoMutex _l(const_cast<weakref_impl*>(this)->mMutex);
            Mutex::Autolock _l(const_cast<weakref_impl*>(this)->mMutex);
    
            char buf[128];
            char buf[128];
            sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
            sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
            text.append(buf);
            text.append(buf);
@@ -173,6 +208,7 @@ private:
    {
    {
        if (mTrackEnabled) {
        if (mTrackEnabled) {
            AutoMutex _l(mMutex);
            AutoMutex _l(mMutex);

            ref_entry* ref = new ref_entry;
            ref_entry* ref = new ref_entry;
            // Reference count at the time of the snapshot, but before the
            // Reference count at the time of the snapshot, but before the
            // update.  Positive value means we increment, negative--we
            // update.  Positive value means we increment, negative--we
@@ -182,7 +218,6 @@ private:
#if DEBUG_REFS_CALLSTACK_ENABLED
#if DEBUG_REFS_CALLSTACK_ENABLED
            ref->stack.update(2);
            ref->stack.update(2);
#endif
#endif
            
            ref->next = *refs;
            ref->next = *refs;
            *refs = ref;
            *refs = ref;
        }
        }
@@ -200,13 +235,37 @@ private:
                    delete ref;
                    delete ref;
                    return;
                    return;
                }
                }
                
                refs = &ref->next;
                refs = &ref->next;
                ref = *refs;
                ref = *refs;
            }
            }


            LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p (weakref_type %p) that doesn't exist!",
#if DEBUG_REFS_FATAL_SANITY_CHECKS
            LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p"
                    "(weakref_type %p) that doesn't exist!",
                    id, mBase, this);
#endif

            LOGE("RefBase: removing id %p on RefBase %p"
                    "(weakref_type %p) that doesn't exist!",
                    id, mBase, this);
                    id, mBase, this);

            CallStack stack;
            stack.update();
            stack.dump();
        }
    }

    void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
    {
        if (mTrackEnabled) {
            AutoMutex _l(mMutex);
            ref_entry* ref = r;
            while (ref != NULL) {
                if (ref->id == old_id) {
                    ref->id = new_id;
                }
                ref = ref->next;
            }
        }
        }
    }
    }


@@ -236,44 +295,6 @@ private:
    // on removeref that match the address ones.
    // on removeref that match the address ones.
    bool mRetain;
    bool mRetain;


#if 0
    void addRef(KeyedVector<const void*, int32_t>* refs, const void* id)
    {
        AutoMutex _l(mMutex);
        ssize_t i = refs->indexOfKey(id);
        if (i >= 0) {
            ++(refs->editValueAt(i));
        } else {
            i = refs->add(id, 1);
        }
    }

    void removeRef(KeyedVector<const void*, int32_t>* refs, const void* id)
    {
        AutoMutex _l(mMutex);
        ssize_t i = refs->indexOfKey(id);
        LOG_ALWAYS_FATAL_IF(i < 0, "RefBase: removing id %p that doesn't exist!", id);
        if (i >= 0) {
            int32_t val = --(refs->editValueAt(i));
            if (val == 0) {
                refs->removeItemsAt(i);
            }
        }
    }

    void printRefs(const KeyedVector<const void*, int32_t>& refs)
    {
        const size_t N=refs.size();
        for (size_t i=0; i<N; i++) {
            printf("\tID %p: %d remain\n", refs.keyAt(i), refs.valueAt(i));
        }
    }

    mutable Mutex mMutex;
    KeyedVector<const void*, int32_t> mStrongRefs;
    KeyedVector<const void*, int32_t> mWeakRefs;
#endif

#endif
#endif
};
};


@@ -282,7 +303,6 @@ private:
void RefBase::incStrong(const void* id) const
void RefBase::incStrong(const void* id) const
{
{
    weakref_impl* const refs = mRefs;
    weakref_impl* const refs = mRefs;
    refs->addWeakRef(id);
    refs->incWeak(id);
    refs->incWeak(id);
    
    
    refs->addStrongRef(id);
    refs->addStrongRef(id);
@@ -314,14 +334,12 @@ void RefBase::decStrong(const void* id) const
            delete this;
            delete this;
        }
        }
    }
    }
    refs->removeWeakRef(id);
    refs->decWeak(id);
    refs->decWeak(id);
}
}


void RefBase::forceIncStrong(const void* id) const
void RefBase::forceIncStrong(const void* id) const
{
{
    weakref_impl* const refs = mRefs;
    weakref_impl* const refs = mRefs;
    refs->addWeakRef(id);
    refs->incWeak(id);
    refs->incWeak(id);
    
    
    refs->addStrongRef(id);
    refs->addStrongRef(id);
@@ -433,7 +451,6 @@ bool RefBase::weakref_type::attemptIncStrong(const void* id)
        }
        }
    }
    }
    
    
    impl->addWeakRef(id);
    impl->addStrongRef(id);
    impl->addStrongRef(id);


#if PRINT_REFS
#if PRINT_REFS
@@ -498,14 +515,11 @@ RefBase::weakref_type* RefBase::getWeakRefs() const
RefBase::RefBase()
RefBase::RefBase()
    : mRefs(new weakref_impl(this))
    : mRefs(new weakref_impl(this))
{
{
//    LOGV("Creating refs %p with RefBase %p\n", mRefs, this);
}
}


RefBase::~RefBase()
RefBase::~RefBase()
{
{
//    LOGV("Destroying RefBase %p (refs %p)\n", this, mRefs);
    if (mRefs->mWeak == 0) {
    if (mRefs->mWeak == 0) {
//        LOGV("Freeing refs %p of old RefBase %p\n", mRefs, this);
        delete mRefs;
        delete mRefs;
    }
    }
}
}
@@ -534,6 +548,23 @@ void RefBase::onLastWeakRef(const void* /*id*/)


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


void RefBase::moveReferences(void* dst, void const* src, size_t n,
        const ReferenceConverterBase& caster)
{
#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);
    }
#endif
}

// ---------------------------------------------------------------------------

TextOutput& printStrongPointer(TextOutput& to, const void* val)
TextOutput& printStrongPointer(TextOutput& to, const void* val)
{
{
    to << "sp<>(" << val << ")";
    to << "sp<>(" << val << ")";