public static void Clear(UnsafeMPMCQueue *queue) { UDebug.Assert(queue != null); UDebug.Assert(queue->_head != null); queue->_crossSegmentLock.Lock(); queue->_tail->EnsureFrozenForEnqueues(); var segmentsize = INITIAL_SEGMENT_LENGTH; if (queue->_fixedSize) { segmentsize = queue->_tail->Capacity; } // Free all segments var segment = queue->_head; do { var next = segment->_nextSegment; QueueSegment.Free(segment); segment = next; }while (segment != null); queue->_tail = queue->_head = QueueSegment.Allocate(segmentsize, queue->_slotStride, queue->_slotOffset); queue->_crossSegmentLock.Unlock(); }
private bool TryEnqueueSlow <T>(T item) where T : unmanaged { while (true) { QueueSegment *tail = _tail; if (tail->TryEnqueue(item)) { return(true); } // Do not create a new segment if the queue has a fixed size. if (_fixedSize) { return(false); } _crossSegmentLock.Lock(); if (tail == _tail) { tail->EnsureFrozenForEnqueues(); int nextSize = tail->_preserved ? INITIAL_SEGMENT_LENGTH : Math.Min(tail->Capacity * 2, MAX_SEGMENT_LENGTH); var newTail = QueueSegment.Allocate(nextSize, _slotStride, _slotOffset); tail->_nextSegment = newTail; _tail = newTail; } _crossSegmentLock.Unlock(); } }
/// <summary> /// Creates a Multi-Producer, Multi-Consumer concurrent queue. /// </summary> /// <param name="segmentSize">The size of a queue segment or the queue capacity when fixedSize = true.</param> /// <param name="fixedSize">Creates a queue with a fixed size if true.</param> public static UnsafeMPMCQueue *Allocate <T>(int segmentSize = INITIAL_SEGMENT_LENGTH, bool fixedSize = false) where T : unmanaged { if (segmentSize < 1) { throw new ArgumentOutOfRangeException(nameof(segmentSize), string.Format(ThrowHelper.ArgumentOutOfRange_MustBePositive, nameof(segmentSize))); } int slotStride = Marshal.SizeOf(new QueueSlot <T>()); int slotAlign = Memory.GetMaxAlignment(sizeof(T), sizeof(int)); int slotOffset = Memory.RoundToAlignment(sizeof(T), slotAlign); var queue = Memory.MallocAndZero <UnsafeMPMCQueue>(); queue->_typeHandle = typeof(T).TypeHandle.Value; queue->_slotStride = slotStride; queue->_slotOffset = slotOffset; queue->_fixedSize = fixedSize; queue->_tail = queue->_head = QueueSegment.Allocate(segmentSize, slotStride, slotOffset); return(queue); }