android分析之智能指针
- 智能指针是一个包装类,该类有一个指针指向真正的类对象
- 引用计数型智能指针,该引用计数是在应该被真正类所持有,而非包装类(智能指针)
- 为了方便,会将引用计数单独实现在一个类中,这样所有继承它的类都有计数器
// --------------------------------------------------------------------------- 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);
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;
void set_pointer(T* ptr);
T* m_ptr;//指向真正的类对象的指针
};
// --------------------------------------------------------------------------- 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); // 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; 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);
} typedef RefBase basetype; protected:
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
}; 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 ReferenceMover;
static void moveReferences(void* d, void const* s, size_t n,
const ReferenceConverterBase& caster); private:
friend class weakref_type;
class weakref_impl; RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o); weakref_impl* const mRefs;
};
// --------------------------------------------------------------------------- class RefBase::weakref_impl : public RefBase::weakref_type//引用计数器的实现类
{
public:
volatile int32_t mStrong;//强引用
volatile int32_t mWeak;//若引用
RefBase* const mBase;
volatile int32_t mFlags; #if !DEBUG_REFS weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
} void addStrongRef(const void* /*id*/) { }
void removeStrongRef(const void* /*id*/) { }
void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void addWeakRef(const void* /*id*/) { }
void removeWeakRef(const void* /*id*/) { }
void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void printRefs() const { }
void trackMe(bool, bool) { } #else weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
, mStrongRefs(NULL)
, mWeakRefs(NULL)
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
} ~weakref_impl()
{
bool dumpStack = false;
if (!mRetain && mStrongRefs != NULL) {
dumpStack = true;
#if DEBUG_REFS_FATAL_SANITY_CHECKS
LOG_ALWAYS_FATAL("Strong references remain!");
#else
ALOGE("Strong references remain:");
#endif
ref_entry* refs = mStrongRefs;
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
refs->stack.dump();
#endif
refs = refs->next;
}
} if (!mRetain && mWeakRefs != NULL) {
dumpStack = true;
#if DEBUG_REFS_FATAL_SANITY_CHECKS
LOG_ALWAYS_FATAL("Weak references remain:");
#else
ALOGE("Weak references remain!");
#endif
ref_entry* refs = mWeakRefs;
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
refs->stack.dump();
#endif
refs = refs->next;
}
}
if (dumpStack) {
ALOGE("above errors at:");
CallStack stack;
stack.update();
stack.dump();
}
} void addStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "addStrongRef: RefBase=%p, id=%p", mBase, id);
addRef(&mStrongRefs, id, mStrong);
} void removeStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "removeStrongRef: RefBase=%p, id=%p", mBase, id);
if (!mRetain) {
removeRef(&mStrongRefs, id);
} else {
addRef(&mStrongRefs, id, -mStrong);
}
} void renameStrongRefId(const void* old_id, const void* new_id) {
//ALOGD_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);
} void removeWeakRef(const void* id) {
if (!mRetain) {
removeRef(&mWeakRefs, id);
} else {
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)
{
mTrackEnabled = track;
mRetain = retain;
} void printRefs() const
{
String8 text; {
Mutex::Autolock _l(mMutex);
char buf[128];
sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
text.append(buf);
printRefsLocked(&text, mStrongRefs);
sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
text.append(buf);
printRefsLocked(&text, mWeakRefs);
} {
char name[100];
snprintf(name, 100, "/data/%p.stack", this);
int rc = open(name, O_RDWR | O_CREAT | O_APPEND);
if (rc >= 0) {
write(rc, text.string(), text.length());
close(rc);
ALOGD("STACK TRACE for %p saved in %s", this, name);
}
else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
name, strerror(errno));
}
} private:
struct ref_entry
{
ref_entry* next;
const void* id;
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack stack;
#endif
int32_t ref;
}; void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex); ref_entry* ref = new ref_entry;
// Reference count at the time of the snapshot, but before the
// update. Positive value means we increment, negative--we
// decrement the reference count.
ref->ref = mRef;
ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
ref->stack.update(2);
#endif
ref->next = *refs;
*refs = ref;
}
} void removeRef(ref_entry** refs, const void* id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex); ref_entry* const head = *refs;
ref_entry* ref = head;
while (ref != NULL) {
if (ref->id == id) {
*refs = ref->next;
delete ref;
return;
}
refs = &ref->next;
ref = *refs;
} #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 ALOGE("RefBase: removing id %p on RefBase %p"
"(weakref_type %p) that doesn't exist!",
id, mBase, this); ref = head;
while (ref) {
char inc = ref->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
ref = ref->next;
} 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;
}
}
} void printRefsLocked(String8* out, const ref_entry* refs) const
{
char buf[128];
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
sprintf(buf, "\t%c ID %p (ref %d):\n",
inc, refs->id, refs->ref);
out->append(buf);
#if DEBUG_REFS_CALLSTACK_ENABLED
out->append(refs->stack.toString("\t\t"));
#else
out->append("\t\t(call stacks disabled)");
#endif
refs = refs->next;
}
} mutable Mutex mMutex;
ref_entry* mStrongRefs;
ref_entry* mWeakRefs; bool mTrackEnabled;
// Collect stack traces on addref and removeref, instead of deleting the stack references
// on removeref that match the address ones.
bool mRetain; #endif
};
小结:
- 通常情况下,智能指针分为sp和wp
- 目标对象的父类是RefBase——这个基类提供了一个weakref_impl类型的引用计数器,可以同时进行强弱引用的控制
android分析之智能指针的更多相关文章
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6786239 Android 系统的运行时库层代 ...
- ZT自老罗的博客 Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
Android系统的智能指针(轻量级指针.强指针和弱指针)的实现原理分析 分类: Android 2011-09-23 00:59 31568人阅读 评论(42) 收藏 举报 androidclass ...
- Android系统智能指针的设计思路(轻量级指针、强指针、弱指针)
本博客为原创,转载请注明出处,谢谢. 参考博文:Android系统的智能指针(轻量级指针.强指针和弱指针)的实现原理分析 C++中最容易出错的地方莫过于指针了,指针问题主要有两类,一是内存泄露,二是无 ...
- Android智能指针SP WP使用方法介绍
Android手机操作系统既然是开源的操作系统.那么在具体的文件夹中就会存放着各种相关功能的开源代码.我们在使用的时候可以根据这些源代码进行相应的修改就能轻松的完成我们所需的功能.在这里大家就一起来看 ...
- c++智能指针介绍_补充
不明白我做错了什么,这几天老婆给我冷战了起来,也不给我开视频让我看娃了..哎,心累!趁着今晚的一些空闲时间来对智能指针做个补充吧. 写完上篇“智能指针介绍”后,第二天上班途中时,突然一个疑问盘踞在心头 ...
- React Native 4 for Android源码分析 一《JNI智能指针之介绍篇》
文/ Tamic: http://blog.csdn.net/sk719887916/article/details/53455441 原文:http://blog.csdn.net/eewolf/a ...
- Android结构分析Android智能指针(两)
笔者:刘蒿羽 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中,我们分析了Android智能指针中的强指针sp,本文我们来分析弱指 ...
- Android智能指针sp wp详解
研究Android的时候,经常会遇到sp.wp的东西,网上一搜,原来是android封装了c++中对象回收机制.说明:1. 如果一个类想使用智能指针,那么必须满足下面两个条件: a. 该类是虚基 ...
- ReactNative 4Android源码分析二: 《JNI智能指针之实现篇》
文/Tamic http://blog.csdn.net/sk719887916/article/details/53462268 回顾 上一篇介绍了<ReactNative4Android源码 ...
随机推荐
- js console 性能测试 & don't-use-array-foreach-use-for-instead
don't-use-array-foreach-use-for-instead slower https://coderwall.com/p/kvzbpa/don-t-use-array-foreac ...
- CSS font-weight all in one
CSS font-weight all in one font-weight: bolder: 没毛病呀! /* 关键字值 */ font-weight: normal; font-weight: b ...
- javascript algorithm visualization
javascript algorithm visualization javascript算法可视化 https://algorithm-visualizer.org https://github.c ...
- URLSearchParams & GET Query String & JSON
URLSearchParams & GET Query String & JSON https://developer.mozilla.org/zh-CN/docs/Web/API/U ...
- Dart: 编码和解码各种存档和压缩格式
path archive import 'dart:io'; import 'package:path/path.dart' as p; import 'package:path/path.dart' ...
- 06_MySQL数据类型
MySQL数据类型
- Java如何保证文件落盘?
本文转载自Java如何保证文件落盘? 导语 在之前的文章Linux/UNIX编程如何保证文件落盘中,我们聊了从应用到操作系统,我们要如何保证文件落盘,来确保掉电等故障不会导致数据丢失.JDK也封装了对 ...
- react性能提升
1.把.bind(this)提升到constructor里面 2.在生命周期函数里面shouldComponentupdate里面做父组件改变重新渲染以致于子组件重新渲染的禁止 3.在setstate ...
- Winform 判断打印机是否可用,实现设置默认打印机功能
Winform 判断打印机是否可用,实现设置默认打印机功能 http://www.cnblogs.com/zfanlong1314/p/3878563.html
- servlet内置对象(传递数据)
一个servlet向另一个servlet发送数据,可以将数据放置在一个容器中(io.数据库.servlet的内置对象),servlet的内置对象成本最小. 一共有三个内置对象. 名字 类型 reque ...