Table Of Contents

Programming Essential

Objective-C

After installing iGC .dmg package or explicitly applying compiler patches, your Xcode compilers are capable to generate GC enabled code for Objective-C/C++. Thus, you can develop an iGC app without using any C++ smart pointers or any iGC header files. In fact, iGC provides ARCGC_C mode that are source code compatible with Apple’s ARC.

Mix GC and non-GC codes together

Within an iGC app, different types of code can be mixed together, including non-GC code: MRR and ARC, and GC code: MRRGC, ARCGC and ARCGC_C.

For example, you can write UI code in ARCGC, performance sensitive code in MRRGC, and link them together with 3rd party libraries and Apple’s Frameworks written in MRR or ARC.

Non-GC code (MRR and ARC)

Non-GC code is consisted of Apple’s MRR and ARC. These code maintain per-object reference count either manually (MRR) or automatically (ARC). For writing these non-GC code, please reference Apple’s documents, e.g. Memory Management Programming Guide.

iGC collects cycles of properties of non-GC code (MRR and ARC) like below. YES

// MRR or ARC code
@interface Foo : NSObject
@property (nonatomic, retain) Foo *next;
@end

Foo * foo = [[Foo alloc] init];
foo.next = foo;     // iGC will collect this cycle

iGC cannot collect cycles of instance variable in MRR, because the instance variables could be unretained. details

iGC by default does not collect cycles of instance variable in ARC because of a bug in early ARC compiler. details

MRRGC code

By adding a compiler flag -fobjc-gc, Objective-C/C++ code are compiled under MRRGC.

instance variables are auto-retained and released

In MRRGC, instance variables will retain objects automatically. So, you don’t need to explicitly maintain reference count for instance variables.

Here is a demo of a setter implemented in MRR and MRRGC:

sidebyside

// MRR Example
- (void)setAnObject:(NSObject*)newValue {
    if (_anObject != newValue) {
       NSObject* oldValue = _anObject;
       _anObject = [newValue retain];
       [oldValue release];
    }
}
// MRRGC Example
- (void)setAnObject:(NSObject*)newValue {
    _anObject = newValue;
}

don’t explicit [release] ivars in [dealloc]

In MRRGC, because instance variables are automatic retained and released, you should no longer send [release] to instance variables, including those back your properties. Here is an example.

@interface Foo : NSObject
@property (nonatomic, retain) Foo *next;
@end

@implementation Foo
@synthesize next = _next;
- (void)dealloc {
    // [_next release]; <-- iGC already does this, skip it!
    [super dealloc];
}
@end

use __weak qualifier to break cycles

You can use __weak qualifier to specify an instance variable or a property to be weak, which does not retain object, to break cycles.

@interface Foo : NSObject {
@property (nonatomic, assign) __weak Foo *next;
@end

@implementation Foo
@synthesize next;
@end

everything else are the same as MRR

For everything else, they are the same as in MRR. For example, in stack local variables of a function do not automatically retain objects, you need to send [retain] or [release] when necessary, like this:

int main() {
    Foo *foo = [[Foo alloc] init];
    ...
    [foo release];      // need to send `[release]` as `foo' is not a ivar.
}

ARCGC and ARCGC_C code

ARCGC and ARCGC_C are designed to provide garbage collection for ARC. The code of ARCGC may look familiar to MRRGC while ARCGC_C is compatible with ARC.

To compile ARCGC code, add compiler flag -fobjc-arc-gc; To compile ARCGC_C code, add flags -fobjc-arc-gc -fobjc-arc-gc-compatible, or flags -fobjc-arc -fobjc-gc. see Compiler flags.

ARCGC_C source code is compatible with ARC

To write ARCGC_C code, you can just follow the documents of ARC programming. iGC does collect cycles of both ivars and properties of ARCGC_C code. However, these cyclic objects are collected randomly.

control reclamation ordering in ARCGC

In ARCGC, the keyword __strong has a special meaning. It enforces the reclamation ordering. If object A is referenced by a __strong property in object B, then object A will be kept alive until object B has deallocated. That is, in B’s [dealloc] method, it is safe to access A when GC is collecting A and B.

See Reclamation ordering for more information. In short, use __strong properties to reference objects that are used in [dealloc] of your object.

simple and clear syntax in ARCGC

For an instance variable, by default (if no qualifier specified) it will automatically retain object. There are two extra qualifiers, __weak for unretained and __autoweak for zeroing reference, can be added to the ivar declarations.

For a property, by default it will automatically retain object, and you can optionally specify property attributes (assign, retain, copy) and qualifiers (__strong, __weak, __autoweak).

[ __weak | __autoweak ] class * ivar;

@property (property attributes) [ __strong | __weak | __autoweak ] class * prop;

Here are some examples of ivar and property declarations.

@interface Foo : NSObject {
    Foo * _foo1;         // default (no qualifier): will retain object
    __weak Foo * _foo2;
    __autoweak Foo * _foo3;
}
@property Foo *foo4;    // default property: will retain object
@property __strong Foo *foo5;       // strong property: retain & safe in [dealloc]
@property __weak Foo *foo6;         // weak property
@property __autoweak Foo *foo7;     // autoweak property
@property (nonatomic, copy) __strong Foo * foo8;
@property (nonatomic, retain) Foo * foo9;
@end

@implementation Foo
@synthesize foo4, foo5, foo6, foo7, foo8, foo9;
...
@end

ARCGC and ARCGC_C provide auto-zeroing weak

ARCGC and ARCGC_C provide auto-zeroing weak similar to ARC weak reference, contents of which are cleared to avoid pointing to a deallocated object.

ARCGC uses __autoweak keyword to indicate an auto-zeroing weak variable or property, while ARCGC_C uses __weak keyword for ARC compatibility reason.

Note

Unlike ARC, you iGC app can use auto-zeroing weak for iOS earlier than 5.0, because you have linked in iGC runtime.

C++

In this section we are going to discuss using HnxGC in C++ language. Objective-C++ will be discussed in the next section.

You can use HnxGC using any C++ standard compiler, including GNU GCC4.2, LLVM-GCC-4.2 and Clang, no need to patch them and no special compiler flags required.

smart pointer

HnxGC provides a set of smart pointers for writing GC application code. A HnxGC smart pointer not only associates with the type(class) of object it would point to, but also associates with the role the smart pointer would play, e.g. the location(at heap or stack) where the smart pointer resides.

For your convenience, most smart pointers are wrapped under the gcptr<T> smart pointer umbrella each with a role specifier. For example, a input parameter of functions should use gcptr<T>::in to replace C/C++ T \* native type.

The T type of smart pointers can be omitted. Non-typed smart pointers can accept any type of pointers.

See C++ smart pointers for details. Here is a list of common-used smart pointers.

gcptr<>         // generic smart pointer, like C/C++ `void *'
gcptr<T>        // generic typed ptr, auto-detect locations in stack, heap, etc.
gcptr<T>::weak  // a weak ptr, fast without RC maintenance.
gcptr<T>::ret   // a return ptr of function/method
gcptr<T>::in    // a input ptr of parameter of a function/method
gcptr<T>::inout // a input and output parameter of a function/method
gcptr<T>::m     // a member variable ptr of an object
gcptr<T>::mm    // manual reported member ptr of an object
gcptr<T>::autoweak  // an auto-zeroing weak ptr
gcptr<T>::ref   // a reference to another gcptr<> pointer

gcnew

Replace C++ new operator with HnxGC gcnew to create a managed object or an array of managed objects in heap, of any types including class, struct and primitives.

gcptr<int> p = gcnew int(0);        // an integer with initial value of 0
p = gcnew int[100];                 // an array of 100 integers
gcptr<CGPoint> pPoint = gcnew CGPoint[20];  // an array of 20 CGPoint instances
gcptr<Foo> foo = gcnew Foo;         // an instance of class Foo
gcptr<Foo> foo = gcnew Foo[30];     // an array of 30 instances of class Foo

see gcnew for details.

class

You can define a GC-enabled C++ class or struct to use managed member pointers, like gcptr<T>::m, to hold objects and have cycles collected.

Here is an example:

class Foo {
public:
    HNXGC_ENABLE(Foo)                       // enable GC for class Foo

    gcptr<Foo>::m           m_pFoo;         // replace C++: Foo * m_pFoo;
    gcptr<sockaddr_in>::m   m_pAddr[5];     // replace C++: sockaddr_in * m_pAddr[5];
    gcptr<>                 m_pObject;      // replace C++: void * m_pObject;
};

see Class (C++) for details.

Objective-C++

If you use Objective-C++ in MRR, then you can use gcptr<> smart pointer to avoid manually retain/release on non-ivar variables, e.g. local variables in a function. Using smart pointers gives you a full control of your program, for example, your function is able to return an unretained pointer, while ARC forces you return an autoreleased.

Using smart pointer also makes your code more portable. For example, if you use gcptr<T>::i as an instance variable of an Objective-C object, then you can write a GC app without using a particular patched compiler. In theory, any Objective-C++ compilers can support iGC smart pointers.

Here is an exmple of Objective-C++ in MRR. It reimplements the ARCGC_C code in Quick Start)

// MRR code in ObjC++
#import <Foundation/Foundation.h>

#include "hnxgc.h"

@interface Foo : NSObject {
    gcptr<Foo>::i _next;     // full smart pointers using any non-GC compilers
    // Foo * _next;     <-- with a patched compiler you can do this
}
@end

@implementation Foo
- (void)dealloc {
    printf("Foo(%p) deallocated\n", self);
    [super dealloc];
}

int main() {
    @autoreleasepool {
        gcptr<Foo> foo = gcnew_i [[Foo alloc] init];

        foo->_next = foo;     // make a cycle of references
    }
    // ARC does not reclaim `foo' because of the cycle.

    printf("-- invoke GC collection explicitly --\n");
    HXSystem_gc();          // iGC specific function

    return 0;
}
@end