WebAssemblyでクロージャ実現にWeak<T>を使ってみる
ラノベのような雰囲気のタイトルになってしまった。 順番にいきましょう。
RustのWeak<T>
RustのWeak<T>
に関しては、公式がすばらしい文章を日本語で出してくれています。本当に感謝しかないです。とにかく読みましょう。
WebAssemblyのクロージャ
さて、それはさておいて、突然クロージャの話になりました。クロージャとはざっくりいうと環境付きの関数ということですが、この場合はStore
が環境にあたります。ほかのプログラミング言語だと環境がネストできたりしますが、今回はグローバル環境(=Store
)だけが対象の話です。
Rustで実装しようとすると困るのが、以下のように、参照関係が循環していることです。
store
は関数実体のリストであるfuncs
を所有しています。そして、その関数実体ひとつひとつからは、環境であるmoduleinst
が参照されています。moduleinst
の中身はほとんどがstore
実体へのポインタなので、当然moduleinst
からstore
への参照も存在します。こんな時にはRustだとWeak<T>
を使うとよいみたいです。
それを踏まえると、宣言は以下のようになる感じでしょうか。
struct Store { funcs: Vec<FuncInst>, tables: Vec<TableInst>, mems: Vec<MemInst>, globals: Vec<GlobalInst>, } struct FuncInst { tp: FuncType, module: ModuleInst, code: Func, } struct ModuleInst { funcaddrs: Weak<Vec<FuncInst>>, tableaddrs: Weak<Vec<TableInst>>, memaddrs: Weak<Vec<MemInst>>, globaladdrs: Weak<Vec<GlobaInst>>, }
木構造の子から親を見たいときにWeak<T>
を使うのが最もオーソドックスなユースケースだと思いますが、今回もたぶん、そうですね。このままうまくいくかどうか、実装を続けたいと思います。
PlantUMLコード
@startuml rectangle store rectangle funcs rectangle moduleinst store -up-> funcs funcs -up-> moduleinst moduleinst .up.> store @enduml