mtl_foundation/
autorelease.rs1use std::ffi::c_void;
21use std::ptr::NonNull;
22
23use mtl_sys::{class, msg_send_0, msg_send_1, sel};
24
25use crate::object::{Object, Referencing};
26
27#[repr(transparent)]
31#[derive(Clone)]
32pub struct AutoreleasePool(NonNull<c_void>);
33
34impl AutoreleasePool {
35 #[inline]
39 pub fn alloc() -> Option<Self> {
40 unsafe {
41 let ptr: *mut c_void = msg_send_0(class!(NSAutoreleasePool).as_ptr(), sel!(alloc));
42 Self::from_ptr(ptr)
43 }
44 }
45
46 #[inline]
50 pub fn init(&self) -> Option<Self> {
51 unsafe {
52 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
53 Self::from_ptr(ptr)
54 }
55 }
56
57 #[inline]
61 pub fn drain(&self) {
62 unsafe {
63 msg_send_0::<()>(self.as_ptr(), sel!(drain));
64 }
65 }
66
67 #[inline]
71 pub fn add_object(&self, object: &Object) {
72 unsafe {
73 let _: () = msg_send_1(self.as_ptr(), sel!(addObject:), object.as_ptr());
74 }
75 }
76
77 #[inline]
81 pub fn show_pools() {
82 unsafe {
83 msg_send_0::<()>(class!(NSAutoreleasePool).as_ptr(), sel!(showPools));
84 }
85 }
86
87 #[inline]
93 pub unsafe fn from_ptr(ptr: *mut c_void) -> Option<Self> {
94 NonNull::new(ptr).map(Self)
95 }
96
97 #[inline]
101 pub fn new() -> Option<Self> {
102 Self::alloc()?.init()
103 }
104}
105
106impl Referencing for AutoreleasePool {
107 #[inline]
108 fn as_ptr(&self) -> *const c_void {
109 self.0.as_ptr()
110 }
111}
112
113unsafe impl Send for AutoreleasePool {}
115unsafe impl Sync for AutoreleasePool {}
116
117impl std::fmt::Debug for AutoreleasePool {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 f.debug_struct("AutoreleasePool")
120 .field("ptr", &self.0)
121 .finish()
122 }
123}
124
125impl Drop for AutoreleasePool {
126 fn drop(&mut self) {
127 self.drain();
128 }
129}
130
131pub struct AutoreleasePoolScope {
135 pool: AutoreleasePool,
136}
137
138impl AutoreleasePoolScope {
139 #[inline]
141 pub fn new() -> Option<Self> {
142 AutoreleasePool::new().map(|pool| Self { pool })
143 }
144
145 #[inline]
147 pub fn pool(&self) -> &AutoreleasePool {
148 &self.pool
149 }
150}
151
152impl Default for AutoreleasePoolScope {
153 fn default() -> Self {
154 Self::new().expect("Failed to create autorelease pool")
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161
162 #[test]
163 fn test_autorelease_pool_size() {
164 assert_eq!(
166 std::mem::size_of::<AutoreleasePool>(),
167 std::mem::size_of::<*mut c_void>()
168 );
169 }
170}