xref: /wasmtime-44.0.1/examples/threads.rs (revision 9ce3ffe1)
17a1b7cdfSAlex Crichton //! This program is an example of how Wasmtime can be used with multithreaded
27a1b7cdfSAlex Crichton //! runtimes and how various types and structures can be shared across threads.
37a1b7cdfSAlex Crichton 
415c68f2cSYury Delendik // You can execute this example with `cargo run --example threads`
515c68f2cSYury Delendik 
67a1b7cdfSAlex Crichton use std::sync::Arc;
715c68f2cSYury Delendik use std::thread;
815c68f2cSYury Delendik use std::time;
915c68f2cSYury Delendik use wasmtime::*;
1015c68f2cSYury Delendik 
1115c68f2cSYury Delendik const N_THREADS: i32 = 10;
1215c68f2cSYury Delendik const N_REPS: i32 = 3;
1315c68f2cSYury Delendik 
main() -> Result<()>147a1b7cdfSAlex Crichton fn main() -> Result<()> {
157a1b7cdfSAlex Crichton     println!("Initializing...");
1615c68f2cSYury Delendik 
17*ce796a96SXinzhao Xu     // Initialize global per-process state. This state will be shared amongst all
187a1b7cdfSAlex Crichton     // threads. Notably this includes the compiled module as well as a `Linker`,
197a1b7cdfSAlex Crichton     // which contains all our host functions we want to define.
207a1b7cdfSAlex Crichton     let engine = Engine::default();
217a1b7cdfSAlex Crichton     let module = Module::from_file(&engine, "examples/threads.wat")?;
227a1b7cdfSAlex Crichton     let mut linker = Linker::new(&engine);
237a1b7cdfSAlex Crichton     linker.func_wrap("global", "hello", || {
247a1b7cdfSAlex Crichton         println!("> Hello from {:?}", thread::current().id());
257a1b7cdfSAlex Crichton     })?;
267a1b7cdfSAlex Crichton     let linker = Arc::new(linker); // "finalize" the linker
2715c68f2cSYury Delendik 
287a1b7cdfSAlex Crichton     // Share this global state amongst a set of threads, each of which will
297a1b7cdfSAlex Crichton     // create stores and execute instances.
307a1b7cdfSAlex Crichton     let children = (0..N_THREADS)
317a1b7cdfSAlex Crichton         .map(|_| {
327a1b7cdfSAlex Crichton             let engine = engine.clone();
337a1b7cdfSAlex Crichton             let module = module.clone();
347a1b7cdfSAlex Crichton             let linker = linker.clone();
357a1b7cdfSAlex Crichton             thread::spawn(move || {
367a1b7cdfSAlex Crichton                 run(&engine, &module, &linker).expect("Success");
377a1b7cdfSAlex Crichton             })
387a1b7cdfSAlex Crichton         })
397a1b7cdfSAlex Crichton         .collect::<Vec<_>>();
4015c68f2cSYury Delendik 
417a1b7cdfSAlex Crichton     for child in children {
427a1b7cdfSAlex Crichton         child.join().unwrap();
4315c68f2cSYury Delendik     }
4415c68f2cSYury Delendik 
4515c68f2cSYury Delendik     Ok(())
4615c68f2cSYury Delendik }
4715c68f2cSYury Delendik 
run(engine: &Engine, module: &Module, linker: &Linker<()>) -> Result<()>487a1b7cdfSAlex Crichton fn run(engine: &Engine, module: &Module, linker: &Linker<()>) -> Result<()> {
497a1b7cdfSAlex Crichton     // Each sub-thread we have starting out by instantiating the `module`
507a1b7cdfSAlex Crichton     // provided into a fresh `Store`.
517a1b7cdfSAlex Crichton     println!("Instantiating module...");
527a1b7cdfSAlex Crichton     let mut store = Store::new(&engine, ());
537a1b7cdfSAlex Crichton     let instance = linker.instantiate(&mut store, module)?;
54b0939f66SAlex Crichton     let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
5515c68f2cSYury Delendik 
567a1b7cdfSAlex Crichton     println!("Executing...");
577a1b7cdfSAlex Crichton     for _ in 0..N_REPS {
587a1b7cdfSAlex Crichton         run.call(&mut store, ())?;
597a1b7cdfSAlex Crichton         thread::sleep(time::Duration::from_millis(100));
6015c68f2cSYury Delendik     }
6115c68f2cSYury Delendik 
627a1b7cdfSAlex Crichton     // Also note that that a `Store` can also move between threads:
637a1b7cdfSAlex Crichton     println!("> Moving {:?} to a new thread", thread::current().id());
647a1b7cdfSAlex Crichton     let child = thread::spawn(move || run.call(&mut store, ()));
657a1b7cdfSAlex Crichton 
667a1b7cdfSAlex Crichton     child.join().unwrap()?;
6715c68f2cSYury Delendik 
6815c68f2cSYury Delendik     Ok(())
6915c68f2cSYury Delendik }
70