mirror of
https://github.com/bspeice/qadapt
synced 2024-11-13 01:28:08 -05:00
Fix conditional compilation guards
This commit is contained in:
parent
79f57ba2f9
commit
5d7be8e18e
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
*.swp
|
||||
.idea/
|
19
examples/release_mode.rs
Normal file
19
examples/release_mode.rs
Normal file
@ -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<u8> {
|
||||
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();
|
||||
}
|
@ -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() == '|' => {
|
||||
|
57
src/lib.rs
57
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<usize> = 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() {
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user