ドキュメント

Unity Engine

Unity Engine

カスタムネイティブコンテナの実装

Implement custom native containers.
読み終わるまでの所要時間 8 分最終更新 1ヶ月前

カスタムのネイティブコンテナを実装するには、型に
NativeContainer
属性の注釈を付ける必要があります。また、ネイティブコンテナが 安全システム にどのように統合されるかを理解する必要があります。
実装するには、大きく分けて 2 つの要素があります。
  • 使用状況の追跡: Unityが
    NativeContainer
    インスタンスを使用するスケジュールされたジョブを追跡できるようにします。これにより、2 つのジョブが同時に同じネイティブコンテナに書き込むなどの潜在的な競合を検出して防ぐことができます。
  • リークの追跡:
    NativeContainer
    が適切に廃棄されなかったケースを検出します。この場合、メモリリークが発生し、
    NativeContainer
    に割り当てられたメモリがプログラムの残りの生存期間全体にわたって使用できなくなります。

使用状況の実装

コードでの使用状況の追跡には
AtomicSafetyHandle
クラスを使用します。
AtomicSafetyHandle
は、安全システムが特定のネイティブコンテナのために保存する中心的な情報への参照を保持し、
NativeContainer
のメソッドが安全システムと相互作用する主な方法です。このため、すべての
NativeContainer
インスタンスに
m_Safety
という名前の
AtomicSafetyHandle
フィールドが必要です。
各
AtomicSafetyHandle
は、現在のコンテキストでネイティブコンテナに対して実行できる操作の種類を示す一揃いのフラグを保存しています。ジョブに
NativeContainer
インスタンスが含まれる場合、ジョブシステムは自動的に
AtomicSafetyHandle
内のフラグを設定し、そのジョブでネイティブコンテナを使用できる方法を反映します。
ジョブが
NativeContainer
インスタンスから読み取ろうとすると、ジョブシステムは読み取る前に
CheckReadAndThrow
メソッドを呼び出して、ジョブがネイティブコンテナへの読み取りアクセス権を持っていることを確認します。同様に、ジョブがネイティブコンテナに書き込もうとすると、ジョブシステムは書き込む前に
CheckWriteAndThrow
を呼び出し、ジョブがネイティブコンテナへの書き込みアクセス権を持っていることを確認します。同じ
NativeContainer
インスタンスが割り当てられた 2 つのジョブは、そのネイティブコンテナの
AtomicSafetyHandle
オブジェクトを別々に持ちます。そのため、どちらも同じ中心的な情報を参照しますが、ネイティブコンテナに対する各ジョブの読み取り/書き込みアクセス権を示す別々のフラグを保持できます。

リーク追跡の実装

Unity のネイティブコードはもともとリーク追跡を実装しています。
UnsafeUtility.MallocTracked
メソッドを使用して
NativeContainer
データの保存に必要なメモリを割り当て、
UnsafeUtility.FreeTracked
を使用してデータを破棄します。
以前のバージョンの Unity では、
DisposeSentinel
クラスがリーク追跡機能を提供します。Unity は、ガベージコレクター が
DisposeSentinel
オブジェクトを収集するとメモリリークを報告します。
DisposeSentinel
を作成するには
Create
メソッドを使用します。このメソッドは同時に
AtomicSafetyHandle
を初期化します。このメソッドを使用する場合、
AtomicSafetyHandle
を初期化する必要はありません。
NativeContainer
が破棄されると、
Dispose
メソッドは 1 回の呼び出しで
DisposeSentinel
と
AtomicSafetyHandle
の両方を破棄します。
リークした
NativeContainer
がどこで作成されたかを特定するには、メモリが最初に割り当てられた場所のスタックトレースをキャプチャします。これを行うには、
NativeLeakDetection.Mode
プロパティを使用します。このプロパティにはエディターでもアクセスできます。これを行うには、Preferences > Jobs > Leak Detection Level の順に移動して、必要なリーク検出レベルを選択します。

ネストされたネイティブコンテナ

安全システムはジョブ内のネストされたネイティブコンテナをサポートしていません。ジョブシステムは、より大きな
NativeContainer
インスタンス内の個々の
NativeContainer
に対して
AtomicSafetyHandle
を正しく設定できないためです。
ネストされたネイティブコンテナを使用するジョブをスケジュールしないようにするには、
SetNestedContainer
を使用します。これは、
NativeContainer
が他の
NativeContainer
インスタンスを含む場合に、ネスト状態であるというフラグを立てる機能です。

セーフティ ID とエラーメッセージ

安全システムは、コードが安全制約を守っていないことを示すエラーメッセージを提供します。エラーメッセージをわかりやすくするために、
NativeContainer
オブジェクトの名前を安全システムに登録できます。
名前を登録するには、
NewStaticSafetyId
を使用します。これは
SetStaticSafetyId
に渡すことができるセーフティ ID を返します。セーフティ ID を作成したら、
NativeContainer
のすべてのインスタンスで再利用できます。そのため、コンテナクラスの静的メンバーに格納するのが一般的です。
特定の安全制約違反のエラー メッセージを
SetCustomErrorMessage
でオーバーライドすることもできます。

追加リソース