커스텀 네이티브 컨테이너를 구현하려면 타입에 NativeContainer
속성을 추가해야 합니다.또한 네이티브 컨테이너가 안전 시스템과 어떻게 통합되는지 이해해야 합니다.
두 가지 주요 요소를 구현해야 합니다.
NativeContainer
인스턴스를 사용하는 예약된 잡을 추적하여 두 개의 잡이 동시에 동일한 네이티브 컨테이너에 쓰는 것과 같은 잠재적인 충돌을 감지하고 방지할 수 있도록 합니다.NativeContainer
가 제대로 폐기되지 않은 경우를 감지합니다.이 상황에서는 메모리 누수가 발생하여 NativeContainer
에 할당된 메모리를 프로그램의 남은 수명 동안 사용할 수 없게 됩니다.코드에서 사용량 트래킹에 액세스하려면 AtomicSafetyHandle
클래스를 사용하십시오.AtomicSafetyHandle
은 안전 시스템이 주어진 네이티브 컨테이너에 대해 저장하는 중앙 정보에 대한 참조를 보유하며, NativeContainer
의 메서드가 안전 시스템과 상호작용하는 주요 방식입니다.따라서 모든 NativeContainer
인스턴스에는 m_Safety
라는 이름의 AtomicSafetyHandle
필드가 포함되어야 합니다.
각 AtomicSafetyHandle
은 현재 컨텍스트에서 네이티브 컨테이너에서 수행할 수 있는 잡의 타입을 나타내는 플래그 집합을 저장합니다.잡에 NativeContainer
인스턴스가 포함된 경우, 잡 시스템은 해당 잡에서 네이티브 컨테이너를 사용할 수 있는 방식을 반영하도록 AtomicSafetyHandle
의 플래그를 자동으로 구성합니다.
잡이 NativeContainer
인스턴스에서 읽기를 시도할 때, 잡 시스템은 읽기 전에 CheckReadAndThrow
메서드를 호출하여 잡에 네이티브 컨테이너에 대한 읽기 액세스 권한이 있는지 확인합니다.마찬가지로, 잡이 네이티브 컨테이너에 쓰기를 시도할 때, 잡 시스템은 쓰기 전에 ’CheckWriteAndThrow’를 호출하여 잡에 네이티브 컨테이너에 대한 쓰기 권한이 있는지 확인합니다.동일한 NativeContainer
인스턴스가 할당된 두 개의 잡에는 해당 네이티브 컨테이너에 대한 별도의 AtomicSafetyHandle
오브젝트가 있습니다. 따라서 둘 다 동일한 중앙 정보 집합을 참조하지만, 각 잡이 네이티브 컨테이너에 대해 어떤 읽기 및 쓰기 액세스 권한을 갖는지 나타내는 별도의 플래그를 각각 보유할 수 있습니다.
Unity의 네이티브 코드는 주로 누수 트래킹을 구현합니다.UnsafeUtility.MallocTracked
메서드를 사용하여 NativeContainer
데이터를 저장하는 데 필요한 메모리를 할당한 다음, UnsafeUtility.FreeTracked
를 사용하여 폐기합니다.
이전 버전의 Unity에서는 DisposeSentinel
) 클래스가 누수 트래킹 기능을 제공합니다.Unity는 가비지 컬렉터가 DisposeSentinel
오브젝트를 수집할 때 메모리 누수가 발생한다고 보고합니다.DisposeSentinel
을 생성하려면 Create
메서드를 사용하여 AtomicSafetyHandle
도 동시에 초기화합니다.이 메서드를 사용할 때는 AtomicSafetyHandle
을 초기화하지 않아도 됩니다.NativeContainer
가 폐기되면 Dispose
메서드는 한 번의 호출로 DisposeSentinel
과 AtomicSafetyHandle
을 모두 폐기합니다.
누수된 NativeContainer
가 생성된 위치를 파악하려면 메모리가 원래 할당된 위치의 스택 추적을 캡처하면 됩니다.이렇게 하려면 NativeLeakDetection.Mode
프로퍼티를 사용하십시오.에디터에서 이 프로퍼티에 액세스할 수도 있습니다.이렇게 하려면 Preferences > Jobs > Leak Detection Level로 이동하여 필요한 누수 감지 수준을 선택합니다.
안전 시스템은 잡에서 중첩된 네이티브 컨테이너를 지원하지 않는데, 이는 잡 시스템이 더 큰 NativeContainer
인스턴스 내부의 각 개별 NativeContainer
에 대해 AtomicSafetyHandle
을 올바르게 구성할 수 없기 때문입니다.
중첩된 네이티브 컨테이너를 사용하는 잡을 예약하지 않으려면 다른 ‘NativeContainer’ 인스턴스를 포함할 때 ’NativeContainer’를 중첩된 것으로 플래그를 지정하는 SetNestedContainer
를 사용하십시오.
안전 시스템은 코드가 안전 제약을 준수하지 않는 경우 오류 메시지를 표시합니다.오류 메시지를 더 명확하게 표시하기 위해 NativeContainer
오브젝트 이름을 안전 시스템에 등록할 수 있습니다.
이름을 등록하려면 SetStaticSafetyId
에 전달할 수 있는 안전 ID를 반환하는 NewStaticSafetyId
를 사용하십시오.안전 ID를 생성하면 NativeContainer
의 모든 인스턴스에 재사용할 수 있으므로 컨테이너 클래스의 정적 멤버에 저장하는 것이 일반적인 패턴입니다.
또한 SetCustomErrorMessage
를 사용하여 특정 안전 제약 위반에 대한 오류 메시지를 오버라이드할 수도 있습니다.