public unsafe static void Release(NativeQueueBlockHeader *block, NativeQueueBlockPoolData *pool) { if (0 == Interlocked.Decrement(ref block->m_NumReaders)) { pool->FreeBlock(block); } }
public static byte *AllocateWriteBlockMT <T>(NativeQueueData *data, NativeQueueBlockPoolData *pool, int threadIndex) where T : struct { int tlsIdx = threadIndex; byte *currentWriteBlock = data->m_CurrentWriteBlockTLS[tlsIdx * IntsPerCacheLine]; if (currentWriteBlock != null && ((NativeQueueBlockHeader *)currentWriteBlock)->itemsInBlock == data->m_ItemsPerBlock) { currentWriteBlock = null; } if (currentWriteBlock == null) { currentWriteBlock = pool->AllocateBlock(); ((NativeQueueBlockHeader *)currentWriteBlock)->nextBlock = null; ((NativeQueueBlockHeader *)currentWriteBlock)->itemsInBlock = 0; NativeQueueBlockHeader *prevLast = (NativeQueueBlockHeader *)Interlocked.Exchange(ref data->m_LastBlock, (IntPtr)currentWriteBlock); if (prevLast == null) { data->m_FirstBlock = currentWriteBlock; } else { prevLast->nextBlock = currentWriteBlock; } data->m_CurrentWriteBlockTLS[tlsIdx * IntsPerCacheLine] = currentWriteBlock; } return(currentWriteBlock); }
public static byte *AllocateWriteBlockMT <T>(NativeQueueData *data, NativeQueueBlockPoolData *pool, int threadIndex) where T : struct { int tlsIdx = threadIndex; NativeQueueBlockHeader *currentWriteBlock = (NativeQueueBlockHeader *)data->GetCurrentWriteBlockTLS(tlsIdx); if (currentWriteBlock != null && currentWriteBlock->itemsInBlock == data->m_ItemsPerBlock) { currentWriteBlock = null; } if (currentWriteBlock == null) { currentWriteBlock = (NativeQueueBlockHeader *)pool->AllocateBlock(); currentWriteBlock->nextBlock = null; currentWriteBlock->itemsInBlock = 0; NativeQueueBlockHeader *prevLast = (NativeQueueBlockHeader *)Interlocked.Exchange(ref data->m_LastBlock, (IntPtr)currentWriteBlock); if (prevLast == null) { data->m_FirstBlock = currentWriteBlock; } else { prevLast->nextBlock = currentWriteBlock; } data->SetCurrentWriteBlockTLS(tlsIdx, currentWriteBlock); } return((byte *)currentWriteBlock); }
public unsafe static void DeallocateQueue(NativeQueueData *data, NativeQueueBlockPoolData *pool, Allocator allocation) { NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)data->m_FirstBlock; while (firstBlock != null) { NativeQueueBlockHeader *next = (NativeQueueBlockHeader *)firstBlock->nextBlock; pool->FreeBlock((byte *)firstBlock); firstBlock = next; } UnsafeUtility.Free(data, allocation); }
/// <summary> /// Constructs a new queue with type of memory allocation. /// </summary> /// <param name="allocator">A member of the /// [Unity.Collections.Allocator](https://docs.unity3d.com/ScriptReference/Unity.Collections.Allocator.html) enumeration.</param> public NativeQueue(Allocator allocator) { CollectionHelper.CheckIsUnmanaged <T>(); m_QueuePool = NativeQueueBlockPool.QueueBlockPool; m_AllocatorLabel = allocator; NativeQueueData.AllocateQueue <T>(allocator, out m_Buffer); #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, allocator); #endif }
public unsafe static void DeallocateQueue(NativeQueueData *data, NativeQueueBlockPoolData *pool, Allocator allocation) { NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)data->m_FirstBlock; while (firstBlock != null) { NativeQueueBlockHeader *next = firstBlock->m_NextBlock; pool->FreeBlock(firstBlock); firstBlock = next; } Memory.Unmanaged.Free(data, allocation); }
public unsafe NativeQueue(Allocator label) { m_QueuePool = NativeQueueBlockPool.QueueBlockPool; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!UnsafeUtility.IsBlittable <T>()) { throw new ArgumentException(string.Format("{0} used in NativeQueue<{0}> must be blittable", typeof(T))); } #endif m_AllocatorLabel = label; NativeQueueData.AllocateQueue <T>(label, out m_Buffer); #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0); #endif }
public static NativeQueueBlockHeader *GetFirstBlock(NativeQueueData *data, NativeQueueBlockPoolData *pool) { NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)data->m_FirstBlock; if (firstBlock == null) { return(null); } if (data->m_CurrentRead >= firstBlock->m_NumItems) { var nextBlock = firstBlock->m_NextBlock; // Block should be freed once last reader calls Release. Interlocked.Decrement(ref firstBlock->m_NumReaders); for (int threadIndex = 0; threadIndex < JobsUtility.MaxJobThreadCount; ++threadIndex) { if (data->GetCurrentWriteBlockTLS(threadIndex) == firstBlock) { data->SetCurrentWriteBlockTLS(threadIndex, null); } } firstBlock = nextBlock; data->m_FirstBlock = (IntPtr)nextBlock; data->m_CurrentRead = 0; if (nextBlock == null) { data->m_LastBlock = IntPtr.Zero; } } if (firstBlock == null) { return(null); } Interlocked.Increment(ref firstBlock->m_NumReaders); return(firstBlock); }
/// <summary> /// Constructs a new queue with type of memory allocation. /// </summary> /// <param name="allocator">A member of the /// [Unity.Collections.Allocator](https://docs.unity3d.com/ScriptReference/Unity.Collections.Allocator.html) enumeration.</param> public NativeQueue(Allocator allocator) { CollectionHelper.CheckIsUnmanaged <T>(); m_QueuePool = NativeQueueBlockPool.QueueBlockPool; m_AllocatorLabel = allocator; NativeQueueData.AllocateQueue <T>(allocator, out m_Buffer); #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, allocator); if (s_staticSafetyId.Data == 0) { CreateStaticSafetyId(); } AtomicSafetyHandle.SetStaticSafetyId(ref m_Safety, s_staticSafetyId.Data); #endif }
public static NativeQueueBlockHeader *AllocateWriteBlockMT <T>(NativeQueueData *data, NativeQueueBlockPoolData *pool, int threadIndex) where T : struct { NativeQueueBlockHeader *currentWriteBlock = data->GetCurrentWriteBlockTLS(threadIndex); if (currentWriteBlock != null && currentWriteBlock->m_NumItems == data->m_MaxItems) { currentWriteBlock = null; } if (currentWriteBlock == null) { currentWriteBlock = pool->AllocateBlock(); currentWriteBlock->m_NextBlock = null; currentWriteBlock->m_NumItems = 0; NativeQueueBlockHeader *prevLast = (NativeQueueBlockHeader *)Interlocked.Exchange(ref data->m_LastBlock, (IntPtr)currentWriteBlock); if (prevLast == null) { data->m_FirstBlock = (IntPtr)currentWriteBlock; } else { prevLast->m_NextBlock = currentWriteBlock; } data->SetCurrentWriteBlockTLS(threadIndex, currentWriteBlock); } return(currentWriteBlock); }