From 5d7be8e18e74d63159a0c6242d2273345792841a Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Sun, 18 Nov 2018 21:29:32 -0500 Subject: [PATCH] Fix conditional compilation guards --- .gitignore | 1 + examples/release_mode.rs | 19 ++++++++++++ qadapt-macro/src/lib.rs | 62 +++++++++++++++++++--------------------- src/lib.rs | 57 ++++++++++++++++++++++-------------- tests/allocations.rs | 6 ++-- tests/macros.rs | 18 ++++++++---- 6 files changed, 101 insertions(+), 62 deletions(-) create mode 100644 examples/release_mode.rs diff --git a/.gitignore b/.gitignore index 2fcd2ae..2886cee 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ **/*.rs.bk Cargo.lock *.swp +.idea/ \ No newline at end of file diff --git a/examples/release_mode.rs b/examples/release_mode.rs new file mode 100644 index 0000000..50bff3e --- /dev/null +++ b/examples/release_mode.rs @@ -0,0 +1,19 @@ +extern crate qadapt; + +use qadapt::allocate_panic; +use qadapt::QADAPT; + +#[global_allocator] +static Q: QADAPT = QADAPT; + +#[allocate_panic] +fn does_allocate() -> Box { + Box::new(0) +} + +fn main() { + // If you were to run `cargo run --example release_mode`, this program blows up. + // If, however, you ran `cargo run --release --example release_mode`, + // nothing interesting will happen. + does_allocate(); +} diff --git a/qadapt-macro/src/lib.rs b/qadapt-macro/src/lib.rs index aea5bb6..70c78a1 100644 --- a/qadapt-macro/src/lib.rs +++ b/qadapt-macro/src/lib.rs @@ -58,35 +58,6 @@ macro_rules! token_stream { }; } -#[rustfmt::skip] -fn release_guard(fn_name: &str) -> TokenStream { - // #[cfg(any(debug, test))] - // { ::qadapt::`fn_name`() } - token_stream!( - punct!('#', Spacing::Alone), - group!(Delimiter::Bracket, token_stream!( - ident!("cfg"), - group!(Delimiter::Parenthesis, token_stream!( - ident!("any"), - group!(Delimiter::Parenthesis, token_stream!( - ident!("debug"), - punct!(',', Spacing::Alone), - ident!("test") - )), - )), - )), - group!(Delimiter::Brace, token_stream!( - punct!(':', Spacing::Joint), - punct!(':', Spacing::Alone), - ident!("qadapt"), - punct!(':', Spacing::Joint), - punct!(':', Spacing::Alone), - ident!(fn_name), - group!(Delimiter::Parenthesis) - )) - ) -} - /// Generate the body of a function that is protected from making allocations. /// The code is conditionally compiled so that all QADAPT-related bits /// will be removed for release/bench builds, making the proc_macro safe @@ -94,7 +65,15 @@ fn release_guard(fn_name: &str) -> TokenStream { #[rustfmt::skip] fn protected_body(fn_body: Group) -> TokenTree { group!(Delimiter::Brace, token_stream!( - group!(Delimiter::Brace, release_guard("enter_protected")), + group!(Delimiter::Brace, token_stream!( + punct!(':', Spacing::Joint), + punct!(':', Spacing::Alone), + ident!("qadapt"), + punct!(':', Spacing::Joint), + punct!(':', Spacing::Alone), + ident!("enter_protected"), + group!(Delimiter::Parenthesis) + )), ident!("let"), ident!("__ret__"), punct!('=', Spacing::Alone), @@ -110,7 +89,15 @@ fn protected_body(fn_body: Group) -> TokenTree { )) )), group!(Delimiter::Brace, token_stream!( - group!(Delimiter::Brace, release_guard("exit_protected")), + group!(Delimiter::Brace, token_stream!( + punct!(':', Spacing::Joint), + punct!(':', Spacing::Alone), + ident!("qadapt"), + punct!(':', Spacing::Joint), + punct!(':', Spacing::Alone), + ident!("exit_protected"), + group!(Delimiter::Parenthesis) + )), ident!("__ret__") )) )) @@ -129,7 +116,18 @@ fn escape_return(ts: TokenStream) -> TokenStream { vec![group!(Delimiter::Brace, escape_return(g.stream()))] } TokenTree::Ident(ref i) if i.to_string() == "return" && !in_closure => vec![ - group!(Delimiter::Brace, release_guard("exit_protected")), + group!( + Delimiter::Brace, + token_stream!( + punct!(':', Spacing::Joint), + punct!(':', Spacing::Alone), + ident!("qadapt"), + punct!(':', Spacing::Joint), + punct!(':', Spacing::Alone), + ident!("exit_protected"), + group!(Delimiter::Parenthesis) + ) + ), tt.clone(), ], TokenTree::Punct(ref p) if p.as_char() == '|' => { diff --git a/src/lib.rs b/src/lib.rs index 13db516..4a2abad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,42 +39,55 @@ pub struct QADAPT; /// Let QADAPT know that we are now entering a protected region and that /// panics should be triggered if allocations/drops happen while we are running. pub fn enter_protected() { - if thread::panicking() { - return; - } + #[cfg(debug_assertions)] + { + if thread::panicking() { + return; + } - PROTECTION_LEVEL - .try_with(|v| { - *v.write() += 1; - }) - .unwrap_or_else(|_e| ()); + PROTECTION_LEVEL + .try_with(|v| { + *v.write() += 1; + }) + .unwrap_or_else(|_e| ()); + } } /// Let QADAPT know that we are exiting a protected region. Will panic /// if we attempt to [`exit_protected`] more times than we [`enter_protected`]. pub fn exit_protected() { - if thread::panicking() { - return; - } + #[cfg(debug_assertions)] + { + if thread::panicking() { + return; + } - PROTECTION_LEVEL - .try_with(|v| { - let val = { *v.read() }; - match val { - v if v == 0 => panic!("Attempt to exit protected too many times"), - _ => { - *v.write() -= 1; + PROTECTION_LEVEL + .try_with(|v| { + let val = { *v.read() }; + match val { + v if v == 0 => panic!("Attempt to exit protected too many times"), + _ => { + *v.write() -= 1; + } } - } - }) - .unwrap_or_else(|_e| ()); + }) + .unwrap_or_else(|_e| ()); + } } static INTERNAL_ALLOCATION: RwLock = RwLock::new(usize::max_value()); /// Get the current "protection level" in QADAPT: calls to enter_protected() - exit_protected() pub fn protection_level() -> usize { - PROTECTION_LEVEL.try_with(|v| *v.read()).unwrap_or(0) + #[cfg(debug_assertions)] + { + PROTECTION_LEVEL.try_with(|v| *v.read()).unwrap_or(0) + } + #[cfg(not(debug_assertions))] + { + 0 + } } fn claim_internal_alloc() { diff --git a/tests/allocations.rs b/tests/allocations.rs index 13616a8..474be54 100644 --- a/tests/allocations.rs +++ b/tests/allocations.rs @@ -17,7 +17,7 @@ fn test_copy() { } #[test] -#[should_panic] +#[cfg_attr(debug_assertions, should_panic)] fn test_allocate() { enter_protected(); let _x = Box::new(12); @@ -90,7 +90,7 @@ fn vec_with_one() { } #[test] -#[should_panic] +#[cfg_attr(debug_assertions, should_panic)] fn exit_too_often() { enter_protected(); exit_protected(); @@ -98,7 +98,7 @@ fn exit_too_often() { } #[test] -#[should_panic] +#[cfg_attr(debug_assertions, should_panic)] fn intentional_drop() { let v: Vec<()> = Vec::new(); let v = Box::new(v); diff --git a/tests/macros.rs b/tests/macros.rs index 6aae496..455a204 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -9,11 +9,6 @@ static Q: QADAPT = QADAPT; #[allocate_panic] fn no_allocate() { - #[cfg(not(release))] - { - let _v = 0; - } - assert_eq!(::qadapt::protection_level(), 1); let _v: Vec<()> = Vec::with_capacity(0); } @@ -149,3 +144,16 @@ fn example_closure() { fn macro_closure() { example_closure() } + +#[test] +#[allocate_panic] +fn macro_release_safe() { + #[cfg(debug_assertions)] + { + assert_eq!(1, ::qadapt::protection_level()); + } + #[cfg(not(debug_assertions))] + { + assert_eq!(0, ::qadapt::protection_level()); + } +}