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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
//! 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 converted 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 one can attempt to load them and obtain an `Id`, or
//! safely fail 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(feature = "apple", doc = "```")]
#![cfg_attr(not(feature = "apple"), doc = "```no_run")]
//! use objc2::{class, msg_send_id};
//! use objc2::rc::{autoreleasepool, Id, Shared, WeakId};
//! use objc2::runtime::Object;
//!
//! // Id will release the object when dropped
//! let obj: Id<Object, Shared> = unsafe {
//! msg_send_id![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 allocated;
mod autorelease;
mod id;
mod id_forwarding_impls;
mod id_traits;
mod ownership;
mod weak_id;
#[cfg(test)]
mod test_object;
pub use self::allocated::Allocated;
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)]
pub(crate) use self::test_object::{RcTestObject, ThreadTestData};
#[cfg(test)]
mod tests {
use core::marker::PhantomData;
use core::mem::size_of;
use super::{Id, Owned, Ownership, Shared, WeakId};
use crate::runtime::Object;
#[repr(C)]
struct TestType {
inner: Object,
}
#[repr(C)]
struct MyObject<'a> {
inner: Object,
p: PhantomData<&'a str>,
}
/// Test that `Id<T, O>` is covariant over `T`.
#[allow(unused)]
fn assert_id_variance<'a, 'b, O: Ownership>(
obj: &'a Id<MyObject<'static>, O>,
) -> &'a Id<MyObject<'b>, O> {
obj
}
/// Test that `WeakId<T>` is covariant over `T`.
#[allow(unused)]
fn assert_weak_id_variance<'a, 'b>(
obj: &'a WeakId<MyObject<'static>>,
) -> &'a WeakId<MyObject<'b>> {
obj
}
#[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 ()>()
);
}
}