if type T
is an NSObject
descendant, then it will support these messages:
+ (T *)alloc;
- (T *)init:(T *)self;
- (void)release;
- (T *)retain;
Objects (technically, variables of type T *
where T
is class type) can be either owned or not.
Assuming T
is class type, p
is a pointer to T
(i.e. T *
), we write OWNED(p)
to mean that p
is owned.
If an object is owned, then it must be released when done with it.
I'll just assume that we have a substructural type system where class types are linear.
Basically, if you have a variable x
, such that it is of type T
, and T
is a class
type, then you HAVE to treat it like a resource. Once you have x
, you cannot simply duplicate/alias it,
or forget about it.
- use
[x release]
to get rid of it. - use
T *y = [x retain]
to duplicate it.x
is still owned, buty
is also owned! so you'll have to get rid of both of them now.
These rules answer the question: how do the owned pointers get introduced in programs?
-
if you create an object using a method starting with
alloc
,copy
,new
, you own it.ex 1:
T *p = [[T alloc] init];
ex 2: assume that
T *p
T *q = [p copy];
ex 3:
T *p = [T new];
-
if you are passed an object and you want to keep it after the current method exits, then you need to
retain
it:-(void) method:(T *)p; { // do: `p retain` before saving to member variable // do NOT: `p retain` "just because". // do NOT: `p release`. // do NOT: alias `p`. you can, technically, but it will get confusing, fast. // kinda similar to ATS usage of `x: !T` where `T` is linear type. }
This rule deals with getting rid of owned pointers in programs.
If you own an object, you must release
it when done.
ex 1:
assume we are in dealloc
method and T *p
is owned.
RELEASE(p);
ex 2:
assume we are in any method, T *p
is owned, and it is a local variable.
RELEASE(p);
ex 3:
assume we are in any method, T *p
is owned, it is a local variable, and T *q
is a member variable.
RELEASE(q);
q = p;
if you have a T *p
an owned or non-owned pointer, you may pass it to other objects.
ex 1. passing p
to method of another object. assume P *object
where P
is class type, and P
has method with signature - (void)method:(T *)p
.
[object method:p];
NSAutoreleasePool
: a type of autorelease pools. it can be modeled as a stack of pools:
stack
: thread-local variable of autorelease poolstop(stack)
: in-use autorelease pool where each pool can hold pointers to objects it owns.
-
at almost every time there is a global
NSAutoreleasePool
in use. in command-line programs, you can always create anNSAutoreleasePool
at the beginning of the program inmain
function. in Cocoa programs, there will always be an in-use autorelease pool. -
objects respond to
autorelease
method by adding themselves to the currentNSAutoreleasePool
in use.[p autorelease];
-
objects in the pool are safe to use until the pool is drained.
-
an
NSAutoreleasePool
can be drained by calling thedrain
method, which will sendrelease
messages to all objects contained in the pool, and then release the pool itself.[p drain];
-
in Cocoa, the pool is drained after every
NSEvent
is sent. basically, every event is handled by creating a new pool, then performing the event handling, and finally by draining the pool. -
pools form a stack per thread, like regions from the literature. each new pool will be pushed to the top, and it will become in-use. draining the pool will pop it off the stack, reinstating its parent pool as the global one. assume
NSAutoreleasePool *p
is the pool in use.NSAutoreleasePool *p1 = [[NSAutoreleasePool alloc] init]; // `p1` is now in use, `p` is parent of `p1`. // any `autorelease` method calls on objects will make those objects add themselves to `p1`. [p1 drain]; // now `p` is in use, and `p1` is released as well as all objects that it owned.
-
some methods will put temporary objects onto the current autorelease pool. you may want to retain those objects if want to keep them.
rules for the autorelease
method:
assume T *p
is owned pointer.
[p autorelease];
or equivalently:
AUTORELEASE(p);
p
can still be used (its now owned by the current autorelease pool, but not the current method).