Пример #1
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="System.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("index", "index must be greater or equal to 0 and less than capacity");
     }
     // Using TryGetValue first just avoid wasting a needle
     TNeedle found;
     if (_entries.TryGetInternal(index, out found))
     {
         // Null resistant
         T previous;
         found.TryGetValue(out previous);
         return previous;
         // We don't donate because we didn't remove
     }
     var newNeedle = _needleFactory(index);
     if (_entries.InsertInternal(index, newNeedle, out found))
     {
         return newNeedle.Value;
     }
     // we just failed to insert, meaning that we created a usless needle
     // donate it
     NeedleReservoir<T, TNeedle>.DonateNeedle(newNeedle);
     return found.Value;
 }
Пример #2
0
        internal bool TryGetOrAdd(TKey key, Predicate <TKey> keyOverwriteCheck, TValue value, out TValue stored)
        {
            // NOTICE this method has no null check
            var needle = PrivateGetNeedle(key);

            if
            (
                _wrapped.TryGetOrAdd
                (
                    needle,
                    input =>
            {
                TKey foundKey;
                if (PrivateTryGetValue(input, out foundKey))
                {
                    return(keyOverwriteCheck(foundKey));
                }
                return(true);
            },
                    value,
                    out stored
                )
            )
            {
                return(true);
            }
            NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);

            return(false);
        }
Пример #3
0
        public TValue AddOrUpdate(TKey key, TValue addValue, Func <TKey, TValue, TValue> updateValueFactory, out bool added)
        {
            if (ReferenceEquals(updateValueFactory, null))
            {
                throw new ArgumentNullException("updateValueFactory");
            }
            TNeedle needle = PrivateGetNeedle(key);
            Func <TNeedle, TValue, TValue> factory = (pairKey, foundValue) =>
            {
                TKey foundKey;
                if (PrivateTryGetValue(pairKey, out foundKey))
                {
                    return(updateValueFactory(foundKey, foundValue));
                }
                return(addValue);
            };
            var result = _wrapped.AddOrUpdate
                         (
                needle,
                addValue,
                factory,
                out added
                         );

            if (!added)
            {
                NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);
            }
            return(result);
        }
Пример #4
0
        /// <summary>
        /// Adds the specified key and associated value.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="keyOverwriteCheck">The key predicate to approve overwriting.</param>
        /// <param name="value">The value.</param>
        /// <exception cref="System.ArgumentException">An item with the same key has already been added</exception>
        internal void AddNew(TKey key, Predicate <TKey> keyOverwriteCheck, TValue value)
        {
            // NOTICE this method has no null check
            var needle = PrivateGetNeedle(key);

            try
            {
                _wrapped.AddNew
                (
                    needle,
                    input =>
                {
                    TKey foundKey;
                    if (PrivateTryGetValue(input, out foundKey))
                    {
                        return(keyOverwriteCheck(foundKey));
                    }
                    return(true);
                },
                    value
                );
            }
            catch (ArgumentException)
            {
                NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);

                throw;
            }
        }
Пример #5
0
        /// <summary>
        /// Attempts to add the specified key and associated value. The value is added if the key is not found.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="stored">The stored pair independently of success.</param>
        /// <returns>
        ///   <c>true</c> if the specified key and associated value were added; otherwise, <c>false</c>.
        /// </returns>
        public bool TryAdd(TKey key, TValue value, out KeyValuePair <TKey, TValue> stored)
        {
            // No risk of dead needles here
            var needle = PrivateGetNeedle(key);
            KeyValuePair <TNeedle, TValue> storedPair;
            Predicate <TNeedle>            check = found =>
            {
                TKey foundKey;
                if (PrivateTryGetValue(found, out foundKey))
                {
                    // Keeping the found key alive
                    // If we found a key, key will be the key found
                    // If we didn't key will be the key added
                    // So, either way key is the key that is stored
                    // By having it here, we don't need to read _stored.Key
                    key = foundKey;
                    return(false);
                }
                return(true);
            };
            var result = _wrapped.TryAdd(needle, check, value, out storedPair);

            if (!result)
            {
                NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);
            }
            stored = new KeyValuePair <TKey, TValue>(key, storedPair.Value);
            return(result);
        }
Пример #6
0
        /// <summary>
        /// Removes all the elements.
        /// </summary>
        public void Clear()
        {
            var displaced = _wrapped.ClearEnumerable();

            foreach (var item in displaced)
            {
                NeedleReservoir <TKey, TNeedle> .DonateNeedle(item.Key);
            }
        }
Пример #7
0
        public WeakDictionary(IEqualityComparer <TKey> comparer)
        {
            Comparer = comparer ?? EqualityComparer <TKey> .Default;
            var needleComparer = new NeedleConversionEqualityComparer <WeakNeedle <TKey>, TKey>(Comparer);

            Wrapped          = new ThreadSafeDictionary <WeakNeedle <TKey>, TValue>(needleComparer);
            _keyCollection   = new KeyCollection <TKey, TValue>(this);
            _valueCollection = new ValueCollection <TKey, TValue>(this);
            _reservoir       = new NeedleReservoir <TKey, WeakNeedle <TKey> >(key => new WeakNeedle <TKey>(key));
        }
Пример #8
0
        public WeakDictionary(IEqualityComparer <TKey> comparer, int initialProbing)
        {
            _keyComparer = comparer ?? EqualityComparer <TKey> .Default;
            var needleComparer = new NeedleConversionEqualityComparer <WeakNeedle <TKey>, TKey>(_keyComparer);

            _wrapped         = new SafeDictionary <WeakNeedle <TKey>, TValue>(needleComparer, initialProbing);
            _keyCollection   = new KeyCollection <TKey, TValue>(this);
            _valueCollection = new ValueCollection <TKey, TValue>(this);
            _reservoir       = new NeedleReservoir <TKey, WeakNeedle <TKey> >(key => new WeakNeedle <TKey>(key));
        }
Пример #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="NeedleBucket{T, TNeedle}" /> class.
 /// </summary>
 /// <param name = "valueFactory">The delegate that is invoked to do the lazy initialization of the items.</param>
 /// <param name="needleFactory">The delegate that is invoked to create a needle</param>
 /// <param name="capacity">The capacity.</param>
 /// <exception cref="InvalidOperationException"></exception>
 /// <exception cref="ArgumentNullException"><paramref name="valueFactory"/> is <c>null</c>.</exception>
 public NeedleBucket(Func <T> valueFactory, Func <T, TNeedle> needleFactory, int capacity)
 {
     if (valueFactory == null)
     {
         throw new ArgumentNullException(nameof(valueFactory));
     }
     _needleFactory      = needleFactory ?? throw new ArgumentNullException(nameof(needleFactory));
     _reservoir          = new NeedleReservoir <T, TNeedle>(_needleFactory);
     _needleIndexFactory = index => Reservoir.GetNeedle(new ValueFuncClosure <T>(valueFactory).InvokeReturn());
     _entries            = new FixedSizeBucket <TNeedle>(capacity);
 }
Пример #10
0
        public TValue GetOrAdd(TKey key, TValue value)
        {
            var    needle = PrivateGetNeedle(key);
            TValue result;

            if (!_wrapped.TryGetOrAdd(needle, input => !input.IsAlive, value, out result))
            {
                NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);
            }
            return(result);
        }
Пример #11
0
        public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
        {
            var needle = PrivateGetNeedle(key);

            if (_wrapped.TryUpdate(needle, newValue, comparisonValue))
            {
                return(true);
            }
            NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);

            return(false);
        }
Пример #12
0
        public bool TryGetOrAdd(TKey key, TValue value, out TValue stored)
        {
            var needle = PrivateGetNeedle(key);

            if (_wrapped.TryGetOrAdd(needle, input => !input.IsAlive, value, out stored))
            {
                return(true);
            }
            NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);

            return(false);
        }
Пример #13
0
        public bool TryUpdate(TKey key, TValue newValue, Predicate <TValue> valueCheck)
        {
            var needle = PrivateGetNeedle(key);

            if (_wrapped.TryUpdate(needle, newValue, valueCheck))
            {
                return(true);
            }
            NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);

            return(false);
        }
Пример #14
0
 /// <summary>
 /// Retrieve or creates a new needle at the specified index.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <returns>The needle.</returns>
 /// <exception cref="System.ArgumentOutOfRangeException">index;index must be greater or equal to 0 and less than capacity</exception>
 public TNeedle GetNeedle(int index)
 {
     TNeedle found;
     var newNeedle = _needleFactory(index);
     if (_entries.Insert(index, newNeedle, out found))
     {
         return newNeedle;
     }
     // we just failed to insert, meaning that we created a usless needle
     // donate it
     NeedleReservoir<T, TNeedle>.DonateNeedle(newNeedle);
     return found;
 }
Пример #15
0
 /// <summary>
 /// Inserts the item at the specified index.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <param name="item">The item.</param>
 /// <returns>
 ///   <c>true</c> if the item was inserted; otherwise, <c>false</c>.
 /// </returns>
 /// <exception cref="System.ArgumentOutOfRangeException">index;index must be greater or equal to 0 and less than capacity.</exception>
 /// <remarks>
 /// The insertion can fail if the index is already used or is being written by another thread.
 /// If the index is being written it can be understood that the insert operation happened before but the item was overwritten or removed.
 /// </remarks>
 public bool Insert(int index, T item)
 {
     // Only succeeds if there was nothing there before
     // meaning that if this succeeds it replaced nothing
     // If this fails whatever was there is still there
     var newNeedle = NeedleReservoir<T, TNeedle>.GetNeedle(item);
     if (_entries.Insert(index, newNeedle))
     {
         return true;
     }
     NeedleReservoir<T, TNeedle>.DonateNeedle(newNeedle);
     return false;
 }
Пример #16
0
 /// <summary>
 /// Removes the item at the specified index.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <param name="previous">The previous item in the specified index.</param>
 /// <returns>
 ///   <c>true</c> if the item was removed; otherwise, <c>false</c>.
 /// </returns>
 /// <exception cref="System.ArgumentOutOfRangeException">index;index must be greater or equal to 0 and less than capacity</exception>
 public bool RemoveAt(int index, out T previous)
 {
     TNeedle found;
     if (_entries.RemoveAt(index, out found))
     {
         // TryGetValue is null resistant
         found.TryGetValue(out previous);
         // Donate it
         NeedleReservoir<T, TNeedle>.DonateNeedle(found);
         return true;
     }
     previous = default(T);
     return false;
 }
Пример #17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="NeedleBucket{T, TNeedle}" /> class.
 /// </summary>
 /// <param name = "valueFactory">The delegate that is invoked to do the lazy initialization of the items.</param>
 /// <param name="capacity">The capacity.</param>
 public NeedleBucket(Func<T> valueFactory, int capacity)
 {
     if (valueFactory == null)
     {
         throw new ArgumentNullException("valueFactory");
     }
     if (!NeedleHelper.CanCreateNeedle<T, TNeedle>())
     {
         throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to find a way to create {0}", typeof(TNeedle).Name));
     }
     _needleFactory = index => NeedleReservoir<T, TNeedle>.GetNeedle(valueFactory());
     _entries = new FixedSizeBucket<TNeedle>(capacity);
     _comparer = EqualityComparer<T>.Default;
 }
Пример #18
0
 /// <summary>
 /// Sets the item at the specified index.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <param name="item">The item.</param>
 /// <param name="previous">The previous item in the specified index.</param>
 /// <returns>
 ///   <c>true</c> if the item was new; otherwise, <c>false</c>.
 /// </returns>
 /// <exception cref="System.ArgumentOutOfRangeException">index;index must be greater or equal to 0 and less than capacity</exception>
 public bool Exchange(int index, T item, out T previous)
 {
     TNeedle found;
     if (_entries.Exchange(index, NeedleReservoir<T, TNeedle>.GetNeedle(item), out found))
     {
         previous = default(T);
         return true;
     }
     // TryGetValue is null resistant
     found.TryGetValue(out previous);
     // This is a needle that is no longer referenced, we donate it
     NeedleReservoir<T, TNeedle>.DonateNeedle(found);
     return false;
 }
Пример #19
0
        /// <summary>
        /// Adds the specified key and associated value.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <exception cref="System.ArgumentException">An item with the same key has already been added</exception>
        public void AddNew(TKey key, TValue value)
        {
            var needle = PrivateGetNeedle(key);

            try
            {
                _wrapped.AddNew(needle, input => !input.IsAlive, value);
            }
            catch (ArgumentException)
            {
                NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);

                throw;
            }
        }
Пример #20
0
 public bool Update(int index, Func<T, T> itemUpdateFactory, Predicate<T> check, out bool isEmpty)
 {
     TNeedle newNeedle = null;
     Func<TNeedle, TNeedle> replacementFactory = needle => newNeedle = NeedleReservoir<T, TNeedle>.GetNeedle(itemUpdateFactory(needle.Value));
     Predicate<TNeedle> replacementCheck = needle => check(needle.Value);
     if (_entries.Update(index, replacementFactory, replacementCheck, out isEmpty))
     {
         return true;
     }
     if (newNeedle != null)
     {
     }
     NeedleReservoir<T, TNeedle>.DonateNeedle(newNeedle);
     return false;
 }
Пример #21
0
 public bool RemoveAt(int index, Predicate<T> check)
 {
     TNeedle found = null;
     Predicate<TNeedle> replacementCheck = needle =>
     {
         found = needle;
         return check(needle.Value);
     };
     if (_entries.RemoveAt(index, replacementCheck))
     {
         // Donate it
         NeedleReservoir<T, TNeedle>.DonateNeedle(found);
         return true;
     }
     return false;
 }
Пример #22
0
 /// <summary>
 /// Inserts the item at the specified index.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <param name="item">The item.</param>
 /// <param name="previous">The previous item in the specified index.</param>
 /// <returns>
 ///   <c>true</c> if the item was inserted; otherwise, <c>false</c>.
 /// </returns>
 /// <exception cref="System.ArgumentOutOfRangeException">index;index must be greater or equal to 0 and less than capacity</exception>
 /// <remarks>
 /// The insertion can fail if the index is already used or is being written by another thread.
 /// If the index is being written it can be understood that the insert operation happened before but the item was overwritten or removed.
 /// </remarks>
 public bool Insert(int index, T item, out T previous)
 {
     // Only succeeds if there was nothing there before
     // meaning that if this succeeds it replaced nothing
     // If this fails whatever was there is still there
     TNeedle found;
     var newNeedle = NeedleReservoir<T, TNeedle>.GetNeedle(item);
     if (_entries.Insert(index, newNeedle, out found))
     {
         previous = default(T);
         return true;
     }
     NeedleReservoir<T, TNeedle>.DonateNeedle(newNeedle);
     // TryGetValue is null resistant
     found.TryGetValue(out previous);
     return false;
 }
Пример #23
0
        /// <summary>
        /// Removes all the elements.
        /// </summary>
        public IEnumerable <KeyValuePair <TKey, TValue> > ClearEnumerable()
        {
            // No risk of dead needles here
            var displaced = _wrapped.ClearEnumerable();

            foreach (var item in displaced)
            {
                TKey foundKey;
                if (PrivateTryGetValue(item.Key, out foundKey))
                {
                    var value = item.Value;
                    yield return(new KeyValuePair <TKey, TValue>(foundKey, value));

                    NeedleReservoir <TKey, TNeedle> .DonateNeedle(item.Key);
                }
            }
        }
Пример #24
0
        public bool TryGetOrAdd(TKey key, Func <TKey, TValue> valueFactory, out TValue stored)
        {
            if (ReferenceEquals(valueFactory, null))
            {
                throw new ArgumentNullException("valueFactory");
            }
            var needle = PrivateGetNeedle(key);
            Func <TNeedle, TValue, TValue> factory = (pairKey, foundValue) =>
            {
                TKey foundKey;
                return(valueFactory(PrivateTryGetValue(pairKey, out foundKey) ? foundKey : key));
            };

            if (_wrapped.TryGetOrAdd(needle, () => valueFactory(key), factory, out stored))
            {
                return(true);
            }
            NeedleReservoir <TKey, TNeedle> .DonateNeedle(needle);

            return(false);
        }
Пример #25
0
 /// <summary>
 /// Sets the item at the specified index.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <param name="item">The item.</param>
 /// <param name="isNew">if set to <c>true</c> the index was not previously used.</param>
 /// <exception cref="System.ArgumentOutOfRangeException">index;index must be greater or equal to 0 and less than capacity</exception>
 public void Set(int index, T item, out bool isNew)
 {
     // This may have replaced something
     _entries.Set(index, NeedleReservoir<T, TNeedle>.GetNeedle(item), out isNew);
 }
Пример #26
0
 private static TNeedle PrivateGetNeedle(TKey key)
 {
     return(NeedleReservoir <TKey, TNeedle> .GetNeedle(key));
 }