カスタムのネイティブコンテナを実装するには、型に NativeContainer
属性のアノテーションをを付ける必要があります。また、ネイティブコンテナが 安全システム とどのように統合されるかを理解する必要があります。
実装するには、大きく分けて 2 つの要素があります。
NativeContainer
インスタンスを使用するスケジュールされたジョブを追跡できるようにします。これにより、2 つのジョブが同時に同じネイティブコンテナに書き込むなどの潜在的な競合を検出して防ぐことができます。NativeContainer
が適切に廃棄されなかったケースを検出します。この場合、メモリリークが発生し、NativeContainer
に割り当てられたメモリがプログラムの残りの生存期間全体にわたって使用できなくなります。コード内で使用状況状況にアクセスするには AtomicSafetyHandle
クラスを使用します。AtomicSafetyHandle
は、安全システムが特定のネイティブコンテナのために保存する中心的な情報への参照を保持し、NativeContainer
のメソッドが安全システムと相互作用する主な方法です。このため、すべての NativeContainer
インスタンスにはm_Safety
という AtomicSafetyHandle
フィールドが必要です。
各 AtomicSafetyHandle
は、現在のコンテキストでネイティブコンテナに対して実行できる操作の種類を示す一揃いのフラグを保存しています。ジョブに NativeContainer
インスタンスが含まれる場合、ジョブシステムは自動的に AtomicSafetyHandle
内のフラグを構成し、そのジョブでネイティブコンテナを使用できる方法を反映します。
ジョブが NativeContainer
インスタンスから読み取ろうとすると、ジョブシステムは読み取る前に CheckReadAndThrow
メソッドを呼び出し、ジョブがネイティブコンテナへの読み取りアクセス権を持っていることを確認します。同様に、ジョブがネイティブコンテナに書き込もうとすると、ジョブシステムは書き込む前に CheckWriteAndThrow
を呼び出し、ジョブがネイティブコンテナへの書き込みアクセス権を持っていることを確認します。同じ NativeContainer
インスタンスを割り当てられた 2 つのジョブは、そのネイティブコンテナの AtomicSafetyHandle
オブジェクトを別々に持ちます。そのため、2 つのジョブは同じ中央情報を参照しますが、各ジョブがネイティブコンテナに対してどのような読み取りと書き込みのアクセス権を持っているかを示す、それぞれ別のフラグを持つことができます。
Unity のネイティブコードは主にリーク追跡を実装しています。これは UnsafeUtility.MallocTracked
メソッドを使用し、NativeContainer
のデータを格納するのに必要なメモリを割り当て、 UnsafeUtility.FreeTracked
を使用して破棄します。
Unity の以前のバージョンでは ディスポーズセンチネル
DisposeSentinel
](../ScriptReference/Unity.Collections.LowLevel.Unsafe.DisposeSentinel.html) クラスがリーク追跡を提供します。ガベージコレクター が DisposeSentinel
オブジェクトを収集すると、Unity はメモリリークを報告します。DisposeSentinel
を作成するには、Create
メソッドを使用し、同時に AtomicSafetyHandle
を初期化します。このメソッドを使用する場合、AtomicSafetyHandle
を初期化する必要はありません。NativeContainer
が破棄されると、Dispose
メソッドは DisposeSentinel
と AtomicSafetyHandle
の両方を 1 回の呼び出しで破棄します。
リークした NativeContainer
がどこで作成されたかを特定するには、メモリが最初に割り当て られた場所のスタックトレースをキャプチャします。そのためには NativeLeakDetection.Mode
プロパティを使用します。このプロパティにはエディターでもアクセスできます。これを行うには、Preferences > Jobs > Leak Detection Level と移動して、必要なリーク検出レベルを選択します。
安全システムはジョブ内のネストされたネイティブコンテナをサポートしていません。ジョブシステムは、より大きな NativeContainer
インスタンス内の個々の NativeContainer
に対して AtomicSafetyHandle
を正しく設定できないためです。
ネストされたネイティブコンテナを使用するジョブをスケジュールしないようにするには、SetNestedContainer
を使用します。これは、NativeContainer
が他の NativeContainer
インスタンスを含む場合に、ネスト状態であるというフラグを立てる機能です。
安全システムは、コードが安全制約を守っていないことを示すエラーメッ セージを提供します。エラーメッセージをわかりやすくするために、NativeContainer
オブジェクトの名前を安全システムに登録できます。
名前を登録するには NewStaticSafetyId
を使用します。これは、SetStaticSafetyId
に渡すことができるセーフティ ID を返します。セーフティ ID を作成すると、NativeContainer
のすべてのインスタンスで再利用できます。一般的なパターンでは、コンテナクラスの静的メンバーに格納されます。
また、特定の安全制約違反に対するエラーメッセージをオーバーライドすることもできます。 SetCustomErrorMessage
.