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