diff options
Diffstat (limited to 'include/utils/RefBase.h')
-rw-r--r-- | include/utils/RefBase.h | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h new file mode 100644 index 000000000000..e37b56f5bf93 --- /dev/null +++ b/include/utils/RefBase.h @@ -0,0 +1,526 @@ +/* + * 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_REF_BASE_H +#define ANDROID_REF_BASE_H + +#include <utils/TextOutput.h> + +#include <stdint.h> +#include <sys/types.h> +#include <stdlib.h> + +// --------------------------------------------------------------------------- +namespace android { + +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 wp<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 wp<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; \ +} + +// --------------------------------------------------------------------------- + +class RefBase +{ +public: + void incStrong(const void* id) const; + void decStrong(const void* id) const; + + void forceIncStrong(const void* id) const; + + //! DEBUGGING ONLY: Get current strong ref count. + int32_t getStrongCount() const; + + class weakref_type + { + public: + RefBase* refBase() const; + + void incWeak(const void* id); + void decWeak(const void* id); + + bool attemptIncStrong(const void* id); + + //! This is only safe if you have set OBJECT_LIFETIME_FOREVER. + bool attemptIncWeak(const void* id); + + //! DEBUGGING ONLY: Get current weak ref count. + int32_t getWeakCount() const; + + //! DEBUGGING ONLY: Print references held on object. + void printRefs() const; + + //! DEBUGGING ONLY: Enable tracking for this object. + // enable -- enable/disable tracking + // retain -- when tracking is enable, if true, then we save a stack trace + // for each reference and dereference; when retain == false, we + // match up references and dereferences and keep only the + // outstanding ones. + + void trackMe(bool enable, bool retain); + }; + + weakref_type* createWeak(const void* id) const; + + weakref_type* getWeakRefs() const; + + //! DEBUGGING ONLY: Print references held on object. + inline void printRefs() const { getWeakRefs()->printRefs(); } + + //! DEBUGGING ONLY: Enable tracking of object. + inline void trackMe(bool enable, bool retain) + { + getWeakRefs()->trackMe(enable, retain); + } + +protected: + RefBase(); + virtual ~RefBase(); + + //! Flags for extendObjectLifetime() + enum { + OBJECT_LIFETIME_WEAK = 0x0001, + OBJECT_LIFETIME_FOREVER = 0x0003 + }; + + void extendObjectLifetime(int32_t mode); + + //! Flags for onIncStrongAttempted() + enum { + FIRST_INC_STRONG = 0x0001 + }; + + virtual void onFirstRef(); + virtual void onLastStrongRef(const void* id); + virtual bool onIncStrongAttempted(uint32_t flags, const void* id); + virtual void onLastWeakRef(const void* id); + +private: + friend class weakref_type; + class weakref_impl; + + RefBase(const RefBase& o); + RefBase& operator=(const RefBase& o); + + weakref_impl* const mRefs; +}; + +// --------------------------------------------------------------------------- + +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: + template<typename Y> friend class sp; + 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> +class wp +{ +public: + typedef typename RefBase::weakref_type weakref_type; + + inline wp() : m_ptr(0) { } + + wp(T* other); + wp(const wp<T>& other); + wp(const sp<T>& other); + template<typename U> wp(U* other); + template<typename U> wp(const sp<U>& other); + template<typename U> wp(const wp<U>& other); + + ~wp(); + + // Assignment + + wp& operator = (T* other); + wp& operator = (const wp<T>& other); + wp& operator = (const sp<T>& other); + + template<typename U> wp& operator = (U* other); + template<typename U> wp& operator = (const wp<U>& other); + template<typename U> wp& operator = (const sp<U>& other); + + void set_object_and_refs(T* other, weakref_type* refs); + + // promotion to sp + + sp<T> promote() const; + + // Reset + + void clear(); + + // Accessors + + inline weakref_type* get_refs() const { return m_refs; } + + inline T* unsafe_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; + + T* m_ptr; + weakref_type* m_refs; +}; + +template <typename T> +TextOutput& operator<<(TextOutput& to, const wp<T>& val); + +#undef COMPARE + +// --------------------------------------------------------------------------- +// 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) { + if (other.m_ptr) other.m_ptr->incStrong(this); + if (m_ptr) m_ptr->decStrong(this); + m_ptr = other.m_ptr; + 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) +{ + if (other.m_ptr) other.m_ptr->incStrong(this); + if (m_ptr) m_ptr->decStrong(this); + m_ptr = other.m_ptr; + 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) +{ + to << "sp<>(" << val.get() << ")"; + return to; +} + +// --------------------------------------------------------------------------- + +template<typename T> +wp<T>::wp(T* other) + : m_ptr(other) +{ + if (other) m_refs = other->createWeak(this); +} + +template<typename T> +wp<T>::wp(const wp<T>& other) + : m_ptr(other.m_ptr), m_refs(other.m_refs) +{ + if (m_ptr) m_refs->incWeak(this); +} + +template<typename T> +wp<T>::wp(const sp<T>& other) + : m_ptr(other.m_ptr) +{ + if (m_ptr) { + m_refs = m_ptr->createWeak(this); + } +} + +template<typename T> template<typename U> +wp<T>::wp(U* other) + : m_ptr(other) +{ + if (other) m_refs = other->createWeak(this); +} + +template<typename T> template<typename U> +wp<T>::wp(const wp<U>& other) + : m_ptr(other.m_ptr) +{ + if (m_ptr) { + m_refs = other.m_refs; + m_refs->incWeak(this); + } +} + +template<typename T> template<typename U> +wp<T>::wp(const sp<U>& other) + : m_ptr(other.m_ptr) +{ + if (m_ptr) { + m_refs = m_ptr->createWeak(this); + } +} + +template<typename T> +wp<T>::~wp() +{ + if (m_ptr) m_refs->decWeak(this); +} + +template<typename T> +wp<T>& wp<T>::operator = (T* other) +{ + weakref_type* newRefs = + other ? other->createWeak(this) : 0; + if (m_ptr) m_refs->decWeak(this); + m_ptr = other; + m_refs = newRefs; + return *this; +} + +template<typename T> +wp<T>& wp<T>::operator = (const wp<T>& other) +{ + if (other.m_ptr) other.m_refs->incWeak(this); + if (m_ptr) m_refs->decWeak(this); + m_ptr = other.m_ptr; + m_refs = other.m_refs; + return *this; +} + +template<typename T> +wp<T>& wp<T>::operator = (const sp<T>& other) +{ + weakref_type* newRefs = + other != NULL ? other->createWeak(this) : 0; + if (m_ptr) m_refs->decWeak(this); + m_ptr = other.get(); + m_refs = newRefs; + return *this; +} + +template<typename T> template<typename U> +wp<T>& wp<T>::operator = (U* other) +{ + weakref_type* newRefs = + other ? other->createWeak(this) : 0; + if (m_ptr) m_refs->decWeak(this); + m_ptr = other; + m_refs = newRefs; + return *this; +} + +template<typename T> template<typename U> +wp<T>& wp<T>::operator = (const wp<U>& other) +{ + if (other.m_ptr) other.m_refs->incWeak(this); + if (m_ptr) m_refs->decWeak(this); + m_ptr = other.m_ptr; + m_refs = other.m_refs; + return *this; +} + +template<typename T> template<typename U> +wp<T>& wp<T>::operator = (const sp<U>& other) +{ + weakref_type* newRefs = + other != NULL ? other->createWeak(this) : 0; + if (m_ptr) m_refs->decWeak(this); + m_ptr = other.get(); + m_refs = newRefs; + return *this; +} + +template<typename T> +void wp<T>::set_object_and_refs(T* other, weakref_type* refs) +{ + if (other) refs->incWeak(this); + if (m_ptr) m_refs->decWeak(this); + m_ptr = other; + m_refs = refs; +} + +template<typename T> +sp<T> wp<T>::promote() const +{ + return sp<T>(m_ptr, m_refs); +} + +template<typename T> +void wp<T>::clear() +{ + if (m_ptr) { + m_refs->decWeak(this); + m_ptr = 0; + } +} + +template <typename T> +inline TextOutput& operator<<(TextOutput& to, const wp<T>& val) +{ + to << "wp<>(" << val.unsafe_get() << ")"; + return to; +} + +}; // namespace android + +// --------------------------------------------------------------------------- + +#endif // ANDROID_REF_BASE_H |