In
live state an object is alive. Its reference counts are initialized to 1
strong, 1
unowned and 1
weak (side table starts at +1).
Strong and
unowned reference access work normally. Once there is a weak reference to the object, the side table is created. The
weak reference points to the
side table instead of the object.
From the
live state, the object moves into the
deiniting state once strong reference count reaches zero. The
deiniting state means that deinit() is in progress. At this point strong ref operations have no effect.
Weak reference reads return nil, if there is an associated side table (otherwise there are no weak refs).
Unowned reads trigger assertion failure. New
unowned references can still be stored. From this state, the object can take two routes:
- A shortcut in case there no weak, unowned references and the side table. The object transitions to the dead state and is removed from memory immediately.
- Otherwise, the object moves to deinited state
In the
deinited state deinit() has been completed and the object has outstanding
unowned references (at least the initial +1).
Strong and
weak stores and reads cannot happen at this point.
Unowned stores also cannot happen.
Unowned reads trigger assertion error. The object can take two routes from here:
- In case there are no weak references, the object can be deallocated immediately. It transitions into the dead state.
- Otherwise, there is still a side table to be removed and the object moves into the freed state.
In the
freed state the object is fully deallocated, but its side table is still alive. During this phase the
weak reference count reaches zero and the side table is destroyed. The object transitions into its final state.
In the
dead state there is nothing left from the object, except for the pointer to it. The pointer to the HeapObject is freed from the
Heap, leaving no traces of the object in memory.