1 // You can execute this example with `cargo run --example threads` 2 3 use anyhow::{format_err, Result}; 4 use std::thread; 5 use std::time; 6 use wasmtime::*; 7 8 const N_THREADS: i32 = 10; 9 const N_REPS: i32 = 3; 10 11 fn run(engine: &Engine, module: Module, id: i32) -> Result<()> { 12 let store = Store::new(&engine); 13 14 // Create external print functions. 15 println!("Creating callback..."); 16 let callback_func = Func::wrap(&store, |arg: i32| { 17 println!("> Thread {} is running", arg); 18 }); 19 20 let id_type = GlobalType::new(ValType::I32, Mutability::Const); 21 let id_global = Global::new(&store, id_type, Val::I32(id))?; 22 23 // Instantiate. 24 println!("Instantiating module..."); 25 let instance = Instance::new(&store, &module, &[callback_func.into(), id_global.into()])?; 26 27 // Extract exports. 28 println!("Extracting export..."); 29 let g = instance 30 .get_func("run") 31 .ok_or(format_err!("failed to find export `run`"))?; 32 33 for _ in 0..N_REPS { 34 thread::sleep(time::Duration::from_millis(100)); 35 // Call `$run`. 36 drop(g.call(&[])?); 37 } 38 39 Ok(()) 40 } 41 42 fn main() -> Result<()> { 43 println!("Initializing..."); 44 let engine = Engine::default(); 45 46 // Compile. 47 println!("Compiling module..."); 48 let module = Module::from_file(&engine, "examples/threads.wat")?; 49 50 let mut children = Vec::new(); 51 for id in 0..N_THREADS { 52 let engine = engine.clone(); 53 let module = module.clone(); 54 children.push(thread::spawn(move || { 55 run(&engine, module, id).expect("Success"); 56 })); 57 } 58 59 for (i, child) in children.into_iter().enumerate() { 60 if let Err(_) = child.join() { 61 println!("Thread #{} errors", i); 62 } 63 } 64 65 Ok(()) 66 } 67