智能指针是一种抽象的数据类型,它通常是经过类模板完成的,能够完成泛型,并且能够经过类的析构函数自动开释指针所指向的内存或目标。
在Android中,有相似 shared_ptr
和 weak_ptr
的智能指针 LightRefBase + sp
和 RefBase + wp
。
其间:
LightRefBase + sp
相似于 shared_ptr
的实践运用办法;
RefBase + wp + sp
相似于 shared_ptr
+ weak_ptr
的实践运用办法。
(weak_ptr
是合作 shared_ptr
运用的,具体能够查看C++四种智能指针)
实践原理便是:
经过引证计数来保护目标的生命周期。每逢一个新的指针指向了一个目标时,这个目标的引证计数就添加1,相反每逢一个指针不再指向一个目标时,这个目标的引证计数就削减1,当引证计数为0的时分,就安全的开释它。
为了防止循环引证。需求自己控制在合适的位置运用 weak 引证。weak 引证不会添加引证计数(这是在C++11中。 在android中,strong引证 和 weak引证 的计数是分开保存的。当然原理共同。只看强引证)
下面的代码基本都在 system/core
目录下,本文中的代码来自android 13 。就不逐个具体标明了。
1、LightRefBase + sp
LightRefBase 是一个模板类,内部经过成员变量mCount来对引证进行计数,incStrong办法对mCount加1,decStrong办法对mCount减1。假如不涉及循环引证。直接承继类LightRefBase运用即可。
template <class T>
class LightRefBase
{
public:
// 构造函数初始化引证计数为0
inline LightRefBase() : mCount(0) { }
// 引证计数变量加1
inline void incStrong(__attribute__((unused)) const void* id) const {
mCount.fetch_add(1, std::memory_order_relaxed);
}
// 引证计数减1
inline void decStrong(__attribute__((unused)) const void* id) const {
if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
// 当引证计数器减到0的时分经过del开释本来目标
delete static_cast<const T*>(this);
}
}
// 获取引证计数值
inline int32_t getStrongCount() const {
return mCount.load(std::memory_order_relaxed);
}
typedef LightRefBase<T> basetype;
protected:
inline ~LightRefBase() { }
private:
// 引证计数成员变量
mutable std::atomic<int32_t> mCount;
};
sp是轻量级指针的完成类,一起也是强指针的完成类。构造函数+1,析构函数-1。
长处:简略便利,能掩盖大多数场景
缺陷:有循环引证导致无法开释,进而导致内存走漏问题。
template<typename T>
class sp {
public:
inline sp() : m_ptr(nullptr) { }
// The old way of using sp<> was like this. This is bad because it relies
// on implicit conversion to sp<>, which we would like to remove (if an
// object is being managed some other way, this is double-ownership). We
// want to move away from this:
//
// sp<Foo> foo = new Foo(...); // DO NOT DO THIS
//
// Instead, prefer to do this:
//
// sp<Foo> foo = sp<Foo>::make(...); // DO THIS
//
// Sometimes, in order to use this, when a constructor is marked as private,
// you may need to add this to your class:
//
// friend class sp<Foo>;
template <typename... Args>
static inline sp<T> make(Args&&... args);
// if nullptr, returns nullptr
//
// if a strong pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline sp<T> fromExisting(T* other);
// for more information about this macro and correct RefBase usage, see
// the comment at the top of utils/RefBase.h
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
sp(std::nullptr_t) : sp() {}
#else
sp(T* other); // NOLINT(implicit)
template <typename U>
sp(U* other); // NOLINT(implicit)
sp& operator=(T* other);
template <typename U>
sp& operator=(U* other);
#endif
sp(const sp<T>& other);
sp(sp<T>&& other) noexcept;
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
// Cast a strong pointer directly from one type to another. Constructors
// allow changing types, but only if they are pointer-compatible. This does
// a static_cast internally.
template <typename U>
static inline sp<T> cast(const sp<U>& other);
~sp();
// Assignment
sp& operator = (const sp<T>& other);
sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<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; }
inline explicit operator bool () const { return m_ptr != nullptr; }
// Punt these to the wp<> implementation.
template<typename U>
inline bool operator == (const wp<U>& o) const {
return o == *this;
}
template<typename U>
inline bool operator != (const wp<U>& o) const {
return o != *this;
}
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
static inline void check_not_on_stack(const void* ptr);
T* m_ptr;
};
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);
}
2、RefBase + wp + sp
RefBase 也是模板类,其间,强引证的计数,供给了incStrong和decStrong办法来保护;弱引证的计数供给了incWeak和decWeak办法。一起它运用weakref_type类的目标来描述目标的引证计数,该类完成类为weakref_impl。因而一起需求运用强指针或者弱指针(也便是要考虑内存走漏的或许状况),就需求承继类RefBase。
class RefBase
{
public:
void incStrong(const void* id) const;
void incStrongRequireStrong(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 incWeakRequireWeak(const void* id);
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
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:
// When constructing these objects, prefer using sp::make<>. Using a RefBase
// object on the stack or with other refcount mechanisms (e.g.
// std::shared_ptr) is inherently wrong. RefBase types have an implicit
// ownership model and cannot be safely used with other ownership models.
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
// Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
// Invoked when either the last strong reference goes away, or we need to undo
// the effect of an unnecessary onIncStrongAttempted.
virtual void onLastStrongRef(const void* id);
// Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to
// strong reference. May have side effects if it returns true.
// The first flags argument is always FIRST_INC_STRONG.
// TODO: Remove initial flag argument.
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
// Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
// kind goes away. Unused.
// TODO: Remove.
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
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;
};
wp是弱指针的完成类。为RefBase供给了弱引证计数,经过weakref_type指针类型的成员变量m_refs,用来保护目标的弱引证计数。
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline wp() : m_ptr(nullptr), m_refs(nullptr) { }
// if nullptr, returns nullptr
//
// if a weak pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline wp<T> fromExisting(T* other);
// for more information about this flag, see above
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
wp(std::nullptr_t) : wp() {}
#else
wp(T* other); // NOLINT(implicit)
template <typename U>
wp(U* other); // NOLINT(implicit)
wp& operator=(T* other);
template <typename U>
wp& operator=(U* other);
#endif
wp(const wp<T>& other);
explicit wp(const sp<T>& other);
template<typename U> wp(const sp<U>& other); // NOLINT(implicit)
template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~wp();
// Assignment
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& 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_WEAK(==)
COMPARE_WEAK(!=)
COMPARE_WEAK_FUNCTIONAL(>, std::greater)
COMPARE_WEAK_FUNCTIONAL(<, std::less)
COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
template<typename U>
inline bool operator == (const wp<U>& o) const {
return m_refs == o.m_refs; // Implies m_ptr == o.mptr; see invariants below.
}
template<typename U>
inline bool operator == (const sp<U>& o) const {
// Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
// object at the same address.
if (o == nullptr) {
return m_ptr == nullptr;
} else {
return m_refs == o->getWeakRefs(); // Implies m_ptr == o.mptr.
}
}
template<typename U>
inline bool operator != (const sp<U>& o) const {
return !(*this == o);
}
template<typename U>
inline bool operator > (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::greater>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
}
}
template<typename U>
inline bool operator < (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::less>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::less>(m_ptr, o.m_ptr);
}
}
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
T* m_ptr;
weakref_type* m_refs;
};
template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
wp<T>& wp<T>::operator = (const wp<T>& other)
{
weakref_type* otherRefs(other.m_refs);
T* otherPtr(other.m_ptr);
if (otherPtr) otherRefs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = otherRefs;
return *this;
}
template<typename T>
sp<T> wp<T>::promote() const
{
sp<T> result;
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result;
}
wp并不能直接操作它引证的目标,是因为wp类并没有重载*和->操作符号,因而无法对wp经过*和->进行调用。那么在需求操作它所引证的目标的时分,需求运用wp的成员函数promote,其完成如下:
template<typename T>
// 弱指针进行升级为强指针
// promote回来sp类型就能够对其进行操作
sp<T> wp<T>::promote() const
{
sp<T> result;
// 实践上是经过weakref_impl的attemptIncStrong函数来检查该目标是否被开释
if (m_ptr && m_refs->attemptIncStrong(&result)) {
// 假如该目标有用,将m_ptr赋值到上面定义的sp类中
result.set_pointer(m_ptr);
}
// 回来一个强引证,它指向的目标与该弱引证指向的目标是同一个目标
return result;
}
3、Android中的实践运用场景
可 wp 的运用和JAVA中的回调运用相同。由于回调经常有或许生命周期比正常activity等要长,运用 wp 来引证能够削减内存走漏或许
class OpsCallback : public BnAppOpsCallback {
public:
explicit OpsCallback(wp<BasicClient> client);
virtual void opChanged(int32_t op, const String16& packageName);
private:
wp<BasicClient> mClient;
}; // class OpsCallback
class BasicClient : public virtual RefBase {
friend class CameraService;
public:
virtual status_t initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) = 0;
virtual binder::Status disconnect();
// because we can't virtually inherit IInterface, which breaks
// virtual inheritance
virtual sp<IBinder> asBinderWrapper() = 0;
// Return the remote callback binder object (e.g. ICameraDeviceCallbacks)
sp<IBinder> getRemote() {
return mRemoteBinder;
}
...
// these are initialized in the constructor.
static sp<CameraService> sCameraService;
...
}
其间 sp 的 CameraService 也承继了 RefBase 。
QSSI.13/frameworks/av/services/camera/libcameraservice/CameraService.h
class CameraService :
public BinderService<CameraService>,
public virtual ::android::hardware::BnCameraService,
public virtual IBinder::DeathRecipient,
public virtual CameraProviderManager::StatusListener
{
friend class BinderService<CameraService>;
friend class CameraOfflineSessionClient;
public:
...
}
QSSI.13/frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.h
struct StatusListener : virtual public RefBase {
~StatusListener() {}
virtual void onDeviceStatusChanged(const String8 &cameraId,
CameraDeviceStatus newStatus) = 0;
virtual void onDeviceStatusChanged(const String8 &cameraId,
const String8 &physicalCameraId,
CameraDeviceStatus newStatus) = 0;
virtual void onTorchStatusChanged(const String8 &cameraId,
TorchModeStatus newStatus,
SystemCameraKind kind) = 0;
virtual void onTorchStatusChanged(const String8 &cameraId,
TorchModeStatus newStatus) = 0;
virtual void onNewProviderRegistered() = 0;
};
而 LightRefBase 的运用在 CameraFlashlight 中有体现。
class CameraFlashlight : public virtual VirtualLightRefBase {
public:
CameraFlashlight(sp<CameraProviderManager> providerManager,
CameraProviderManager::StatusListener* callbacks);
virtual ~CameraFlashlight();
...
}
QSSI.13/frameworks/av/services/camera/libcameraservice/CameraService.h
// flashlight control
sp<CameraFlashlight> mFlashlight;