diff --git a/src/autorelease.rs b/src/autorelease.rs new file mode 100644 index 000000000..0665c2b22 --- /dev/null +++ b/src/autorelease.rs @@ -0,0 +1,39 @@ +use std::os::raw::c_void; +use runtime::{objc_autoreleasePoolPush, objc_autoreleasePoolPop}; + +// we use a struct to ensure that objc_autoreleasePoolPop during unwinding. +struct AutoReleaseHelper { + context: *mut c_void, +} + +impl AutoReleaseHelper { + unsafe fn new() -> Self { + AutoReleaseHelper { context: objc_autoreleasePoolPush() } + } +} + +impl Drop for AutoReleaseHelper { + fn drop(&mut self) { + unsafe { objc_autoreleasePoolPop(self.context) } + } +} + +/** +Execute `f` in the context of a new autorelease pool. The pool is drained +after the execution of `f` completes. This corresponds to @autoreleasepool blocks +in Objective-c and Swift. +*/ +pub fn autoreleasepool(f: F) { + let _context = unsafe { AutoReleaseHelper::new() }; + f(); +} + +#[cfg(test)] +mod tests { + use super::autoreleasepool; + + #[test] + fn test_pool() { + autoreleasepool(|| {}); + } +} diff --git a/src/lib.rs b/src/lib.rs index fc89cdddb..7257c87e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,8 @@ mod macros; pub mod runtime; pub mod declare; +mod autorelease; +pub use autorelease::autoreleasepool; mod encode; #[cfg(feature = "exception")] mod exception; diff --git a/src/runtime.rs b/src/runtime.rs index a98526615..af22d8bc1 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -109,6 +109,9 @@ extern { pub fn objc_allocateProtocol(name: *const c_char) -> *mut Protocol; pub fn objc_registerProtocol(proto: *mut Protocol); + pub fn objc_autoreleasePoolPush() -> *mut c_void; + pub fn objc_autoreleasePoolPop(context: *mut c_void); + pub fn protocol_addMethodDescription(proto: *mut Protocol, name: Sel, types: *const c_char, isRequiredMethod: BOOL, isInstanceMethod: BOOL); pub fn protocol_addProtocol(proto: *mut Protocol, addition: *const Protocol);