iOS autoreleasepool

1. 数据结构

//  AutoreleasePoolPage对象
class AutoreleasePoolPage 
{
    static pthread_key_t const key = AUTORELEASE_POOL_KEY;
    magic_t const magic;
    id *next;                        // 自动回收对象栈的栈指针(相当于sp)
    pthread_t const thread;          // 当前回收迟对应的线程
    AutoreleasePoolPage * const parent;// parent页指针 链表指针
    AutoreleasePoolPage *child; // child页指针 链表指针
}
  • parent和child使AutoreleasePoolPage对象组成一个双向链表
    iOS autoreleasepool_第1张图片
    双向链表
  • 栈(存储autorelease对象指针)
AutoreleasePoolPage ->
 id *next; // 相当于栈指针sp

// 看add方法
 id *add(id obj)
    {
        //assert(!full());
       // unprotect();
        id *ret = next;  // faster than `return next-1` because of aliasing
        *next++ = obj;
       // protect();
        return ret;
    }
  • 游标 hotPage()获取当前线程的当前AutoreleasePoolPage页
// 获取当前线程的hotPage
 static inline AutoreleasePoolPage *hotPage() 
    {
        AutoreleasePoolPage *result = (AutoreleasePoolPage *)
            tls_get_direct(key);
        if (result) result->fastcheck();
        return result;
    }

// 设置当前线程的hotPage
static inline void setHotPage(AutoreleasePoolPage *page) 
    {
        if (page) page->fastcheck();
        tls_set_direct(key, (void *)page);
    }
  • POOL_SENTINEL哨兵
#define POOL_SENTINEL nil // POOL_SENTINEL 这个很重要,是自动回收池栈帧的分隔符

备注:TLS(线程独享存储技术)
TSL的存储是每个线程独立的,互不干扰。
TLS是线程局部存储(Thread Local Storage)的缩写,在oc中通过这两个方法来使用:

static inline void *tls_get_direct(tls_key_t k) 
{ 
    assert(is_valid_direct_key(k));

    if (_pthread_has_direct_tsd()) {
        return _pthread_getspecific_direct(k);
    } else {
        return pthread_getspecific(k);
    }
}

static inline void tls_set_direct(tls_key_t k, void *value) 
{ 
    assert(is_valid_direct_key(k));

    if (_pthread_has_direct_tsd()) {
        _pthread_setspecific_direct(k, value);
    } else {
        pthread_setspecific(k, value);
    }
}

2.调用

// @autoreleasepool {} 
相当于 -->
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
     }
struct __AtAutoreleasePool {
  __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
  ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
  void * atautoreleasepoolobj;
};
相当于 -->
   void * atautoreleasepoolobj = objc_autoreleasePoolPush();  
   // do whatever you want
   objc_autoreleasePoolPop(atautoreleasepoolobj);


// 
void *objc_autoreleasePoolPush(void) {
    return AutoreleasePoolPage::push();
}
void objc_autoreleasePoolPop(void *ctxt) {
    AutoreleasePoolPage::pop(ctxt); // 执行所有autorelease对象的release
}

对象调用autorelease的过程

[obj autorelease] 相当于 --> AutoreleasePoolPage::autorelease(obj);
// 
static inline id autorelease(id obj)
    {
        id *dest __unused = autoreleaseFast(obj);
    }
 static inline id *autoreleaseFast(id obj)
    {
        AutoreleasePoolPage *page = hotPage();
        if (page && !page->full()) {
            return page->add(obj); // 添加对象指针到当前页的栈
        } else if (page) {
            return autoreleaseFullPage(obj, page); // 创建新的AutoreleasePoolPage,并add
        } else {
            return autoreleaseNoPage(obj); // 创建根AutoreleasePoolPage并add
        }
    }

///// autoreleaseNoPage
    id *autoreleaseNoPage(id obj)
    {
        // No pool in place.
        assert(!hotPage());

        if (obj != POOL_SENTINEL  &&  DebugMissingPools) {
            // We are pushing an object with no pool in place, 
            // and no-pool debugging was requested by environment.
            _objc_inform("MISSING POOLS: Object %p of class %s "
                         "autoreleased with no pool in place - "
                         "just leaking - break on "
                         "objc_autoreleaseNoPool() to debug", 
                         (void*)obj, object_getClassName(obj));
            objc_autoreleaseNoPool(obj);
            return nil;
        }

        // Install the first page.
        AutoreleasePoolPage *page = new AutoreleasePoolPage(nil);
        setHotPage(page);

        // Push an autorelease pool boundary if it wasn't already requested.
        if (obj != POOL_SENTINEL) {
            page->add(POOL_SENTINEL);
        }

        // Push the requested object.
        return page->add(obj);
    }

push和pop

 static inline void *push() 
    {
        id *dest;
        if (DebugPoolAllocation) {
            // Each autorelease pool starts on a new pool page.
            dest = autoreleaseNewPage(POOL_SENTINEL);
        } else {
            dest = autoreleaseFast(POOL_SENTINEL);
        }
        assert(*dest == POOL_SENTINEL);
        return dest;
    }

    static inline void pop(void *token) 
    {
        AutoreleasePoolPage *page;
        id *stop;

        page = pageForPointer(token);
        stop = (id *)token;
        if (DebugPoolAllocation  &&  *stop != POOL_SENTINEL) {
            // This check is not valid with DebugPoolAllocation off
            // after an autorelease with a pool page but no pool in place.
            _objc_fatal("invalid or prematurely-freed autorelease pool %p; ", 
                        token);
        }

        if (PrintPoolHiwat) printHiwat();

        page->releaseUntil(stop);

        // memory: delete empty children
        if (DebugPoolAllocation  &&  page->empty()) {
            // special case: delete everything during page-per-pool debugging
            AutoreleasePoolPage *parent = page->parent;
            page->kill();
            setHotPage(parent);
        } else if (DebugMissingPools  &&  page->empty()  &&  !page->parent) {
            // special case: delete everything for pop(top) 
            // when debugging missing autorelease pools
            page->kill();
            setHotPage(nil);
        } 
        else if (page->child) {
            // hysteresis: keep one empty child if page is more than half full
            if (page->lessThanHalfFull()) {
                page->child->kill();
            }
            else if (page->child->child) {
                page->child->child->kill();
            }
        }
    }

关键字

双向链表TLS(线程独享存储)分页的栈哨兵

子线程与auotrelease

你可能感兴趣的:(iOS autoreleasepool)