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