スケジューラーをプラグインとして切り離すシステムについて考えている。
プラグインの種類は主に3つに分けられる。
- IOプラグイン: ホストのシステムとのIOを担当する、Rustで外部関数のFFIを書く必要があるもの。printlnみたいなやつ。インスタンスの生成とか破棄については考える必要がない
- ネイティブUGen:クラスにおけるコンストラクタに相当する関数がエクスポートされてて、実行するとクロージャとしてそのインスタンスが帰ってくるもの。
- システムプラグイン:今回考えたいもの。原則1VMに対して1インスタンスしか存在せず、
on_init
とかon_sample
みたいなシステムの関数にフックして任意の処理を実行しつつ、mimium側からもいくつかの関数を通じてアクセスができる(_mimium_schedule_at
みたいなこと)
システムプラグインについて考えると所有権が結構めんどくさい。VMの中ではIOプラグインとネイティブUGenとシステムプラグインは同じCallExtFun
もしくはCallExtCls
で扱えるようにしたい。がシステムプラグインはVMホスト側(というかオーディオドライバー)からと、mimium側からRustのクロージャインスタンスとを通じて双方向からアクセスされることになる。システムプラグインのインスタンスはクロージャとVM本体と両方から参照されることになるので、Rc<Refcell<_>>
でラップするとかしないといけない。
プラグインの実装側では当然いくつかメンバ関数(&mut self
と&mut Machine
を引数にとる)を実装して、それをmimium側にエクスポートするみたいなことをしたい
が、そうするとSystemPluginSignatureの型の中にSelf
が混ざってくるのを避けられず、object-safeにするのが難しい