1 //! This program is an example of how Wasmtime can be used with multithreaded 2 //! runtimes and how various types and structures can be shared across threads. 3 4 // You can execute this example with `cargo run --example threads` 5 6 use std::sync::Arc; 7 use std::thread; 8 use std::time; 9 use wasmtime::*; 10 11 const N_THREADS: i32 = 10; 12 const N_REPS: i32 = 3; 13 14 fn main() -> Result<()> { 15 println!("Initializing..."); 16 17 // Initialize global per-process state. This state will be shared amongst all 18 // threads. Notably this includes the compiled module as well as a `Linker`, 19 // which contains all our host functions we want to define. 20 let engine = Engine::default(); 21 let module = Module::from_file(&engine, "examples/threads.wat")?; 22 let mut linker = Linker::new(&engine); 23 linker.func_wrap("global", "hello", || { 24 println!("> Hello from {:?}", thread::current().id()); 25 })?; 26 let linker = Arc::new(linker); // "finalize" the linker 27 28 // Share this global state amongst a set of threads, each of which will 29 // create stores and execute instances. 30 let children = (0..N_THREADS) 31 .map(|_| { 32 let engine = engine.clone(); 33 let module = module.clone(); 34 let linker = linker.clone(); 35 thread::spawn(move || { 36 run(&engine, &module, &linker).expect("Success"); 37 }) 38 }) 39 .collect::<Vec<_>>(); 40 41 for child in children { 42 child.join().unwrap(); 43 } 44 45 Ok(()) 46 } 47 48 fn run(engine: &Engine, module: &Module, linker: &Linker<()>) -> Result<()> { 49 // Each sub-thread we have starting out by instantiating the `module` 50 // provided into a fresh `Store`. 51 println!("Instantiating module..."); 52 let mut store = Store::new(&engine, ()); 53 let instance = linker.instantiate(&mut store, module)?; 54 let run = instance.get_typed_func::<(), ()>(&mut store, "run")?; 55 56 println!("Executing..."); 57 for _ in 0..N_REPS { 58 run.call(&mut store, ())?; 59 thread::sleep(time::Duration::from_millis(100)); 60 } 61 62 // Also note that that a `Store` can also move between threads: 63 println!("> Moving {:?} to a new thread", thread::current().id()); 64 let child = thread::spawn(move || run.call(&mut store, ())); 65 66 child.join().unwrap()?; 67 68 Ok(()) 69 } 70