Files
hakorune/docs/reference/boxes-system/plugin_lifecycle.md
Moe Charm da716addc8 feat: Implement plugin singleton pattern with shutdown support
- Add singleton support for plugin boxes (e.g., CounterBox)
- Implement shutdown_plugins_v2() for controlled plugin lifecycle
- Plugin instances now shared across multiple new() calls
- Shutdown properly releases and allows re-initialization
- All singleton E2E tests passing 

ChatGPT5による高度なプラグインライフサイクル管理実装
- シングルトンパターンでプラグインインスタンス共有
- 明示的なshutdownでリソース解放と再初期化対応
- Nyashの統一ライフサイクルポリシー維持

Note: ast.rs test failures are due to rapid development pace -
tests need updating for new BoxDeclaration fields (private_fields, public_fields)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-21 21:35:17 +09:00

5.1 KiB
Raw Blame History

プラグインBoxのライフサイクルv2と nyash.toml 定義

本書は、プラグインBoxPluginBoxV2の生成birthと終了finiの流れ、singleton オプション、ならびに nyash.toml v2 における methods 定義の役割をまとめたものです。


1. 用語

  • birth: プラグインBoxのインスタンス生成method_id=0
  • fini: プラグインBoxの終了処理任意の method_id。例: 4294967295
  • invoke_fn: プラグイン側の単一エントリポイント(nyash_plugin_invoke

2. 生成birthの流れ

  1. unified registryPluginLoaderV2::create_box(box_type, args) を呼び出す。
  2. PluginLoaderV2nyash.toml から type_idmethods を読み込む。
  3. invoke_fn(type_id, method_id=0 /* birth */, instance_id=0, ...) を呼び、戻り値出力TLVの先頭4バイトから instance_id を取得。
  4. PluginBoxV2 { box_type, inner: Arc<PluginHandleInner> } を生成して返す。
    • PluginHandleInner{ type_id, instance_id, invoke_fn, fini_method_id, finalized } を保持し、参照カウントArcで共有される。

補足:

  • fini_method_idnyash.tomlmethods から finimethod_id を取り出して保持します。未定義の場合は None

3. 終了finiの流れ現在

  • フィールド差し替え時(代入で旧値を置き換えるとき):
    • 旧値が InstanceBox の場合: インタプリタが fini() を呼び、finalized としてマーキングします。
    • 旧値が PluginBoxV2 の場合: fini_method_id が設定されていれば invoke_fn(type_id, fini_method_id, instance_id, ...) を呼びます。
  • プラグインBoxPluginBoxV2:
    • すべての参照ArcがDropされ「最後の参照が解放」された時、Dropで一度だけ fini を呼ぶRAII、二重呼び出し防止
    • 明示finiが必要な場合は PluginBoxV2::finalize_now() を使える内部的に一度だけfini実行
    • 代入/フィールド代入/Map.get/Array.get/slice/退避などは「PluginBoxV2は共有share、それ以外は複製clone」で統一。

4. nyash.toml v2 の定義例methods + singleton

[libraries]
[libraries."libnyash_filebox_plugin.so"]
boxes = ["FileBox"]
path = "./plugins/nyash-filebox-plugin/target/release/libnyash_filebox_plugin.so"

[libraries."libnyash_filebox_plugin.so".FileBox]
type_id = 6

[libraries."libnyash_filebox_plugin.so".FileBox.methods]
birth = { method_id = 0 }
open  = { method_id = 1 }
read  = { method_id = 2 }
write = { method_id = 3 }
close = { method_id = 4 }
fini  = { method_id = 4294967295 } # 任意の終端ID

要点:

  • methodsfini を定義すれば、差し替え時などに fini が呼ばれます。
  • fini 未定義の場合、プラグインBoxの終了処理は呼ばれませんフォールバック動作

singleton例

[libraries."libnyash_counter_plugin.so".CounterBox]
type_id = 7
singleton = true

[libraries."libnyash_counter_plugin.so".CounterBox.methods]
birth = { method_id = 0 }
inc = { method_id = 1 }
get = { method_id = 2 }
fini = { method_id = 4294967295 }
  • singleton = true を設定すると、ローダー初期化時に事前birthし、ローダーが共有ハンドルを保持します。
  • create_box() は保持中の共有ハンドルを返すため、複数回の new でも同一インスタンスを共有できます。
  • Nyash終了時または明示要求時shutdown_plugins_v2() を呼ぶと、ローダーが保持する全シングルトンの fini を実行し、クリーンに解放されます。

5. WASMwasm-bindgenとの関係

  • WASMターゲットでは libloading が使えないため、プラグイン機構は features/cfg でスタブ化しています。
  • plugins フィーチャを外す、または target_arch = "wasm32" のときは、プラグイン生成・fini 呼び出しのコードはコンパイル対象外になります(ビルド可能化のため)。

6. 将来拡張の方向

  • ローカル変数のスコープ終了時(関数/メソッド呼び出しの戻りなどに、InstanceBox/PluginBoxV2 の fini を安全に呼び出す仕組み(順序・例外耐性・二重呼び出し防止を含む)。
  • nyash.toml にクラス名→プラグインBox型の overrides を加え、ユーザー定義Boxの外部置換を許可する設計任意

以上。


7. v2.1: BoxRefBox引数サポート

目的: プラグインメソッドの引数として、他のBoxインスタンスを不透明参照で受け渡し可能にする。

  • 仕様詳細: docs/reference/plugin-system/nyash-toml-v2_1-spec.md
  • 設定例1引数にプラグインBoxを渡す:
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
copyFrom = { method_id = 7, args = [ { kind = "box", category = "plugin" } ] }

注意:

  • 当面は category = "plugin" のみ対応。ユーザー定義Boxや複雑なビルトインBoxは非対応。
  • 戻り値の BoxRef は次版v2.2)で検討。