From 8b45d74ecf49a34b8b126394a3cb8251f4c0e741 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 19 Aug 2016 17:30:07 -0400 Subject: [PATCH 1/2] Add syntex::with_extra_stack helper --- syntex/src/lib.rs | 3 +++ syntex/src/stack.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 syntex/src/stack.rs diff --git a/syntex/src/lib.rs b/syntex/src/lib.rs index 6f7352fe..40a71444 100644 --- a/syntex/src/lib.rs +++ b/syntex/src/lib.rs @@ -27,6 +27,9 @@ use syntex_syntax::ptr::P; mod error; pub use error::Error; +mod stack; +pub use stack::with_extra_stack; + pub type Pass = fn(ast::Crate) -> ast::Crate; pub struct Registry { diff --git a/syntex/src/stack.rs b/syntex/src/stack.rs new file mode 100644 index 00000000..05dc4606 --- /dev/null +++ b/syntex/src/stack.rs @@ -0,0 +1,63 @@ +use std::env; +use std::ffi::OsStr; +use std::ops::Drop; +use std::thread; + +const STACK_ENV_VAR: &'static str = "RUST_MIN_STACK"; +const EXTRA_STACK: &'static str = "16777216"; // 16 MB + +/// Runs a function in a thread with extra stack space (16 MB or +/// `$RUST_MIN_STACK` if set). +/// +/// The Rust parser uses a lot of stack space so codegen sometimes requires more +/// than is available by default. +/// +/// ``` +/// syntex::with_extra_stack(move || { +/// let mut reg = syntex::Registry::new(); +/// reg.add_decorator(/* ... */); +/// reg.expand("", src, dst) +/// }) +/// ``` +/// +/// This function runs with a 16 MB stack by default but a different value can +/// be set by the RUST_MIN_STACK environment variable. +pub fn with_extra_stack(f: F) -> T + where F: Send + 'static + FnOnce() -> T, + T: Send + 'static +{ + let _tmp_env = set_if_unset(STACK_ENV_VAR, EXTRA_STACK); + + thread::spawn(f).join().unwrap() +} + +fn set_if_unset(k: K, v: V) -> TmpEnv + where K: AsRef, + V: AsRef, +{ + match env::var(&k) { + Ok(_) => TmpEnv::WasAlreadySet, + Err(_) => { + env::set_var(&k, v); + TmpEnv::WasNotSet(k) + } + } +} + +#[must_use] +enum TmpEnv + where K: AsRef, +{ + WasAlreadySet, + WasNotSet(K), +} + +impl Drop for TmpEnv + where K: AsRef, +{ + fn drop(&mut self) { + if let TmpEnv::WasNotSet(ref k) = *self { + env::remove_var(k); + } + } +} From 8337663a1f1d9cb05bbd72ee5bc2f0319f7e794e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 19 Aug 2016 17:44:40 -0400 Subject: [PATCH 2/2] Ignore with_extra_stack example --- syntex/src/stack.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syntex/src/stack.rs b/syntex/src/stack.rs index 05dc4606..2d96a6ae 100644 --- a/syntex/src/stack.rs +++ b/syntex/src/stack.rs @@ -12,7 +12,7 @@ const EXTRA_STACK: &'static str = "16777216"; // 16 MB /// The Rust parser uses a lot of stack space so codegen sometimes requires more /// than is available by default. /// -/// ``` +/// ```rust,ignore /// syntex::with_extra_stack(move || { /// let mut reg = syntex::Registry::new(); /// reg.add_decorator(/* ... */);