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
// The contents of this file is licensed by its authors and copyright holders under the Apache // License (Version 2.0), MIT license, or Mozilla Public License (Version 2.0), at your option. The // contents of this file may not be copied, modified, or distributed except according to those // terms. See the COPYRIGHT file at the top-level directory of this distribution for copies of these // licenses and more information. // See https://github.com/opensource-apple/objc4/blob/master/runtime/objc-internal.h // and https://clang.llvm.org/docs/AutomaticReferenceCounting.html extern crate core; extern crate libc; use objc; #[link(name = "objc")] extern "C" { pub fn objc_autoreleasePoolPush() -> *mut libc::c_void; pub fn objc_autoreleasePoolPop(pool: *mut libc::c_void); pub fn objc_retain(obj: objc::id) -> objc::id; pub fn objc_release(obj: objc::id); pub fn objc_retainAutorelease(obj: objc::id) -> objc::id; pub fn objc_loadWeakRetained(location: *mut objc::id) -> objc::id; } // TODO: I think that this macro should be removed. Consider the following code: // fn do_stuff() { // autoreleasepool!{ // return; // } // } // I believe the return statement would result in the autoreleasepool not being popped. // This could possibly be fixed by using a gaurd variable with a Drop implementation that pops the pool, but I'm not sure that's foolproof. #[macro_export] macro_rules! autoreleasepool { ($($tt: tt)*) => { // Compiling the Objective-C program `int main() {@autoreleasepool{} return 0;}` shows that // clang doesn't check the return value of the pool push. If clang never does it, then I feel // comfortable not doing it here either (plus I've looked through the Objective-C runtime code // and I don't think our lack of null-checking here can be problematic). // TODO: does this need to be surrounded in {} for any reason? let pool = unsafe { objc_autoreleasePoolPush() }; {$($tt)*;} unsafe { objc_autoreleasePoolPop(pool) }; }; } // TODO: What happens to autoreleasepools when an exception is thrown (before the pool is popped)? How does Objective-C handle it, and does objrs match it? #[inline] pub fn autoreleasepool<F>(f: F) where F: FnOnce(), { autoreleasepool!{ f(); } }