天天看點

NSAutoreleasePool實作原理

先來看一下NSAutoreleasePool的屬性和方法

@interfaceNSAutoreleasePool : NSObject {
@private
   void   *_token;      //pool對應的POOL_SENTINEL的記憶體位址
void  *_reserved3;
void  *_reserved2;
void  *_reserved;
}
 
+ (void)addObject:(id)anObject;
 
- (void)addObject:(id)anObject;
 
- (void)drain;
 
@end
           

作用:NSAutoreleasePool隻是延遲了對象的釋放,配合ARC機制完成系統對記憶體的管理,在釋放池收到drain消息的時候将會對池中所有的對象執行一次release操作。

NSAutoreleasePool本身沒有一個具體的記憶體結構,可以将它看成是一個由NSAutoreleasePoolPage作為節點構成的雙向連結清單,那麼問題來了,什麼又是NSAutoreleasePoolPage呢

對NSAutoreleasePool,可以總結出以下幾點:

1.一個線程的NSAutoreleasePool其實就是一個指針的堆棧,其中每一個指針代表一個需要release的對象或者POOL_SENTINEL(哨兵對象,代表一個釋放池的邊界),之是以說是或者,是因為剛開始添加進入的是哨兵,後來添加的不再是哨兵,而是實實在在的需要release的對象

2.一個pool_token就是這個NSAutoreleasePool所對應的POOL_SENTINEL在記憶體中的位址,當NSAutoreleasePool被pop的時候,記憶體位址在pool_token之後的對象都将被release;

單個的NSAutoreleasePool的運作過程可以簡化為三個操作:NSAutoreleasePoolPage::push,autorelease,NSAutoreleasePoolPage::pop ;

1.NSAutoreleasePoolPage::push

       一個push操作其實就是建立一個新的NSAutoreleasePool,對應NSAutoreleasePool的具體實作其實就是往NSAutoreleasePool的next位置插入一個POOL_SENTINEL(哨兵),并且傳回POOL_SENTINEL的記憶體位址(就是前面提到的pool_token),在後面的pop操作中作為參數傳入;

2.autorelease

       autorelease操作與push操作比較類似,都是在連結清單的next位置插入一個對象,差別在于前者插入的是一個實實在在的需要release的對象,而後者則是插入一個哨兵對象;

3.NSAutoreleasePoolPage::pop

       pop執行時利用push操作傳回的pool_token作為參入參數,将記憶體位址在pool_token之後的所有autoreleased對象都釋放掉;