Example #1
0
        /// <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));
        }
Example #2
0
        /// <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);
        }