How can the Objective-C runtime know whether a weakly referenced object is still alive?

老子叫甜甜 提交于 2020-01-04 06:50:14

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/14854635/how-can-the-objective-c-runtime-know-whether-a-weakly-referenced-object-is-still

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!