xref: /wasmtime-44.0.1/examples/threads.cc (revision a70809d0)
1eaa01d7bSTill Schneidereit /*
2eaa01d7bSTill Schneidereit Example of instantiating of the WebAssembly module and invoking its exported
3eaa01d7bSTill Schneidereit function in a separate thread.
4eaa01d7bSTill Schneidereit 
5eaa01d7bSTill Schneidereit You can build the example using CMake:
6eaa01d7bSTill Schneidereit 
7eaa01d7bSTill Schneidereit mkdir build && (cd build && cmake .. && \
8eaa01d7bSTill Schneidereit   cmake --build . --target wasmtime-threads-cpp)
9eaa01d7bSTill Schneidereit 
10eaa01d7bSTill Schneidereit And then run it:
11eaa01d7bSTill Schneidereit 
12eaa01d7bSTill Schneidereit build/wasmtime-threads-cpp
13eaa01d7bSTill Schneidereit */
14eaa01d7bSTill Schneidereit 
15eaa01d7bSTill Schneidereit #include <fstream>
16eaa01d7bSTill Schneidereit #include <iostream>
17eaa01d7bSTill Schneidereit #include <mutex>
18eaa01d7bSTill Schneidereit #include <sstream>
19eaa01d7bSTill Schneidereit #include <thread>
20eaa01d7bSTill Schneidereit #include <unordered_map>
21eaa01d7bSTill Schneidereit #include <vector>
22eaa01d7bSTill Schneidereit #include <wasmtime.hh>
23eaa01d7bSTill Schneidereit 
24eaa01d7bSTill Schneidereit using namespace wasmtime;
25eaa01d7bSTill Schneidereit 
readFile(const char * name)26eaa01d7bSTill Schneidereit std::string readFile(const char *name) {
27eaa01d7bSTill Schneidereit   std::ifstream watFile;
28eaa01d7bSTill Schneidereit   watFile.open(name);
29eaa01d7bSTill Schneidereit   std::stringstream strStream;
30eaa01d7bSTill Schneidereit   strStream << watFile.rdbuf();
31eaa01d7bSTill Schneidereit   return strStream.str();
32eaa01d7bSTill Schneidereit }
33eaa01d7bSTill Schneidereit 
34*a70809d0SAlex Crichton #if defined(WASMTIME_ASAN)
35*a70809d0SAlex Crichton const int N_THREADS = 1;
36*a70809d0SAlex Crichton const int N_REPS = 1;
37*a70809d0SAlex Crichton #else
38eaa01d7bSTill Schneidereit const int N_THREADS = 10;
39eaa01d7bSTill Schneidereit const int N_REPS = 3;
40*a70809d0SAlex Crichton #endif
41eaa01d7bSTill Schneidereit 
42eaa01d7bSTill Schneidereit std::mutex print_mutex;
43eaa01d7bSTill Schneidereit 
run_worker(Engine engine,Module module)44eaa01d7bSTill Schneidereit void run_worker(Engine engine, Module module) {
45eaa01d7bSTill Schneidereit   std::thread::id id = std::this_thread::get_id();
46eaa01d7bSTill Schneidereit   Store store(engine);
47eaa01d7bSTill Schneidereit   for (int i = 0; i < N_REPS; i++) {
48eaa01d7bSTill Schneidereit     {
49eaa01d7bSTill Schneidereit       std::lock_guard<std::mutex> lock(print_mutex);
50eaa01d7bSTill Schneidereit       std::cout << "Instantiating module...\n";
51eaa01d7bSTill Schneidereit     }
52eaa01d7bSTill Schneidereit     Func hello_func = Func::wrap(store, []() {
53eaa01d7bSTill Schneidereit       std::lock_guard<std::mutex> lock(print_mutex);
54eaa01d7bSTill Schneidereit       std::thread::id id = std::this_thread::get_id();
55eaa01d7bSTill Schneidereit       std::cout << "> Hello from ThreadId(" << id << ")\n";
56eaa01d7bSTill Schneidereit     });
57eaa01d7bSTill Schneidereit     auto instance_res = Instance::create(store, module, {hello_func});
58eaa01d7bSTill Schneidereit     if (!instance_res) {
59eaa01d7bSTill Schneidereit       std::cout << "> Error instantiating module!\n";
60eaa01d7bSTill Schneidereit       return;
61eaa01d7bSTill Schneidereit     }
62eaa01d7bSTill Schneidereit     Instance instance = instance_res.unwrap();
63eaa01d7bSTill Schneidereit     Func run = std::get<Func>(*instance.get(store, "run"));
64eaa01d7bSTill Schneidereit     {
65eaa01d7bSTill Schneidereit       std::lock_guard<std::mutex> lock(print_mutex);
66eaa01d7bSTill Schneidereit       std::cout << "Executing...\n";
67eaa01d7bSTill Schneidereit     }
68eaa01d7bSTill Schneidereit     run.call(store, {}).unwrap();
69eaa01d7bSTill Schneidereit     std::this_thread::sleep_for(std::chrono::milliseconds(100));
70eaa01d7bSTill Schneidereit   }
71eaa01d7bSTill Schneidereit 
72eaa01d7bSTill Schneidereit   // Move store to a new thread once.
73eaa01d7bSTill Schneidereit   {
74eaa01d7bSTill Schneidereit     std::lock_guard<std::mutex> lock(print_mutex);
75eaa01d7bSTill Schneidereit     std::cout << "> Moving (" << id << ") to a new thread\n";
76eaa01d7bSTill Schneidereit   }
77eaa01d7bSTill Schneidereit   auto handle = std::thread([store = std::move(store), module]() mutable {
78eaa01d7bSTill Schneidereit     Func hello_func = Func::wrap(store, []() {
79eaa01d7bSTill Schneidereit       std::lock_guard<std::mutex> lock(print_mutex);
80eaa01d7bSTill Schneidereit       std::thread::id id = std::this_thread::get_id();
81eaa01d7bSTill Schneidereit       std::cout << "> Hello from ThreadId(" << id << ")\n";
82eaa01d7bSTill Schneidereit     });
83eaa01d7bSTill Schneidereit     Instance instance = Instance::create(store, module, {hello_func}).unwrap();
84eaa01d7bSTill Schneidereit     Func run = std::get<Func>(*instance.get(store, "run"));
85eaa01d7bSTill Schneidereit     run.call(store, {}).unwrap();
86eaa01d7bSTill Schneidereit   });
87eaa01d7bSTill Schneidereit   handle.join();
88eaa01d7bSTill Schneidereit }
89eaa01d7bSTill Schneidereit 
main()90eaa01d7bSTill Schneidereit int main() {
91eaa01d7bSTill Schneidereit   std::cout << "Initializing...\n";
92eaa01d7bSTill Schneidereit 
93eaa01d7bSTill Schneidereit   Engine engine;
94eaa01d7bSTill Schneidereit   auto wat = readFile("examples/threads.wat");
95eaa01d7bSTill Schneidereit   Module module = Module::compile(engine, wat).unwrap();
96eaa01d7bSTill Schneidereit 
97eaa01d7bSTill Schneidereit   std::vector<std::thread> threads;
98eaa01d7bSTill Schneidereit   threads.reserve(N_THREADS);
99eaa01d7bSTill Schneidereit   for (int i = 0; i < N_THREADS; i++)
100eaa01d7bSTill Schneidereit     threads.emplace_back(run_worker, engine, module);
101eaa01d7bSTill Schneidereit   for (auto &t : threads)
102eaa01d7bSTill Schneidereit     t.join();
103eaa01d7bSTill Schneidereit   return 0;
104eaa01d7bSTill Schneidereit }
105