Skip to content

Commit

Permalink
Merge pull request #543 from samschott/updated-memory-management
Browse files Browse the repository at this point in the history
Updated memory management
  • Loading branch information
mhsmith authored Dec 5, 2024
2 parents f8199b1 + 51ba75b commit 99e7ae0
Show file tree
Hide file tree
Showing 6 changed files with 360 additions and 299 deletions.
5 changes: 5 additions & 0 deletions changes/256.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Retain Objective-C objects when creating Python wrappers and release them when the
Python wrapped is garbage collected. This means that manual ``retain`` calls and
subsequent ``release`` or ``autorelease`` calls from Python are no longer needed with
very few exceptions, for example when writing implementations of ``copy`` that return an
existing object.
5 changes: 5 additions & 0 deletions changes/256.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Manual calls to ``release`` or ``autorelease`` no longer cause Rubicon
to skip releasing an Objective-C object when its Python wrapper is
garbage collected. This means that fewer ``retain`` than ``release`` calls will cause
segfaults on garbage collection. Review your code carefully for unbalanced ``retain``
and ``release`` calls before updating.
43 changes: 27 additions & 16 deletions docs/how-to/memory-management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
Memory management for Objective-C instances
===========================================

Reference counting in Objective-C
=================================

Reference counting works differently in Objective-C compared to Python. Python
will automatically track where variables are referenced and free memory when
the reference count drops to zero whereas Objective-C uses explicit reference
Expand All @@ -13,28 +16,36 @@ When enabling automatic reference counting (ARC), the appropriate calls for
memory management will be inserted for you at compile-time. However, since
Rubicon Objective-C operates at runtime, it cannot make use of ARC.

Reference counting in Rubicon Objective-C
-----------------------------------------
Reference management in Rubicon
===============================

In most cases, you won't have to manage reference counts in Python, Rubicon
Objective-C will do that work for you. It does so by calling ``retain`` on an
object when Rubicon creates a ``ObjCInstance`` for it on the Python side, and calling
``autorelease`` when the ``ObjCInstance`` is garbage collected in Python. Retaining
the object ensures it is not deallocated while it is still referenced from Python
and releasing it again on ``__del__`` ensures that we do not leak memory.

The only exception to this is when you create an object -- which is always done
through methods starting with "alloc", "new", "copy", or "mutableCopy". Rubicon does
not explicitly retain such objects because we own objects created by us, but Rubicon
does autorelease them when the Python wrapper is garbage collected.

You won't have to manage reference counts in Python, Rubicon Objective-C will do
that work for you. It does so by tracking when you gain ownership of an object.
This is the case when you create an Objective-C instance using a method whose
name begins with ``alloc``, ``new``, ``copy``, or ``mutableCopy``. Rubicon
Objective-C will then insert a ``release`` call when the Python variable that
corresponds to the Objective-C instance is deallocated.
Rubicon Objective-C will not keep track if you additionally manually ``retain`` an
object. You will be responsible to insert appropriate ``release`` or ``autorelease``
calls yourself to prevent leaking memory.

An exception to this is when you manually ``retain`` an object. Rubicon
Objective-C will not keep track of such retain calls and you will be
responsible to insert appropriate ``release`` calls yourself.
Weak references in Objective-C
------------------------------

You will also need to pay attention to reference counting in case of **weak
references**. In Objective-C, creating a **weak reference** means that the
reference count of the object is not incremented and the object will still be
You will need to pay attention to reference counting in case of **weak
references**. In Objective-C, as in Python, creating a weak reference means that
the reference count of the object is not incremented and the object will be
deallocated when no strong references remain. Any weak references to the object
are then set to ``nil``.

Some objects will store references to other objects as a weak reference. Such
properties will be declared in the Apple developer documentation as
Some Objective-C objects store references to other objects as a weak reference.
Such properties will be declared in the Apple developer documentation as
"@property(weak)" or "@property(assign)". This is commonly the case for
delegates. For example, in the code below, the ``NSOutlineView`` only stores a
weak reference to the object which is assigned to its delegate property:
Expand Down
4 changes: 4 additions & 0 deletions docs/spelling_wordlist
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Alea
alloc
Autorelease
autorelease
autoreleased
autoreleases
Bugfixes
callables
CPython
Expand All @@ -22,6 +25,7 @@ lookups
macOS
metaclass
metaclasses
mutableCopy
namespace
namespaces
ObjC
Expand Down
Loading

0 comments on commit 99e7ae0

Please sign in to comment.