1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
//! Utilities for reference counting Objective-C objects.
//!
//! These utilities in this module provide ARC-like semantics for working with
//! Objective-C's reference counted objects.
//!
//! A smart pointer [`Id`] is provided to ensure that Objective-C objects are
//! retained and released when created and dropped, respectively.
//!
//! To enforce aliasing rules, an `Id` can be either owned or shared; if it is
//! owned, meaning the `Id` is the only reference to the object, it can be
//! mutably dereferenced. An owned `Id` can be downgraded to a shared `Id`
//! which can be cloned to allow multiple references.
//!
//! Weak references may be created using the [`WeakId`] struct; these will not
//! retain the object, but they can upgraded to an `Id` in a manner that
//! safely fails if the object has been deallocated.
//!
//! See [the clang documentation][clang-arc] and [the Apple article on memory
//! management][mem-mgmt] (similar document exists [for Core Foundation][cf])
//! for more information on automatic and manual reference counting.
//!
//! It can also be useful to [enable Malloc Debugging][mem-debug] if you're trying
//! to figure out if/where your application has memory errors and leaks.
//!
//! [clang-arc]: https://clang.llvm.org/docs/AutomaticReferenceCounting.html
//! [mem-mgmt]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
//! [cf]: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/CFMemoryMgmt.html
//! [mem-debug]: https://developer.apple.com/library/archive/documentation/Performance/Conceptual/ManagingMemory/Articles/MallocDebug.html
//!
//!
//! ## Example
//!
#![cfg_attr(apple, doc = "```")]
#![cfg_attr(not(apple), doc = "```no_run")]
//! use objc2::{class, msg_send};
//! use objc2::rc::{autoreleasepool, Id, Shared, WeakId};
//! use objc2::runtime::Object;
//!
//! // Id will release the object when dropped
//! let obj: Id<Object, Shared> = unsafe {
//! Id::new(msg_send![class!(NSObject), new])
//! };
//!
//! // Cloning retains the object an additional time
//! let cloned = obj.clone();
//! autoreleasepool(|pool| {
//! // Autorelease consumes the Id, but won't
//! // actually release until the end of an autoreleasepool
//! let obj_ref: &Object = cloned.autorelease(pool);
//! });
//!
//! // Weak references won't retain the object
//! let weak = WeakId::new(&obj);
//! drop(obj);
//! assert!(weak.load().is_none());
//! ```
mod autorelease;
mod id;
mod id_forwarding_impls;
mod id_traits;
mod ownership;
mod weak_id;
pub use self::autorelease::{autoreleasepool, AutoreleasePool, AutoreleaseSafe};
pub use self::id::Id;
pub use self::id_traits::{DefaultId, SliceId, SliceIdMut};
pub use self::ownership::{Owned, Ownership, Shared};
pub use self::weak_id::WeakId;
#[cfg(test)]
mod tests {
use core::mem::size_of;
use super::{Id, Owned, Shared, WeakId};
struct TestType {
_data: [u8; 0], // TODO: `UnsafeCell`?
}
#[test]
fn test_size_of() {
assert_eq!(size_of::<Id<TestType, Owned>>(), size_of::<&TestType>());
assert_eq!(size_of::<Id<TestType, Shared>>(), size_of::<&TestType>());
assert_eq!(
size_of::<Option<Id<TestType, Owned>>>(),
size_of::<&TestType>()
);
assert_eq!(
size_of::<Option<Id<TestType, Shared>>>(),
size_of::<&TestType>()
);
assert_eq!(
size_of::<Option<WeakId<TestType>>>(),
size_of::<*const ()>()
);
}
}