github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/examples/multiple-runtimes/counter.go (about) 1 package main 2 3 import ( 4 "context" 5 _ "embed" 6 "fmt" 7 "log" 8 "os" 9 10 wazero "github.com/wasilibs/wazerox" 11 "github.com/wasilibs/wazerox/api" 12 ) 13 14 // counterWasm was generated by the following: 15 // 16 // cd testdata; wat2wasm --debug-names counter.wat 17 // 18 //go:embed testdata/counter.wasm 19 var counterWasm []byte 20 21 // main shows how to share the same compilation cache across the multiple runtimes. 22 func main() { 23 // Choose the context to use for function calls. 24 ctx := context.Background() 25 26 // Prepare a cache directory. 27 cacheDir, err := os.MkdirTemp("", "example") 28 if err != nil { 29 log.Panicln(err) 30 } 31 defer os.RemoveAll(cacheDir) 32 33 // Initializes the new compilation cache with the cache directory. 34 // This allows the compilation caches to be shared even across multiple OS processes. 35 cache, err := wazero.NewCompilationCacheWithDir(cacheDir) 36 if err != nil { 37 log.Panicln(err) 38 } 39 defer cache.Close(ctx) 40 41 // Creates a shared runtime config to share the cache across multiple wazero.Runtime. 42 runtimeConfig := wazero.NewRuntimeConfig().WithCompilationCache(cache) 43 44 // Creates two wazero.Runtimes with the same compilation cache. 45 runtimeFoo := wazero.NewRuntimeWithConfig(ctx, runtimeConfig) 46 runtimeBar := wazero.NewRuntimeWithConfig(ctx, runtimeConfig) 47 48 // Instantiate two modules on separate Runtimes with identical configuration, which allows each instance 49 // has the isolated states of "env" module. 50 m1 := instantiateWithEnv(ctx, runtimeFoo) 51 m2 := instantiateWithEnv(ctx, runtimeBar) 52 53 for i := 0; i < 2; i++ { 54 fmt.Printf("m1 counter=%d\n", counterGet(ctx, m1)) 55 fmt.Printf("m2 counter=%d\n", counterGet(ctx, m2)) 56 } 57 } 58 59 // count calls "counter.get" in the given namespace 60 func counterGet(ctx context.Context, mod api.Module) uint64 { 61 results, err := mod.ExportedFunction("get").Call(ctx) 62 if err != nil { 63 log.Panicln(err) 64 } 65 return results[0] 66 } 67 68 // counter is an example showing state that needs to be independent per importing module. 69 type counter struct { 70 counter uint32 71 } 72 73 func (e *counter) getAndIncrement() (ret uint32) { 74 ret = e.counter 75 e.counter++ 76 return 77 } 78 79 // instantiateWithEnv returns a module instance. 80 func instantiateWithEnv(ctx context.Context, r wazero.Runtime) api.Module { 81 // Instantiate a new "env" module which exports a stateful function. 82 c := &counter{} 83 _, err := r.NewHostModuleBuilder("env"). 84 NewFunctionBuilder().WithFunc(c.getAndIncrement).Export("next_i32"). 85 Instantiate(ctx) 86 if err != nil { 87 log.Panicln(err) 88 } 89 90 // Instantiate the module that imports "env". 91 mod, err := r.Instantiate(ctx, counterWasm) 92 if err != nil { 93 log.Panicln(err) 94 } 95 return mod 96 }