Unity 6.3
0 онлайн 36 гостей 3 в системе
Вход

Реализация настраиваемого основного контейнера

Чтобы реализовать пользовательский основной контейнер, вы должны аннотировать свой тип с атрибутами NativeContainer. Вы также должны понимать, как основной контейнер интегрирован с системой безопасности.

Необходимо осуществить два основных элемента:

  • Отслеживание использования: Позволяет Unity отслеживать запланированные задания, использующие экземпляр NativeContainer, чтобы можно было обнаруживать и предотвращать потенциальные конфликты, такие как одновременная запись двух заданий в один и тот же основной контейнер.
  • Отслеживание утечек: Обнаруживает, когда NativeContainer не удаляется должным образом. В этой ситуации происходит утечка памяти, когда память, выделенная для NativeContainer, становится недоступной на весь оставшийся срок жизни программы.

Внедрить отслеживание использования

Чтобы получить доступ к отслеживанию использования в коде, используйте AtomicSafetyHandle class. AtomicSafetyHandle содержит ссылку на центральную информацию, которую система безопасности хранит для данного собственного контейнера, и является основным способом, с помощью которого методы NativeContainer взаимодействия с системой безопасности. Из-за этого каждый NativeContainer экземпляр должен содержать AtomicSafetyHandle поле названо m_Safety.

Каждый 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. Вы также можете получить доступ к этому свойству в Редакторе. Для этого перейдите в Настройки > Задания > Уровень обнаружения утечки и выберите необходимый уровень обнаружения утечки.

Вложенные нативные контейнеры

Система безопасности не поддерживает вложенные оригинальные контейнеры в заданиях, потому что система заданий не может правильно настроить AtomicSafetyHandle для каждого отдельного экземпляра NativeContainer внутри более крупного экземпляра NativeContainer.

Чтобы предотвратить планирование заданий, использующих вложенные основные контейнеры, используйте SetNestedContainer, который помечает NativeContainer как вложенный, если он содержит другие экземпляры NativeContainer.

Безопасность IDs и сообщения об ошибках

Система безопасности предоставляет сообщения об ошибках, которые указывают, когда ваш код не соответствует ограничениям безопасности. Чтобы сделать сообщения об ошибках более ясными, вы можете зарегистрировать имя объекта NativeContainer в системе безопасности.

Чтобы зарегистрировать имя, используйте NewStaticSafetyId, которая возвращает безопасный ID, который вы можете передать SetStaticSafetyId. После создания безопасности ID, вы можете повторно использовать его для всех экземпляров NativeContainer, поэтому распространённый приём — хранить его в статическом члене класса-контейнера.

Можно также переопределить сообщения об ошибках для конкретных нарушений ограничений безопасности с помощью SetCustomErrorMessage.

Дополнительные ресурсы