using System; using System.Diagnostics; using UnityEngine.Assertions; using Unity.Collections.LowLevel.Unsafe; namespace Unity.Collections { /// /// A double rewindable allocators . /// unsafe public struct DoubleRewindableAllocators : IDisposable { RewindableAllocator* Pointer; AllocatorHelper UpdateAllocatorHelper0; AllocatorHelper UpdateAllocatorHelper1; /// /// Update the double rewindable allocators, switch Pointer to another allocator and rewind the newly switched allocator. /// public void Update() { var UpdateAllocator0 = (RewindableAllocator*)UnsafeUtility.AddressOf(ref UpdateAllocatorHelper0.Allocator); var UpdateAllocator1 = (RewindableAllocator*)UnsafeUtility.AddressOf(ref UpdateAllocatorHelper1.Allocator); Pointer = (Pointer == UpdateAllocator0) ? UpdateAllocator1 : UpdateAllocator0; CheckIsCreated(); Allocator.Rewind(); } [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] void CheckIsCreated() { if (!IsCreated) { throw new InvalidOperationException($"DoubleRewindableAllocators is not created."); } } /// /// Retrieve the current rewindable allocator. /// /// The Allocator retrieved. public ref RewindableAllocator Allocator { get { CheckIsCreated(); return ref UnsafeUtility.AsRef(Pointer); } } /// /// Check whether the double rewindable allocators is created. /// /// True if current allocator is not null, otherwise false. public bool IsCreated => Pointer != null; /// /// Construct a double rewindable allocators by allocating the allocators from backingAllocator and registering them. /// /// Allocator used to allocate the double rewindable allocators. /// The initial capacity of the allocators, in bytes public DoubleRewindableAllocators(AllocatorManager.AllocatorHandle backingAllocator, int initialSizeInBytes) { this = default; Initialize(backingAllocator, initialSizeInBytes); } /// /// Initialize a double rewindable allocators by allocating the allocators from backingAllocator and registering them. /// /// Allocator used to allocate the double rewindable allocators. /// The initial capacity of the allocators, in bytes public void Initialize(AllocatorManager.AllocatorHandle backingAllocator, int initialSizeInBytes) { UpdateAllocatorHelper0 = new AllocatorHelper(backingAllocator); UpdateAllocatorHelper1 = new AllocatorHelper(backingAllocator); UpdateAllocatorHelper0.Allocator.Initialize(initialSizeInBytes); UpdateAllocatorHelper1.Allocator.Initialize(initialSizeInBytes); Pointer = null; Update(); } /// /// the double rewindable allocators and unregister it. /// public void Dispose() { if (!IsCreated) { return; } UpdateAllocatorHelper0.Allocator.Dispose(); UpdateAllocatorHelper1.Allocator.Dispose(); UpdateAllocatorHelper0.Dispose(); UpdateAllocatorHelper1.Dispose(); } internal bool EnableBlockFree { get { Assert.IsTrue(UpdateAllocatorHelper0.Allocator.EnableBlockFree == UpdateAllocatorHelper1.Allocator.EnableBlockFree); return UpdateAllocatorHelper0.Allocator.EnableBlockFree; } set { UpdateAllocatorHelper0.Allocator.EnableBlockFree = value; UpdateAllocatorHelper1.Allocator.EnableBlockFree = value; } } } }