diff --git a/examples/threading.rs b/examples/threading.rs new file mode 100644 index 00000000..9e115f0a --- /dev/null +++ b/examples/threading.rs @@ -0,0 +1,51 @@ +use rhai::{Engine, RegisterFn, INT}; + +fn main() { + // Channel: Script -> Master + let (tx_script, rx_master) = std::sync::mpsc::channel(); + // Channel: Master -> Script + let (tx_master, rx_script) = std::sync::mpsc::channel(); + + // Spawn thread with Engine + std::thread::spawn(move || { + // Create Engine + let mut engine = Engine::new(); + + // Register API + // Notice that the API functions are blocking + engine + .register_fn("get", move || rx_script.recv().unwrap()) + .register_fn("put", move |v: INT| tx_script.send(v).unwrap()); + + // Run script + engine + .consume( + r#" + print("Starting script loop..."); + + loop { + let x = get(); + print("Script Read: " + x); + x += 1; + print("Script Write: " + x); + put(x); + } + "#, + ) + .unwrap(); + }); + + // This is the main processing thread + + println!("Starting main loop..."); + + let mut value: INT = 0; + + while value < 10 { + println!("Value: {}", value); + // Send value to script + tx_master.send(value).unwrap(); + // Receive value from script + value = rx_master.recv().unwrap(); + } +} diff --git a/src/fn_args.rs b/src/fn_args.rs index 876c59ba..eeb53a1a 100644 --- a/src/fn_args.rs +++ b/src/fn_args.rs @@ -19,7 +19,7 @@ macro_rules! impl_args { ($($p:ident),*) => { impl<$($p: Variant + Clone),*> FuncArgs for ($($p,)*) { - #[inline] + #[inline(always)] fn into_vec(self) -> StaticVec { let ($($p,)*) = self; diff --git a/src/parser.rs b/src/parser.rs index 12eb9649..ae8ece87 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2870,7 +2870,9 @@ fn parse_fn( /// Creates a curried expression from a list of external variables #[cfg(not(feature = "no_function"))] +#[cfg(not(feature = "no_closure"))] fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec, pos: Position) -> Expr { + // If there are no captured variables, no need to curry if externals.is_empty() { return fn_expr; } @@ -2880,14 +2882,8 @@ fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec, pos: Po args.push(fn_expr); - #[cfg(not(feature = "no_closure"))] externals.iter().for_each(|x| { - args.push(Expr::Variable(Box::new((None, None, x.clone().into())))); - }); - - #[cfg(feature = "no_closure")] - externals.into_iter().for_each(|x| { - args.push(Expr::Variable(Box::new((None, None, x.clone().into())))); + args.push(Expr::Variable(Box::new((None, None, x.clone())))); }); let curry_func = crate::engine::KEYWORD_FN_PTR_CURRY; @@ -2904,21 +2900,12 @@ fn make_curry_from_externals(fn_expr: Expr, externals: StaticVec, pos: Po pos, ); - // If there are captured variables, convert the entire expression into a statement block, - // then insert the relevant `Share` statements. - #[cfg(not(feature = "no_closure"))] - { - // Statement block - let mut statements: StaticVec<_> = Default::default(); - // Insert `Share` statements - statements.extend(externals.into_iter().map(|x| Stmt::Share(x))); - // Final expression - statements.push(Stmt::Expr(expr)); - Expr::Stmt(Box::new(statements), pos) - } - - #[cfg(feature = "no_closure")] - return expr; + // Convert the entire expression into a statement block, then insert the relevant + // [`Share`][Stmt::Share] statements. + let mut statements: StaticVec<_> = Default::default(); + statements.extend(externals.into_iter().map(Stmt::Share)); + statements.push(Stmt::Expr(expr)); + Expr::Stmt(Box::new(statements), pos) } /// Parse an anonymous function definition. @@ -3029,11 +3016,8 @@ fn parse_anon_fn( let expr = Expr::FnPointer(fn_name, settings.pos); - let expr = if cfg!(not(feature = "no_closure")) { - make_curry_from_externals(expr, externals, settings.pos) - } else { - expr - }; + #[cfg(not(feature = "no_closure"))] + let expr = make_curry_from_externals(expr, externals, settings.pos); Ok((expr, script)) } diff --git a/tests/native.rs b/tests/native.rs index d0e669fc..209c4a57 100644 --- a/tests/native.rs +++ b/tests/native.rs @@ -1,4 +1,4 @@ -use rhai::{Dynamic, Engine, EvalAltResult, NativeCallContext, RegisterFn, INT}; +use rhai::{Dynamic, Engine, EvalAltResult, NativeCallContext, INT}; use std::any::TypeId; #[test]