Skip to content

Commit b5297b9

Browse files
committed
Document Id::retain_autoreleased
1 parent 5d1b3f9 commit b5297b9

2 files changed

Lines changed: 32 additions & 7 deletions

File tree

objc2/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1414
* Added convenience methods `Id::new_null`, `Id::as_ptr` and
1515
`Id::retain_null`.
1616
* The `objc2-encode` dependency is now exposed as `objc2::encode`.
17+
* `Id::retain_autoreleased` to make following Cocoas memory management rules
18+
more efficient.
1719

1820

1921
## 0.3.0-alpha.6 - 2022-01-03

objc2/src/rc/id.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ impl<T: Message, O: Ownership> Id<T, O> {
216216
/// some API, and you would like to ensure that the object stays around
217217
/// so that you can work with it.
218218
///
219+
/// If said API is a normal Objective-C method, you probably want to use
220+
/// [`Id::retain_autoreleased`] instead.
221+
///
219222
/// This is rarely used to construct owned [`Id`]s, see [`Id::new`] for
220223
/// that.
221224
///
@@ -272,29 +275,49 @@ impl<T: Message, O: Ownership> Id<T, O> {
272275
NonNull::new(ptr).map(|ptr| unsafe { Id::retain(ptr) })
273276
}
274277

275-
/// TODO
278+
/// Retains a previously autoreleased object pointer.
279+
///
280+
/// This is useful when calling Objective-C methods that return
281+
/// autoreleaed objects, see [Cocoa's Memory Management Policy][mmRules].
282+
///
283+
/// This has exactly the same semantics as [`Id::retain`], except it can
284+
/// sometimes avoid putting the object into the autorelease pool, possibly
285+
/// yielding increased speed and reducing memory pressure.
286+
///
287+
/// Note: This relies heavily on being inlined right after [`msg_send!`],
288+
/// be careful not accidentally require instructions between these.
289+
///
290+
/// [mmRules]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
291+
///
292+
/// # Safety
293+
///
294+
/// Same as [`Id::retain`].
276295
#[doc(alias = "objc_retainAutoreleasedReturnValue")]
277-
// This relies heavily on being inlined right after `objc_msgSend`.
278296
#[inline(always)]
279297
pub unsafe fn retain_autoreleased(ptr: NonNull<T>) -> Id<T, O> {
280298
// Add magic nop instruction to participate in the fast autorelease
281299
// scheme.
282300
//
301+
// See `callerAcceptsOptimizedReturn` in `objc-object.h`:
302+
// https://github.com/apple-oss-distributions/objc4/blob/objc4-838/runtime/objc-object.h#L1209-L1377
303+
//
283304
// We will unconditionally emit these instructions, even if they end
284305
// up being unused (for example because we're unlucky with inlining,
285306
// some other work is done between the objc_msgSend and this, or the
286307
// runtime version is too old to support it).
287308
//
288-
// See `callerAcceptsOptimizedReturn` in `objc-object.h`:
289-
// https://github.com/apple-oss-distributions/objc4/blob/objc4-838/runtime/objc-object.h#L1209-L1377
290-
// and this StackOverflow answer for some background on why the design
291-
// is like it is: https://stackoverflow.com/a/23765612.
292-
//
293309
// It may seem like there should be a better way to do this, but
294310
// emitting raw assembly is exactly what Clang and Swift does:
295311
// swiftc: https://github.com/apple/swift/blob/swift-5.5.3-RELEASE/lib/IRGen/GenObjC.cpp#L148-L173
296312
// Clang: https://github.com/llvm/llvm-project/blob/889317d47b7f046cf0e68746da8f7f264582fb5b/clang/lib/CodeGen/CGObjC.cpp#L2339-L2373
297313
//
314+
// Resources:
315+
// - https://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html
316+
// - https://www.galloway.me.uk/2012/02/how-does-objc_retainautoreleasedreturnvalue-work/
317+
// - https://github.com/gfx-rs/metal-rs/issues/222
318+
// - https://news.ycombinator.com/item?id=29311736
319+
// - https://stackoverflow.com/a/23765612
320+
//
298321
// SAFETY:
299322
// Based on https://doc.rust-lang.org/stable/reference/inline-assembly.html#rules-for-inline-assembly
300323
//

0 commit comments

Comments
 (0)