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); }
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); }
/// <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; }
/// <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); }
/// <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; } }
/// <summary> /// Removes all the elements. /// </summary> public void Clear() { var displaced = _wrapped.ClearEnumerable(); foreach (var item in displaced) { NeedleReservoir <TKey, TNeedle> .DonateNeedle(item.Key); } }
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); }
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); }
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); }
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); }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; } }
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; }
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; }
/// <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; }
/// <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); } } }
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); }