mirror of
				https://github.com/bspeice/qadapt
				synced 2025-10-31 01:20:36 -04:00 
			
		
		
		
	Fix conditional compilation guards
This commit is contained in:
		
							
								
								
									
										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()); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user