Objective-C运行时如何知道弱引用的对象是否仍然存在? [英] How can the Objective-C runtime know whether a weakly referenced object is still alive?
问题描述
随着ARC的出现,提供了一些新功能,以使开发人员可以使用弱引用的对象. id objc_loadWeak(id *location)
是其中之一.该函数接收一个对应于内存中弱对象存储位置的参数,如果该对象仍然存在,则返回该对象;如果释放该对象,则返回nil
.
似乎当将对象obj
作为weak
存储在具有id objc_storeWeak(id *location, id obj)
的位置location
中时,将obj
置于弱映射"中,并以location
作为键.但是,为了检索obj
,objc_loadWeak
不仅可以使用location
作为键并返回对应于obj
的值.它还必须检查obj
是否仍然有效,以返回nil
(如果不再存在).
但是,objc_loadWeak
无法尝试读取对象的保留计数,因为该对象可能已被释放.此外,尽管弱映射objc_storeWeak
,objc_loadWeak
和NSObject
类在同一文件中实现(解决方案
NSObject的dealloc方法不会向弱映射发送信号,表明正在被释放的对象将要消失.
可以.
- [NSObject dealloc]
通话
_objc_rootDealloc(self);
依次调用
object_dispose()
依次调用
objc_destructInstance()
最终会调用
objc_clear_deallocating()
最后一个功能如下:
void
objc_clear_deallocating(id obj)
{
assert(obj);
assert(!UseGC);
SideTable *table = SideTable::tableForPointer(obj); /* *** THIS LINE *** */
// clear any weak table items
// clear extra retain count and deallocating bit
// (fixme warn or abort if extra retain count == 0 ?)
OSSpinLockLock(&table->slock);
if (seen_weak_refs) {
arr_clear_deallocating(&table->weak_table, obj); /* *** THIS LINE *** */
}
table->refcnts.erase(DISGUISE(obj)); /* *** THIS LINE *** */
OSSpinLockUnlock(&table->slock);
}
三个突出显示的行都具有魔力. SideTable
是在NSObject.mm
中实现的C ++类,其中的refcnts
成员变量完全像听起来那样:它保存引用计数.
With the advent of ARC, some new functions were made available to allow developers to play around with weakly referenced objects. id objc_loadWeak(id *location)
is one of them. This function receives one parameter correspoding to a location in memory where a weak object was stored and returns this object if it is still alive or nil
if it were deallocated.
It seems that when an object obj
is stored as weak
in a location location
with id objc_storeWeak(id *location, id obj)
, obj
is put in a "weak map", with location
as a key. However, in order to retrieve obj
, objc_loadWeak
can not only use location
as a key and return the value, which corresponds to obj
. It must also check whether obj
is still alive to return nil
if it is not anymore.
However, objc_loadWeak
can not try to read the object's retain count, because the object may have been deallocated. Moreover, although the weak map, objc_storeWeak
, objc_loadWeak
and the NSObject
class are implemented in the same file (NSObject.mm), NSObject
's dealloc
method doesn't signals to the weak map that the object that is being deallocated is going away.
So, how does the Objective-C runtime figure out whether a weak
object is still alive?
NSObject's dealloc method doesn't signals to the weak map that the object that is being deallocated is going away.
It does.
- [NSObject dealloc]
calls
_objc_rootDealloc(self);
which in turn invokes
object_dispose()
which in turn calls
objc_destructInstance()
which finally calls
objc_clear_deallocating()
This last function looks like this:
void
objc_clear_deallocating(id obj)
{
assert(obj);
assert(!UseGC);
SideTable *table = SideTable::tableForPointer(obj); /* *** THIS LINE *** */
// clear any weak table items
// clear extra retain count and deallocating bit
// (fixme warn or abort if extra retain count == 0 ?)
OSSpinLockLock(&table->slock);
if (seen_weak_refs) {
arr_clear_deallocating(&table->weak_table, obj); /* *** THIS LINE *** */
}
table->refcnts.erase(DISGUISE(obj)); /* *** THIS LINE *** */
OSSpinLockUnlock(&table->slock);
}
The three highlighted lines do the magic. SideTable
is a C++ class implemented in NSObject.mm
of which the refcnts
member variable does exactly what it sounds like it does: it holds reference counts.
这篇关于Objective-C运行时如何知道弱引用的对象是否仍然存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!