/// <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); }
/// <summary> /// Adds the specified item. Will not overwrite existing items. /// </summary> /// <param name="item">The item.</param> /// <returns>Returns the position where the item was added, -1 otherwise.</returns> public int TryAdd(T item) { var index = Interlocked.Increment(ref _index) & (_capacity - 1); if (_entries.InsertInternal(index, item)) { return(index); } return(-1); }
/// <summary> /// Attempts to Adds the specified item. /// </summary> /// <param name="item">The item.</param> /// <returns> /// <c>true</c> if the item was added; otherwise, <c>false</c>. /// </returns> public bool TryAdd(T item) { if (_entries.Count < Capacity) { var preCount = Interlocked.Increment(ref _preCount); if (preCount <= Capacity) { var index = (Interlocked.Increment(ref _indexEnqueue) - 1) & (Capacity - 1); if (_entries.InsertInternal(index, item)) { return(true); } } Interlocked.Decrement(ref _preCount); } return(false); }