ドキュメント

Unity Engine

Unity Engine

NativeContainer 構造体のコピー

Copy and reference multiple native containers.
読み終わるまでの所要時間 9 分最終更新 1ヶ月前

ネイティブコンテナ は値型です。変数に割り当てられると、Unityは
NativeContainer
構造体をコピーします。この構造体にはネイティブコンテナのデータを格納する場所へのポインター (
AtomicSafetyHandle
など) が含まれます。
NativeContainer
のコンテンツ全体をコピーするわけではありません。
これは、同じメモリ領域を参照する
NativeContainer
構造体のコピーが複数存在し、そのすべてに同じ主要レコードを参照する
AtomicSafetyHandle
オブジェクトが存在する可能性があるということです。

NativeContainer オブジェクトのコピーの仕組み

上図に示す
NativeArray
構造体の 3 つの異なるコピーは、同じ実際のコンテナを表しています。各コピーは保存された同じデータ、および元の
NativeArray
と同じ安全データを指しています。ただし、
NativeArray
の各コピーは、ジョブがそのコピーで実行できる内容を示す互いに異なるフラグを持っています。安全データへのポインターは、フラグとの組み合わせで、
AtomicSafetyHandle
を構成します。

バージョン番号

NativeContainer
を破棄する場合、
NativeContainer
構造体のすべてのコピーは、元の
NativeContainer
が無効になることを認識する必要があります。元の
NativeContainer
を廃棄すると、
NativeContainer
のデータを保持していたメモリブロックの割り当てが解除されます。この場合、
NativeContainer
の各コピーに格納されているデータへのポインターは無効になり、使用するとアクセス違反になる可能性があります。
AtomicSafetyHandle
も同様に
NativeContainer
インスタンスで無効になる主要レコードを指しています。ただし、安全システムは主要レコードのメモリ割り当てを解除しないため、アクセス違反のリスクを回避できます。
代わりに、各レコードにはバージョン番号が追加されます。バージョン番号のコピーは、そのレコードを参照する各
AtomicSafetyHandle
内に格納されます。NativeContainer が破棄されると、Unity は
Release()
を呼び出し、主要レコードのバージョン番号を更新します。こうすることで、このレコードは他の
NativeContainer
インスタンスに再利用できるようになります。
残りの各
AtomicSafetyHandle 
は、保存されているバージョン番号と主要レコードのバージョン番号を比較して、
NativeContainer
が破棄されたかどうかをテストします。Unity は、
CheckReadAndThrow
や
CheckWriteAndThrow
などのメソッドの呼び出しの一部として、このテストを自動的に実行します。

動的ネイティブコンテナの静的ビュー

動的ネイティブコンテナは、可変サイズのコンテナです。
NativeList<T>
(Collections パッケージで使用可能) などの要素を継続的に追加できます。これは、
NativeArray<T>
などの静的ネイティブコンテナがサイズを変更できないのとは対照的です。
動的ネイティブコンテナを使用する場合、ビューと呼ばれる別のインターフェースからデータに直接アクセスすることもできます。ビューを使用すると、
NativeContainer
オブジェクトのデータをコピーしたり所有権を取得したりすることなく、エイリアスを作成できます。ビューの例として、ネイティブコンテナの要素ごとにデータにアクセスできる Enumerator (列挙子) オブジェクトがあります。また、
NativeList
を
NativeArray
のように扱うために使用できる
NativeList<T>.AsArray
などのメソッドもあります。
動的ネイティブコンテナのサイズを変更する場合、ビューは通常スレッドセーフではありません。これは、ネイティブコンテナのサイズを変更すると、Unity がメモリ内のデータの格納場所を変更し、ビューの格納するポインターが無効になるためです。

補助バージョン番号

動的ネイティブコンテナのサイズの変更に対応するため、安全システムには
AtomicSafetyHandle
に補助バージョン番号が記録されています。バージョン更新の仕組みと似ていますが、ここでは主要レコードに格納された 2 つ目のバージョン番号を使用し、1 つ目のバージョン番号とは別に更新します。
補助バージョン番号を使用するには、
UseSecondaryVersion
を使用して、ビューを
NativeContainer
に保存されているデータに設定します。ネイティブコンテナのサイズを変更する操作や、既存のビューを無効にする操作には、
CheckWriteAndThrow
ではなく
CheckWriteAndBumpSecondaryVersion
を使用します。また、ネイティブコンテナへ書き込むジョブがスケジュールされるたびにビューが自動的に無効になるよう、
NativeContainer
に
SetBumpSecondaryVersionOnScheduleWrite
を設定する必要があります。
ビューを作成して
AtomicSafetyHandle
をコピーする場合は、
CheckGetSecondaryDataPointerAndThrow
を使用して、ネイティブコンテナのメモリーへのポインターをビューにコピーしても安全であることを確認します。

特殊フォルダー

一時的なネイティブコンテナで作業するときに使える特別なハンドルが 2 つあります。
  • GetTempMemoryHandle
    :
    Allocator.Temp
    で割り当てられたネイティブコンテナで使用できる
    AtomicSafetyHandle
    を返します。現在の一時メモリ範囲が終了すると、Unity はこのハンドルを自動的に無効にするため、自分で解除する必要はありません。特定の
    AtomicSafetyHandle
    が
    GetTempMemoryHandle
    によって返されるハンドルかどうかをテストするには、
    IsTempMemoryHandle
    を使用します。
  • GetTempUnsafePtrSliceHandle
    : 安全でないメモリで保持された一時的なネイティブコンテナに使用できるグローバルハンドルを返します。例えば、スタックメモリから構築された
    NativeSlice
    などです。このハンドルを使用するコンテナをジョブに渡すことはできません。

追加リソース