/// <summary> /// Attempts to retrieve the next item to be taken without removing it. /// </summary> /// <param name="item">The item retrieved.</param> /// <returns> /// <c>true</c> if an item was retrieved; otherwise, <c>false</c>. /// </returns> public bool TryPeek(out T item) { item = default; var index = Interlocked.Add(ref _indexDequeue, 0); return(index < Capacity && index > 0 && _entries.TryGetInternal(index, out item)); }
/// <summary> /// Retrieve or creates a new item at the specified index. /// </summary> /// <param name="index">The index.</param> /// <returns>The value.</returns> /// <exception cref="ArgumentOutOfRangeException">index;index must be greater or equal to 0 and less than capacity</exception> public T Get(int index) { if (index < 0 || index >= _entries.Capacity) { throw new ArgumentOutOfRangeException(nameof(index), "index must be greater or equal to 0 and less than capacity"); } // Using TryGetValue first just avoid wasting a needle if (_entries.TryGetInternal(index, out var found)) { // Null resistant found.TryGetValue(out var previous); return(previous); // We don't donate because we didn't remove } var newNeedle = _needleIndexFactory(index); if (_entries.InsertInternal(index, newNeedle, out found)) { return(newNeedle.Value); } // we just failed to insert, meaning that we created a useless needle // donate it Reservoir.DonateNeedle(newNeedle); return(found.Value); }