--- date: 2025-06-27 17:10 --- #mimium #memo 今の所の問題点として - マシンが一つの結合されたコンパイル済みバイトコードしか受け付けていない - これを配列として複数保持する必要あり - 外部関数の参照インデックスのテーブルはVM上に載っているが、内部関数は一つのプログラム上の絶対位置しか参照できない - プログラム上で定義した内部関数を、他のプログラムでも参照できるようにする、シンボルテーブルがいる - またグローバル環境の評価も同様に、シンボル-(GlobalPos,型)変換のテーブルをコンパイラが持っていないとだめ - マシンをオーディオドライバ立ち上げとともにオーディオスレッドにMoveしてしまっているので、メインスレッドで新たにコンパイルしたプログラムを何かの方法でオーディオスレッドに送ってやらないといけない - しかもできればロックフリーで - [GitHub - hawkw/sharded-slab: a lock-free concurrent slab (experimental)](https://github.com/hawkw/sharded-slab) これかな - それか普通にDashMapか - シンボルテーブルもDashMapで作ってればなんとかなるのかな - VMの中にControllerみたいなDashMap系をArcで包んだものを用意しておいて、メインのマシンはオーディオスレッドに送ってしまい、Arcでコントローラーだけをメインスレッドに残しておく - ExecContextはRepl起動から終了まで次の情報を持ち続ける - グローバル変数のシンボルテーブル(型情報含む) - 内部関数のシンボルテーブル(型情報含む) - 外部関数のシンボルテーブル(型情報含む) ExecContextは、起動時VMのインスタンスを作る。この時VMConrollerのArc参照がVM内に渡される。 ExecContextは、ソースコードを受け取るたびにコンパイラのインスタンスを作ってはプログラムを出力し、終了する。 出力されたプログラムはVMControllerのPrograms(DashMap)に非同期でインサートされ、シンボルテーブルも更新される Replで送られた新しいプログラム(一行だけ)のプログラムをどのスレッドで、いつ実行するかが問題 DSPの頭でReplで溜まった処理(無名関数のキュー)を順番に消化する?あるいは、 ```rust dsp = |l,r| ->(float,float){ ( new_process )} ``` こんな感じでREPLに送ると、実際には ```rust fn repl_001(){ | | { dsp = |l,r| ->(float,float){ ( new_process )} }@now } ``` みたいなのを実行したことになるとか これだとスケジューラープラグイン実装されてることが前提にはなるし、スケジューラーにタスクを登録するのをController越しに行える必要がある というか、メインスレッドに相当するものを別途作る方がやっぱり良さそう 結局、今VMに乗ってるだいたいのものはShared Stateとして共有されて、スタック、ベースポインタ、StateStorageだけが独立する形になりそう --- シングルスレッドの場合、REPLで実行されたものは必ずオーディオドライバのブロック頭で消化 マルチスレッド前提の場合、Shared State全般がRwLockとかで包まれることになってしまう しかし、大概の場合グローバルな状態共有はAtomicな単一パラメーターで済む あくまで、普通のグローバル変数宣言はスレッドローカルな扱いにして、メインスレッドと協調しないといけない場合は"shared"みたいなキーワードをつけるようにするとか(構文増やしたくないけど) だし、これだと結局OSC送るサーバークライアント構成と実質的に変わらないかも