美文网首页
自动释放池的实现原理

自动释放池的实现原理

作者: 有一种再见叫青春 | 来源:发表于2016-11-14 16:29 被阅读63次

    顾名思义,autorelease就是自动释放.这看上去很像ARC,但实际上它更类似于C语言中的自动变量的特性
    <pre>
    {
    int a;
    }
    因超出变量作用域int a 被废弃,不可访问.
    </pre>

    autolease会像C语言的自动变量那样对待对象实例.当超出作用域时,对象实例的release实例方法被调用.autorelease的具体使用方法如下:
    <li>生成并持有NSAutoreleasePool对象</li>
    <li>调用已分配对象的autolease实例方法</li>
    <li>废弃NSAutoreleasePool对象</li>

    NSAutoreleasePool对象的生存周期相当于C语言变量的作用域.对于所有掉用过autorelease实例方法的对象,在废弃NSAutoreleasePool对象时,都将调用release方法.源码如下:
    <pre>NSAutoreleasePool *pool =[ [NSAutoreleasePool alloc]init]; id obj = [NSObject alloc]init; [obj autolease]; [pool drain]; <==> [obj release];</pre>

    在Cocoa框架中,相当于主程序主循环的NSRunLoop或者在其他程序可运行的地方,对NSAutoreleasePool对象进行生层,持有和废弃处理.因此,应用程序开发者不一定非得使用NSAutoreleasePool对象进行开发工作.

    NSRunLoop每次循环中NSAutoreleasePool对象被生成或废弃

    <li>生成NSAutoreleasePool对象</li>
    <li>应用程序主线程处理操作</li>
    <li>废弃NSAutoreleasePool对象</li>

    尽管如此,但在大量产生autorelease的对象时,只要不废弃NSAutoreleasePool对象,那么生成的对象就不会被释放,因此会产生内存不足的现象.典型的例子就是读入大量图像的同时改变尺寸
    <pre>`
    for (int i = 0 i< 图像数; i++)
    {
    //读入图像
    //大量产生autorelease的对象
    //由于没有废弃NSAutoreleasePool对象,导致内存不足
    }

    `</pre>

    在此情况下,有必要在适当的地方生成,持有或废弃NSAutoreleasePool对象.

    <pre>for (int i = 0 i< 图像数; i++) { //读入图像 //大量产生autorelease的对象 [pool darin]; }</pre>
    另外,Cocoa框架中也有很多类方法用于返回autorelease的对象.比如NSMutableArray类的arrayWithCapactiy类方法.

    <pre>id array = [NSMutableArray arrayWithCapactiy:1] =>
    id array = [[[NSMutableArray alloc] initWithCapactiy:1] autolease];
    </pre>

    <ol>总结思考</ol>

    <li>NSAutoreleasePool的生命周期问题与RunLoop的关系</li>
    <li>类方法内部实现的原理</li>

    下面来说说autorelease的实现原理.

    以下以GNUstep的源代码为例
    <pre>-(id) autorelease { [NSAutoreleasePool addObject:self]; }</pre>

    <pre>+(void) addObject: (id)anObj { NSAutoreleasePool *Pool = 取得正在使用的NSAutoreleasePool对象; if(pool != nil) { [pool addObject:anObj]; }else { NSLog(@"NSAutoreleasePool对象非存在状态下调用NSAutorelease"); } }</pre>

    苹果中的实现

    <pre>`
    class AutoreleasePoolPage
    {
    static inline void *push ()
    {
    相当于生成或持有NSAutoreleasePool类对象;
    }
    static inline void *pop (void * token)
    {
    相当于废弃NSAutoreleasePool类对象;
    releaseAll( ) ;
    }
    static inline id autorelease (id obj )
    {
    相当于NSAutoreleasePool类的addObject类方法
    AutoreleasePoolPage *autoreleasePoolPage =取得正在使用的AutoreleasePoolPage实例;
    autoreleasePoolPage->add(obj)
    }
    id *add (id obj)
    {
    将对象追加到内部数组中;
    }
    void releaseAll
    {
    调用内部数组中对象的releasse方法;
    }
    };

    void *objc_autoreleasePoolPush(void)
    {
    return AutoreleasePoolPage::push ( );
    }

    void *objc_autoreleasePoolPop(void * ctxt)
    {
    return AutoreleasePoolPage::pop (ctxt );
    }

    id *objc_autorelease (id obj)
    {
    return AutoreleasePoolPage::autorelease (obj );
    }
    `</pre>

    关于具体实现细节,可以查看以下几篇文章
    深入理解RunLoop
    自动释放池的前世今生
    Objective-C Autorelease Pool 的实现原理

    相关文章

      网友评论

          本文标题:自动释放池的实现原理

          本文链接:https://www.haomeiwen.com/subject/fhehpttx.html