< Summary

Information
Class: SwiftCollections.SwiftQueue<T>
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Collection/SwiftQueue.cs
Line coverage
97%
Covered lines: 293
Uncovered lines: 6
Coverable lines: 299
Total lines: 855
Line coverage: 97.9%
Branch coverage
95%
Covered branches: 101
Total branches: 106
Branch coverage: 95.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor()100%11100%
.ctor(...)100%44100%
.ctor(...)83.33%6685.71%
InitializeFromKnownCountRange(...)83.33%7672.72%
.ctor(...)100%11100%
get_InnerArray()100%11100%
get_Count()100%11100%
get_Capacity()100%11100%
get_IsSynchronized()100%11100%
get_SyncRoot()50%22100%
get_IsReadOnly()100%11100%
get_Item(...)100%11100%
set_Item(...)100%11100%
get_State()100%22100%
set_State(...)100%44100%
System.Collections.Generic.ICollection<T>.Add(...)100%11100%
Enqueue(...)100%22100%
EnqueueRange(...)100%66100%
EnqueueKnownCountRange(...)75%4490.9%
EnqueueRange(...)100%11100%
EnqueueRange(...)100%44100%
EnsureAdditionalCapacity(...)100%11100%
Dequeue()100%22100%
TryDequeue(...)100%44100%
System.Collections.Generic.ICollection<T>.Remove(...)100%11100%
Peek()100%11100%
TryPeek(...)100%22100%
PeekTail()100%11100%
Contains(...)100%66100%
Exists(...)100%44100%
Find(...)100%44100%
Clear()100%66100%
FastClear()100%11100%
EnsureCapacity(...)100%22100%
Resize(...)100%66100%
TrimExcessCapacity()100%88100%
ToArray()100%44100%
GetSegments(...)100%44100%
CopyTo(...)100%22100%
CopyTo(...)100%22100%
CopyTo(...)50%22100%
CopyToInternal(...)100%22100%
CloneTo(...)100%22100%
GetEnumerator()100%11100%
System.Collections.Generic.IEnumerable<T>.GetEnumerator()100%11100%
System.Collections.IEnumerable.GetEnumerator()100%11100%
.ctor(...)100%11100%
get_Current()100%11100%
System.Collections.IEnumerator.get_Current()100%11100%
MoveNext()100%44100%
Reset()100%11100%
Dispose()100%11100%

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Collection/SwiftQueue.cs

#LineLine coverage
 1//=======================================================================
 2// SwiftQueue.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using Chronicler;
 9using MemoryPack;
 10using SwiftCollections.Diagnostics;
 11using SwiftCollections.Utility;
 12using System;
 13using System.Collections;
 14using System.Collections.Generic;
 15using System.Runtime.CompilerServices;
 16using System.Text.Json.Serialization;
 17
 18namespace SwiftCollections;
 19
 20/// <summary>
 21/// <c>SwiftQueue&lt;T&gt;</c> is a high-performance, circular buffer-based queue designed for ultra-low-latency enqueue
 22/// <para>
 23/// It leverages power-of-two capacities and bitwise arithmetic to eliminate expensive modulo operations, enhancing perf
 24/// By managing memory efficiently with a wrap-around technique and custom capacity growth strategies, SwiftQueue minimi
 25/// Aggressive inlining and optimized exception handling further reduce overhead, making SwiftQueue outperform tradition
 26/// especially in scenarios with high-frequency additions and removals.
 27/// </para>
 28/// </summary>
 29/// <typeparam name="T">Specifies the type of elements in the queue.</typeparam>
 30[Serializable]
 31[JsonConverter(typeof(StateJsonConverterFactory))]
 32[MemoryPackable]
 33public sealed partial class SwiftQueue<T> : IStateBacked<SwiftArrayState<T>>, ISwiftCloneable<T>, IEnumerable<T>, IEnume
 34{
 35    #region Constants
 36
 37    /// <summary>
 38    /// The default initial capacity of the SwiftQueue if none is specified.
 39    /// Used to allocate a reasonable starting size to minimize resizing operations.
 40    /// </summary>
 41    public const int DefaultCapacity = 8;
 42
 243    private static readonly T[] _emptyArray = Array.Empty<T>();
 244    private static readonly bool _clearReleasedSlots = RuntimeHelpers.IsReferenceOrContainsReferences<T>();
 45
 46    #endregion
 47
 48    #region Fields
 49
 50    /// <summary>
 51    /// The internal array that stores elements of the SwiftQueue. Resized as needed to
 52    /// accommodate additional elements. Not directly exposed outside the queue.
 53    /// </summary>
 54    private T[] _innerArray;
 55
 56    /// <summary>
 57    /// The current number of elements in the SwiftQueue. Represents the total count of
 58    /// valid elements stored in the queue, also indicating the arrayIndex of the next insertion point.
 59    /// </summary>
 60    private int _count;
 61
 62    /// <summary>
 63    /// The arrayIndex of the first element in the queue. Adjusts as elements are dequeued.
 64    /// </summary>
 65    private int _head;
 66
 67    /// <summary>
 68    /// The arrayIndex at which the next element will be enqueued, wrapping around as needed.
 69    /// </summary>
 70    private int _tail;
 71
 72    /// <summary>
 73    /// A bitmask used for efficient modulo operations, derived from the capacity of the internal array.
 74    /// </summary>
 75    private int _mask;
 76
 77    /// <summary>
 78    /// A version number used to track modifications to the SwiftQueue to help detect changes during enumeration and ens
 79    /// </summary>
 80    [NonSerialized]
 81    private uint _version;
 82
 83    /// <summary>
 84    /// An object used to synchronize access to the SwiftQueue, ensuring thread safety.
 85    /// </summary>
 86    [NonSerialized]
 87    private object? _syncRoot;
 88
 89    #endregion
 90
 91    #region Constructors
 92
 93    /// <summary>
 94    /// Initializes a new, empty instance of SwiftQueue.
 95    /// </summary>
 9096    public SwiftQueue() : this(0) { }
 97
 98    /// <summary>
 99    /// Initializes a new, empty instance of SwiftQueue with the specified initial capacity.
 100    /// </summary>
 65101    public SwiftQueue(int capacity)
 102    {
 65103        if (capacity == 0)
 104        {
 45105            _innerArray = _emptyArray;
 45106            _mask = 0;
 107        }
 108        else
 109        {
 20110            capacity = capacity < DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(capacity);
 20111            _innerArray = new T[capacity];
 20112            _mask = _innerArray.Length - 1;
 113        }
 20114    }
 115
 116    /// <summary>
 117    /// Initializes a new instance of SwiftQueue that contains elements copied from the provided items.
 118    /// </summary>
 3119    public SwiftQueue(IEnumerable<T> items)
 120    {
 3121        SwiftThrowHelper.ThrowIfNull(items, nameof(items));
 3122        _innerArray = _emptyArray;
 123
 3124        if (items is ICollection<T> collection)
 125        {
 2126            InitializeFromKnownCountRange(collection, collection.Count);
 2127            return;
 128        }
 129
 1130        if (items is IReadOnlyCollection<T> readOnlyCollection)
 131        {
 0132            InitializeFromKnownCountRange(readOnlyCollection, readOnlyCollection.Count);
 0133            return;
 134        }
 135
 1136        _innerArray = new T[DefaultCapacity];
 1137        _mask = _innerArray.Length - 1;
 138
 8139        foreach (T item in items)
 3140            Enqueue(item);
 1141    }
 142
 143    private void InitializeFromKnownCountRange(IEnumerable<T> items, int count)
 144    {
 2145        if (count == 0)
 146        {
 0147            _innerArray = _emptyArray;
 0148            _mask = 0;
 0149            return;
 150        }
 151
 2152        int capacity = count < DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(count);
 2153        _innerArray = new T[capacity];
 2154        _mask = _innerArray.Length - 1;
 155
 28156        foreach (T item in items)
 12157            _innerArray[_count++] = item;
 158
 2159        _tail = _count & _mask;
 2160    }
 161
 162    ///  <summary>
 163    ///  Initializes a new instance of the <see cref="SwiftQueue{T}"/> class with the specified <see cref="SwiftArraySta
 164    ///  </summary>
 165    ///  <param name="state">The state containing the internal array, count, offset, and version for initialization.</pa
 166    [MemoryPackConstructor]
 5167    public SwiftQueue(SwiftArrayState<T> state)
 168    {
 5169        State = state;
 170
 5171        SwiftThrowHelper.ThrowIfNull(_innerArray, nameof(_innerArray));
 5172    }
 173
 174    #endregion
 175
 176    #region Properties
 177
 178    /// <inheritdoc cref="_innerArray"/>
 179    [JsonIgnore]
 180    [MemoryPackIgnore]
 5181    public T[] InnerArray => _innerArray;
 182
 183    /// <inheritdoc cref="_count"/>
 184    [JsonIgnore]
 185    [MemoryPackIgnore]
 129186    public int Count => _count;
 187
 188    /// <summary>
 189    /// Gets the total number of elements the SwiftQueue can hold without resizing.
 190    /// Reflects the current allocated size of the internal array.
 191    /// </summary>
 192    [JsonIgnore]
 193    [MemoryPackIgnore]
 15194    public int Capacity => _innerArray.Length;
 195
 196    /// <inheritdoc/>
 197    [JsonIgnore]
 198    [MemoryPackIgnore]
 1199    public bool IsSynchronized => false;
 200
 201    /// <inheritdoc/>
 202    [JsonIgnore]
 203    [MemoryPackIgnore]
 1204    public object SyncRoot => _syncRoot ??= new object();
 205
 206    /// <inheritdoc/>
 207    [JsonIgnore]
 208    [MemoryPackIgnore]
 1209    public bool IsReadOnly => false;
 210
 211    /// <summary>
 212    /// Gets the element at the specified arrayIndex.
 213    /// </summary>
 214    [JsonIgnore]
 215    [MemoryPackIgnore]
 216    public T this[int index]
 217    {
 218        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 219        get
 220        {
 201221            SwiftThrowHelper.ThrowIfListIndexInvalid(index, _count);
 200222            return _innerArray[(_head + index) & _mask];
 223        }
 224        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 225        set
 226        {
 2227            SwiftThrowHelper.ThrowIfListIndexInvalid(index, _count);
 1228            _innerArray[(_head + index) & _mask] = value;
 1229        }
 230    }
 231
 232    /// <summary>
 233    /// Gets or sets the current state of the collection, including its items and order.
 234    /// </summary>
 235    /// <remarks>
 236    /// Setting this property replaces the entire contents of the collection with the items from the specified state.
 237    /// Getting this property returns a snapshot of the collection's current items and their order.
 238    /// This property is intended for serialization and deserialization scenarios.
 239    /// </remarks>
 240    [JsonInclude]
 241    [MemoryPackInclude]
 242    public SwiftArrayState<T> State
 243    {
 244        get
 245        {
 2246            var items = new T[_count];
 247
 404248            for (int i = 0; i < _count; i++)
 200249                items[i] = _innerArray[(_head + i) & _mask];
 250
 2251            return new SwiftArrayState<T>(items);
 252        }
 253        internal set
 254        {
 5255            SwiftThrowHelper.ThrowIfNull(value.Items, nameof(value.Items));
 256
 5257            int count = value.Items.Length;
 258
 5259            if (count == 0)
 260            {
 1261                _innerArray = _emptyArray;
 1262                _count = 0;
 1263                _head = 0;
 1264                _tail = 0;
 1265                _mask = 0;
 1266                _version = 0;
 1267                return;
 268            }
 269
 4270            int capacity = SwiftHashTools.NextPowerOfTwo(count <= DefaultCapacity ? DefaultCapacity : count);
 271
 4272            _innerArray = new T[capacity];
 4273            Array.Copy(value.Items, 0, _innerArray, 0, count);
 274
 4275            _count = count;
 4276            _head = 0;
 4277            _tail = count;
 4278            _mask = capacity - 1;
 279
 4280            _version = 0;
 4281        }
 282    }
 283
 284    #endregion
 285
 286    #region Collection Management
 287
 288    /// <inheritdoc/>
 1289    void ICollection<T>.Add(T item) => Enqueue(item);
 290
 291    /// <summary>
 292    /// Adds an item to the end of the queue. Automatically resizes the queue if the capacity is exceeded.
 293    /// </summary>
 294    /// <param name="item">The item to add to the queue.</param>
 295    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 296    public void Enqueue(T item)
 297    {
 318298        if ((uint)_count >= (uint)_innerArray.Length)
 34299            Resize(_innerArray.Length * 2);
 318300        _innerArray[_tail] = item;
 318301        _tail = (_tail + 1) & _mask;
 318302        _count++;
 318303        _version++;
 318304    }
 305
 306    /// <summary>
 307    /// Adds the elements of the specified collection to the end of the queue.
 308    /// </summary>
 309    /// <remarks>
 310    /// Known-count sources reserve capacity before enumeration to avoid repeated growth.
 311    /// </remarks>
 312    /// <param name="items">The collection of elements to add to the queue. Cannot be null.</param>
 313    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 314    public void EnqueueRange(IEnumerable<T> items)
 315    {
 4316        SwiftThrowHelper.ThrowIfNull(items, nameof(items));
 317
 4318        if (items is ICollection<T> collection)
 319        {
 1320            EnqueueKnownCountRange(collection, collection.Count);
 1321            return;
 322        }
 323
 3324        if (items is IReadOnlyCollection<T> readOnlyCollection)
 325        {
 1326            EnqueueKnownCountRange(readOnlyCollection, readOnlyCollection.Count);
 1327            return;
 328        }
 329
 16330        foreach (T item in items)
 6331            Enqueue(item);
 2332    }
 333
 334    private void EnqueueKnownCountRange(IEnumerable<T> items, int count)
 335    {
 2336        if (count == 0)
 0337            return;
 338
 2339        EnsureAdditionalCapacity(count);
 340
 2341        int appendedCount = 0;
 28342        foreach (T item in items)
 343        {
 12344            _innerArray[_tail] = item;
 12345            _tail = (_tail + 1) & _mask;
 12346            appendedCount++;
 347        }
 348
 2349        _count += appendedCount;
 2350        _version++;
 2351    }
 352
 353    /// <summary>
 354    /// Adds the elements of the specified array to the end of the queue in queue order.
 355    /// </summary>
 356    /// <param name="items">The array whose elements should be enqueued.</param>
 357    public void EnqueueRange(T[] items)
 358    {
 7359        SwiftThrowHelper.ThrowIfNull(items, nameof(items));
 7360        EnqueueRange(items.AsSpan());
 7361    }
 362
 363    /// <summary>
 364    /// Adds the elements of the specified span to the end of the queue in queue order.
 365    /// </summary>
 366    /// <param name="items">The span whose elements should be enqueued.</param>
 367    public void EnqueueRange(ReadOnlySpan<T> items)
 368    {
 30369        if (items.Length == 0)
 1370            return;
 371
 29372        EnsureAdditionalCapacity(items.Length);
 373
 316374        for (int i = 0; i < items.Length; i++)
 375        {
 129376            _innerArray[_tail] = items[i];
 129377            _tail = (_tail + 1) & _mask;
 378        }
 379
 29380        _count += items.Length;
 29381        _version++;
 29382    }
 383
 384    private void EnsureAdditionalCapacity(int additionalCount)
 385    {
 31386        long requiredCount = (long)_count + additionalCount;
 31387        SwiftThrowHelper.ThrowIfTrue(requiredCount > int.MaxValue, message: "The collection is too large.");
 31388        EnsureCapacity((int)requiredCount);
 31389    }
 390
 391    /// <summary>
 392    /// Removes and returns the item at the front of the queue.
 393    /// Throws an InvalidOperationException if the queue is empty.
 394    /// </summary>
 395    /// <returns>The item at the front of the queue.</returns>
 396    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 397    public T Dequeue()
 398    {
 83399        SwiftThrowHelper.ThrowIfTrue((uint)_count == 0, message: "Queue is Empty");
 82400        T item = _innerArray[_head];
 82401        if (_clearReleasedSlots)
 5402            _innerArray[_head] = default!;
 82403        _head = (_head + 1) & _mask;
 82404        _count--;
 82405        _version++;
 82406        return item;
 407    }
 408
 409    /// <summary>
 410    /// Tries to remove and return the item at the front of the queue.
 411    /// </summary>
 412    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 413    public bool TryDequeue(out T item)
 414    {
 3415        if ((uint)_count == 0)
 416        {
 1417            item = default!;
 1418            return false;
 419        }
 420
 2421        item = _innerArray[_head];
 2422        if (_clearReleasedSlots)
 1423            _innerArray[_head] = default!;
 2424        _head = (_head + 1) & _mask;
 2425        _count--;
 2426        _version++;
 2427        return true;
 428    }
 429
 1430    bool ICollection<T>.Remove(T item) => throw new NotSupportedException("Remove is not supported for SwiftQueue.");
 431
 432    /// <summary>
 433    /// Returns the item at the front of the queue without removing it.
 434    /// Throws an InvalidOperationException if the queue is empty.
 435    /// </summary>
 436    /// <returns>The item at the front of the queue.</returns>
 437    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 438    public T Peek()
 439    {
 5440        SwiftThrowHelper.ThrowIfTrue((uint)_count == 0, message: "Queue is Empty");
 3441        return _innerArray[_head];
 442    }
 443
 444    /// <summary>
 445    /// Tries to return the item at the front of the queue without removing it.
 446    /// </summary>
 447    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 448    public bool TryPeek(out T item)
 449    {
 2450        if ((uint)_count == 0)
 451        {
 1452            item = default!;
 1453            return false;
 454        }
 455
 1456        item = _innerArray[_head];
 1457        return true;
 458    }
 459
 460    /// <summary>
 461    /// Returns the item at the end of the queue without removing it.
 462    /// Throws an InvalidOperationException if the queue is empty.
 463    /// </summary>
 464    /// <returns>The item at the end of the queue.</returns>
 465    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 466    public T PeekTail()
 467    {
 4468        SwiftThrowHelper.ThrowIfTrue((uint)_count == 0, message: "Queue is Empty");
 3469        int tailIndex = (_tail - 1) & _mask;
 3470        return _innerArray[tailIndex];
 471    }
 472
 473    /// <inheritdoc/>
 474    public bool Contains(T item)
 475    {
 4476        if ((uint)_count == 0) return false;
 477
 2478        int index = _head;
 20479        for (int i = 0; i < _count; i++)
 480        {
 9481            if (Equals(_innerArray[index], item))
 1482                return true;
 483
 8484            index = (index + 1) & _mask;
 485        }
 486
 1487        return false;
 488    }
 489
 490    /// <summary>
 491    /// Determines whether the <see cref="SwiftQueue{T}"/> contains an element that matches the conditions defined by th
 492    /// </summary>
 493    /// <param name="match">The predicate that defines the conditions of the element to search for.</param>
 494    /// <returns><c>true</c> if the <see cref="SwiftQueue{T}"/> contains one or more elements that match the specified p
 495    public bool Exists(Predicate<T> match)
 496    {
 3497        SwiftThrowHelper.ThrowIfNull(match, nameof(match));
 498
 2499        int index = _head;
 20500        for (int i = 0; i < _count; i++)
 501        {
 9502            if (match(_innerArray[index]))
 1503                return true;
 504
 8505            index = (index + 1) & _mask;
 506        }
 507
 1508        return false;
 509    }
 510
 511    /// <summary>
 512    /// Searches for an element that matches the conditions defined by the specified predicate, and returns the first ma
 513    /// </summary>
 514    /// <param name="match">The predicate that defines the conditions of the element to search for.</param>
 515    /// <returns>The first element that matches the conditions defined by the specified predicate, if found; otherwise, 
 516    public T Find(Predicate<T> match)
 517    {
 2518        SwiftThrowHelper.ThrowIfNull(match, nameof(match));
 519
 2520        int index = _head;
 22521        for (int i = 0; i < _count; i++)
 522        {
 10523            T item = _innerArray[index];
 10524            if (match(item))
 1525                return item;
 526
 9527            index = (index + 1) & _mask;
 528        }
 529
 1530        return default!;
 531    }
 532
 533    /// <summary>
 534    /// Removes all elements from the SwiftQueue, resetting its count to zero.
 535    /// </summary>
 536    public void Clear()
 537    {
 8538        if (_count == 0) return;
 539
 4540        if (_clearReleasedSlots)
 541        {
 2542            if ((uint)_head < (uint)_tail)
 1543                Array.Clear(_innerArray, _head, _count);
 544            else
 545            {
 1546                Array.Clear(_innerArray, _head, _innerArray.Length - _head);
 1547                Array.Clear(_innerArray, 0, _tail);
 548            }
 549        }
 550
 4551        _count = 0;
 4552        _head = 0;
 4553        _tail = 0;
 4554        _version++;
 4555    }
 556
 557    /// <summary>
 558    /// Clears the SwiftQueue without releasing the reference to the stored elements.
 559    /// Use FastClear() when you want to quickly reset the list without reallocating memory.
 560    /// </summary>
 561    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 562    public void FastClear()
 563    {
 1564        _count = 0;
 1565        _tail = 0;
 1566        _head = 0;
 1567        _version++;
 1568    }
 569
 570    #endregion
 571
 572    #region Capacity Management
 573
 574    /// <summary>
 575    /// Ensures that the internal storage has at least the specified capacity, resizing if necessary.
 576    /// </summary>
 577    /// <remarks>
 578    /// If the specified capacity is not a power of two, it is rounded up to the next power of two to optimize internal 
 579    /// </remarks>
 580    /// <param name="capacity">The minimum number of elements that the internal storage should be able to hold. Must be 
 581    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 582    public void EnsureCapacity(int capacity)
 583    {
 33584        capacity = SwiftHashTools.NextPowerOfTwo(capacity);  // Capacity must be a power of 2 for proper masking
 33585        if (capacity > _innerArray.Length)
 9586            Resize(capacity);
 33587    }
 588
 589    /// <summary>
 590    /// Ensures that the capacity of the queue is sufficient to accommodate the specified number of elements.
 591    /// The capacity increases to the next power of two greater than or equal to the required minimum capacity.
 592    /// </summary>
 593    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 594    private void Resize(int newSize)
 595    {
 43596        var newArray = new T[newSize <= DefaultCapacity ? DefaultCapacity : newSize];
 43597        if ((uint)_count > 0)
 598        {
 599            // If we are not wrapped around...
 10600            if ((uint)_head < (uint)_tail)
 601            {
 602                // ...copy from head to tail into new array starting at arrayIndex 0
 1603                Array.Copy(_innerArray, _head, newArray, 0, _count);
 604            }
 605            // Else if we are wrapped around...
 606            else
 607            {
 608                // ...copy from head to end of old array to beginning of new array
 9609                Array.Copy(_innerArray, _head, newArray, 0, _innerArray.Length - _head);
 610                // ...copy from start of old array to tail into new array
 9611                Array.Copy(_innerArray, 0, newArray, _innerArray.Length - _head, _tail);
 612            }
 613        }
 614
 43615        _innerArray = newArray;
 43616        _mask = _innerArray.Length - 1;
 43617        _head = 0;
 43618        _tail = _count & _mask;
 43619        _version++;
 43620    }
 621
 622    /// <summary>
 623    /// Reduces the capacity of the SwiftQueue if the element count is significantly less than the current capacity.
 624    /// This method resizes the internal array to the next power of two greater than or equal to the current count,
 625    /// optimizing memory usage.
 626    /// </summary>
 627    public void TrimExcessCapacity()
 628    {
 5629        int newSize = _count < DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(_count);
 6630        if (newSize >= _innerArray.Length) return;
 631
 4632        var newArray = new T[newSize];
 633
 4634        if ((uint)_count != 0)
 635        {
 3636            if ((uint)_head < (uint)_tail)
 637            {
 638                // No wrap-around, simple copy
 2639                Array.Copy(_innerArray, _head, newArray, 0, _count);
 640            }
 641            else
 642            {
 643                // Wrap-around, copy in two parts
 1644                Array.Copy(_innerArray, _head, newArray, 0, _innerArray.Length - _head);
 1645                Array.Copy(_innerArray, 0, newArray, _innerArray.Length - _head, _tail);
 646            }
 647        }
 648
 4649        _innerArray = newArray;
 4650        _mask = _innerArray.Length - 1;
 4651        _head = 0;
 4652        _tail = _count & _mask;
 4653        _version++;
 4654    }
 655
 656    #endregion
 657
 658    #region Utility Methods
 659
 660    /// <summary>
 661    /// Copies the elements of the SwiftQueue to a new array.
 662    /// </summary>
 663    public T[] ToArray()
 664    {
 20665        var result = new T[_count];
 21666        if ((uint)_count == 0) return result;
 19667        if ((uint)_head < (uint)_tail)
 17668            Array.Copy(_innerArray, _head, result, 0, _count);
 669        else
 670        {
 2671            int firstPartLength = _innerArray.Length - _head;
 2672            Array.Copy(_innerArray, _head, result, 0, firstPartLength);
 2673            Array.Copy(_innerArray, 0, result, firstPartLength, _tail);
 674        }
 19675        return result;
 676    }
 677
 678    /// <summary>
 679    /// Returns the current queue contents as up to two read-only spans.
 680    /// </summary>
 681    /// <param name="first">The first contiguous queue segment.</param>
 682    /// <param name="second">The wrapped tail segment, if any.</param>
 683    public void GetSegments(out ReadOnlySpan<T> first, out ReadOnlySpan<T> second)
 684    {
 4685        if ((uint)_count == 0)
 686        {
 1687            first = ReadOnlySpan<T>.Empty;
 1688            second = ReadOnlySpan<T>.Empty;
 1689            return;
 690        }
 691
 3692        if ((uint)_head < (uint)_tail)
 693        {
 1694            first = _innerArray.AsSpan(_head, _count);
 1695            second = ReadOnlySpan<T>.Empty;
 1696            return;
 697        }
 698
 2699        int firstPartLength = _innerArray.Length - _head;
 2700        first = _innerArray.AsSpan(_head, firstPartLength);
 2701        second = _innerArray.AsSpan(0, _tail);
 2702    }
 703
 704    /// <inheritdoc/>
 705    public void CopyTo(Array array, int arrayIndex)
 706    {
 6707        SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 6708        SwiftThrowHelper.ThrowIfArgument((uint)array.Rank != 1, nameof(array), "Array must be single dimensional.");
 5709        SwiftThrowHelper.ThrowIfArgument((uint)array.GetLowerBound(0) != 0, nameof(array), "Array must have zero-based i
 4710        SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length);
 4711        SwiftThrowHelper.ThrowIfArgument((uint)(array.Length - arrayIndex) < _count, nameof(array), "Destination array i
 712
 4713        if ((uint)_count == 0)
 1714            return;
 715
 716        try
 717        {
 3718            CopyToInternal(array, arrayIndex);
 2719        }
 1720        catch (ArrayTypeMismatchException)
 721        {
 1722            throw new ArgumentException("Invalid array type.", nameof(array));
 723        }
 2724    }
 725
 726    /// <inheritdoc/>
 727    public void CopyTo(T[] array, int arrayIndex)
 728    {
 3729        SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 3730        SwiftThrowHelper.ThrowIfArgument((uint)array.Rank != 1, nameof(array), "Array must be single dimensional.");
 3731        SwiftThrowHelper.ThrowIfArgument((uint)array.GetLowerBound(0) != 0, nameof(array), "Array must have zero-based i
 3732        SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length);
 3733        SwiftThrowHelper.ThrowIfArgument((uint)(array.Length - arrayIndex) < _count, nameof(array), "Destination array i
 734
 3735        if ((uint)_count == 0) return;
 736
 1737        CopyToInternal(array, arrayIndex);
 1738    }
 739
 740    /// <summary>
 741    /// Copies the elements of the SwiftQueue into the specified destination span.
 742    /// </summary>
 743    /// <param name="destination">The destination span.</param>
 744    public void CopyTo(Span<T> destination)
 745    {
 2746        SwiftThrowHelper.ThrowIfArgument((uint)destination.Length < _count, nameof(destination), "Destination span is no
 747
 1748        GetSegments(out ReadOnlySpan<T> first, out ReadOnlySpan<T> second);
 1749        first.CopyTo(destination);
 750
 1751        if (second.Length > 0)
 1752            second.CopyTo(destination[first.Length..]);
 1753    }
 754
 755    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 756    private void CopyToInternal(Array destination, int arrayIndex)
 757    {
 4758        if ((uint)_head < (uint)_tail)
 759        {
 2760            Array.Copy(_innerArray, _head, destination, arrayIndex, _count);
 761        }
 762        else
 763        {
 2764            int firstPartLength = _innerArray.Length - _head;
 2765            Array.Copy(_innerArray, _head, destination, arrayIndex, firstPartLength);
 2766            Array.Copy(_innerArray, 0, destination, arrayIndex + firstPartLength, _tail);
 767        }
 2768    }
 769
 770    /// <inheritdoc/>
 771    public void CloneTo(ICollection<T> output)
 772    {
 1773        SwiftThrowHelper.ThrowIfNull(output, nameof(output));
 1774        output.Clear();
 12775        foreach (var item in this)
 5776            output.Add(item);
 1777    }
 778
 779    #endregion
 780
 781    #region Enumerators
 782
 783    /// <summary>
 784    /// Returns an enumerator that iterates through the SwiftList.
 785    /// </summary>
 16786    public SwiftQueueEnumerator GetEnumerator() => new(this);
 10787    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
 2788    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 789
 790    /// <summary>
 791    /// Enumerates the elements of a <see cref="SwiftQueue{T}"/> in the order they would be dequeued.
 792    /// </summary>
 793    public struct SwiftQueueEnumerator : IEnumerator<T>, IEnumerator, IDisposable
 794    {
 795        private readonly SwiftQueue<T> _queue;
 796        private readonly T[] _array;
 797        private readonly uint _version;
 798        private uint _index;
 799        private uint _currentIndex;
 800
 801        private T _current;
 802
 803        internal SwiftQueueEnumerator(SwiftQueue<T> queue)
 804        {
 16805            _queue = queue;
 16806            _array = queue._innerArray;
 16807            _version = queue._version;
 16808            _index = 0;
 16809            _currentIndex = (uint)queue._head - 1;
 16810            _current = default!;
 16811        }
 812
 813        /// <inheritdoc/>
 416814        public readonly T Current => _current;
 815
 816        readonly object IEnumerator.Current
 817        {
 818            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 819            get
 820            {
 3821                SwiftThrowHelper.ThrowIfTrue(_index >= (uint)_queue._count, message: "Bad enumeration");
 2822                return _current!;
 823            }
 824        }
 825
 826        /// <inheritdoc/>
 827        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 828        public bool MoveNext()
 829        {
 236830            SwiftThrowHelper.ThrowIfTrue(_version != _queue._version, message: "Collection was modified during enumerati
 831
 236832            _index++;
 250833            if (_index > (uint)_queue._count) return false;
 222834            _currentIndex++;
 223835            if (_currentIndex == _array.Length) _currentIndex = 0;
 222836            _current = _array[_currentIndex];
 222837            return true;
 838        }
 839
 840        /// <inheritdoc/>
 841        public void Reset()
 842        {
 2843            SwiftThrowHelper.ThrowIfTrue(_version != _queue._version, message: "Collection was modified during enumerati
 844
 2845            _index = 0;
 2846            _currentIndex = (uint)_queue._head - 1;
 2847            _current = default!;
 2848        }
 849
 850        /// <inheritdoc/>
 12851        public void Dispose() => _index = 0;
 852    }
 853
 854    #endregion
 855}

Methods/Properties

.cctor()
.ctor()
.ctor(System.Int32)
.ctor(System.Collections.Generic.IEnumerable`1<T>)
InitializeFromKnownCountRange(System.Collections.Generic.IEnumerable`1<T>,System.Int32)
.ctor(SwiftCollections.SwiftArrayState`1<T>)
get_InnerArray()
get_Count()
get_Capacity()
get_IsSynchronized()
get_SyncRoot()
get_IsReadOnly()
get_Item(System.Int32)
set_Item(System.Int32,T)
get_State()
set_State(SwiftCollections.SwiftArrayState`1<T>)
System.Collections.Generic.ICollection<T>.Add(T)
Enqueue(T)
EnqueueRange(System.Collections.Generic.IEnumerable`1<T>)
EnqueueKnownCountRange(System.Collections.Generic.IEnumerable`1<T>,System.Int32)
EnqueueRange(T[])
EnqueueRange(System.ReadOnlySpan`1<T>)
EnsureAdditionalCapacity(System.Int32)
Dequeue()
TryDequeue(T&)
System.Collections.Generic.ICollection<T>.Remove(T)
Peek()
TryPeek(T&)
PeekTail()
Contains(T)
Exists(System.Predicate`1<T>)
Find(System.Predicate`1<T>)
Clear()
FastClear()
EnsureCapacity(System.Int32)
Resize(System.Int32)
TrimExcessCapacity()
ToArray()
GetSegments(System.ReadOnlySpan`1<T>&,System.ReadOnlySpan`1<T>&)
CopyTo(System.Array,System.Int32)
CopyTo(T[],System.Int32)
CopyTo(System.Span`1<T>)
CopyToInternal(System.Array,System.Int32)
CloneTo(System.Collections.Generic.ICollection`1<T>)
GetEnumerator()
System.Collections.Generic.IEnumerable<T>.GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
.ctor(SwiftCollections.SwiftQueue`1<T>)
get_Current()
System.Collections.IEnumerator.get_Current()
MoveNext()
Reset()
Dispose()