/// <summary> /// Enqueue value into the container. /// </summary> /// <param name="value">The value to be appended.</param> public void Enqueue(T value) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif NativeQueueBlockHeader *writeBlock = NativeQueueData.AllocateWriteBlockMT <T>(m_Buffer, m_QueuePool, 0); UnsafeUtility.WriteArrayElement(writeBlock + 1, writeBlock->m_NumItems, value); ++writeBlock->m_NumItems; }
/// <summary> /// Enqueue value into the container. /// </summary> /// <param name="value">The value to be appended.</param> public void Enqueue(T value) { CheckWrite(); NativeQueueBlockHeader *writeBlock = NativeQueueData.AllocateWriteBlockMT <T>(m_Buffer, m_QueuePool, 0); UnsafeUtility.WriteArrayElement(writeBlock + 1, writeBlock->m_NumItems, value); ++writeBlock->m_NumItems; }
static void OnDomainUnload(object sender, EventArgs e) { while (data.firstBlock != IntPtr.Zero) { NativeQueueBlockHeader *block = (NativeQueueBlockHeader *)data.firstBlock; data.firstBlock = (IntPtr)(block->nextBlock); UnsafeUtility.Free(block, Allocator.Persistent); --data.allocatedBlocks; } }
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); }
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); }
/// <summary> /// /// </summary> /// <returns></returns> public T Peek() { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckReadAndThrow(m_Safety); #endif NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)m_Buffer->m_FirstBlock; if (firstBlock == null) { throw new InvalidOperationException("Trying to peek from an empty queue"); } return(UnsafeUtility.ReadArrayElement <T>(firstBlock + 1, m_Buffer->m_CurrentRead)); }
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); }
unsafe public void Clear() { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)m_Buffer->m_FirstBlock; while (firstBlock != null) { NativeQueueBlockHeader *next = (NativeQueueBlockHeader *)firstBlock->nextBlock; m_QueuePool->FreeBlock((byte *)firstBlock); firstBlock = next; } m_Buffer->m_FirstBlock = null; m_Buffer->m_LastBlock = IntPtr.Zero; m_Buffer->m_CurrentReadIndexInBlock = 0; for (int tls = 0; tls < JobsUtility.MaxJobThreadCount; ++tls) { m_Buffer->m_CurrentWriteBlockTLS[tls * NativeQueueData.IntsPerCacheLine] = null; } }
unsafe public bool TryDequeue(out T item) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif NativeQueueBlockHeader *firstBlock = NativeQueueData.GetFirstBlock(m_Buffer, m_QueuePool); if (firstBlock == null) { item = default(T); return(false); } var currentRead = m_Buffer->m_CurrentRead++; item = UnsafeUtility.ReadArrayElement <T>(firstBlock + 1, currentRead); NativeQueueData.Release(firstBlock, m_QueuePool); return(true); }
/// <summary> /// Try dequeueing item from the container. If container is empty item won't be changed, and return result will be false. /// </summary> /// <param name="item">Item value if dequeued.</param> /// <returns>Returns true if item was dequeued.</returns> public bool TryDequeue(out T item) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)m_Buffer->m_FirstBlock; if (firstBlock == null) { item = default(T); return(false); } var currentRead = m_Buffer->m_CurrentRead++; item = UnsafeUtility.ReadArrayElement <T>(firstBlock + 1, currentRead); if (m_Buffer->m_CurrentRead >= firstBlock->m_NumItems) { m_Buffer->m_CurrentRead = 0; m_Buffer->m_FirstBlock = (IntPtr)firstBlock->m_NextBlock; if (m_Buffer->m_FirstBlock == IntPtr.Zero) { m_Buffer->m_LastBlock = IntPtr.Zero; } for (int threadIndex = 0; threadIndex < JobsUtility.MaxJobThreadCount; ++threadIndex) { if (m_Buffer->GetCurrentWriteBlockTLS(threadIndex) == firstBlock) { m_Buffer->SetCurrentWriteBlockTLS(threadIndex, null); } } m_QueuePool->FreeBlock(firstBlock); } return(true); }
/// <summary> /// Clears the container. /// </summary> public void Clear() { CheckWrite(); NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)m_Buffer->m_FirstBlock; while (firstBlock != null) { NativeQueueBlockHeader *next = firstBlock->m_NextBlock; m_QueuePool->FreeBlock(firstBlock); firstBlock = next; } m_Buffer->m_FirstBlock = IntPtr.Zero; m_Buffer->m_LastBlock = IntPtr.Zero; m_Buffer->m_CurrentRead = 0; for (int threadIndex = 0; threadIndex < JobsUtility.MaxJobThreadCount; ++threadIndex) { m_Buffer->SetCurrentWriteBlockTLS(threadIndex, null); } }
public void FreeBlock(NativeQueueBlockHeader *block) { if (m_NumBlocks > m_MaxBlocks) { if (Interlocked.Decrement(ref m_NumBlocks) + 1 > m_MaxBlocks) { UnsafeUtility.Free(block, Allocator.Persistent); return; } Interlocked.Increment(ref m_NumBlocks); } NativeQueueBlockHeader *checkBlock = (NativeQueueBlockHeader *)m_FirstBlock; NativeQueueBlockHeader *nextPtr; do { nextPtr = checkBlock; block->m_NextBlock = checkBlock; checkBlock = (NativeQueueBlockHeader *)Interlocked.CompareExchange(ref m_FirstBlock, (IntPtr)block, (IntPtr)checkBlock); }while (checkBlock != nextPtr); }
/// <summary> /// Clears the container. /// </summary> public void Clear() { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif NativeQueueBlockHeader *firstBlock = (NativeQueueBlockHeader *)m_Buffer->m_FirstBlock; while (firstBlock != null) { NativeQueueBlockHeader *next = firstBlock->m_NextBlock; m_QueuePool->FreeBlock(firstBlock); firstBlock = next; } m_Buffer->m_FirstBlock = IntPtr.Zero; m_Buffer->m_LastBlock = IntPtr.Zero; m_Buffer->m_CurrentRead = 0; for (int threadIndex = 0; threadIndex < JobsUtility.MaxJobThreadCount; ++threadIndex) { m_Buffer->SetCurrentWriteBlockTLS(threadIndex, null); } }
internal void SetCurrentWriteBlockTLS(int threadIndex, NativeQueueBlockHeader *currentWriteBlock) { var data = (NativeQueueBlockHeader **)&m_CurrentWriteBlockTLS[threadIndex * JobsUtility.CacheLineSize]; *data = currentWriteBlock; }