Пример #1
0
        /// <summary>
        /// Remove the specified key from the collection.
        /// </summary>
        public bool Remove(TKey key)
        {
            Shield.AssertInTransaction();
            var keeper = PrepareWrite(key);

            if (keeper != null)
            {
                var res = !keeper.Empty;
                keeper.Empty = true;
                keeper.Value = default;
                return(res);
            }
            var old = CurrentTransactionOldValue(key);

            if (old == null || old.Empty)
            {
                return(false);
            }
            var locals = _localDict.Value;

            locals.Items[key] = new ItemKeeper {
                Empty = true
            };
            locals.HasChanges = true;
            return(true);
        }
Пример #2
0
 /// <summary>
 /// Gets or sets the item with the specified key.
 /// If there are many with the same key, acts on the first one it finds!
 /// </summary>
 public TValue this[TKey key]
 {
     get
     {
         return(Shield.InTransaction(() => {
             var n = FindInternal(key);
             if (n == null)
             {
                 throw new KeyNotFoundException();
             }
             return n.Value.Value;
         }));
     }
     set
     {
         Shield.AssertInTransaction();
         // replaces the first occurrence...
         var n = FindInternal(key);
         if (n == null)
         {
             Add(key, value);
         }
         else
         {
             n.Modify((ref Node nInner) => nInner.Value = value);
         }
     }
 }
Пример #3
0
        private void RemoveInternal(Shielded <Node> node)
        {
            Shield.AssertInTransaction();
            // find the first follower in the right subtree (arbitrary choice..)
            Shielded <Node> follower;

            if (node.Value.Right == null)
            {
                follower = node;
            }
            else
            {
                follower = node.Value.Right;
                while (follower.Value.Left != null)
                {
                    follower = follower.Value.Left;
                }

                // loosing the node value right now!
                node.Modify((ref Node n) =>
                {
                    var f   = follower.Value;
                    n.Key   = f.Key;
                    n.Value = f.Value;
                });
            }
            DeleteOneChild(follower);
            OnRemove();
        }
Пример #4
0
        /// <summary>
        /// Remove the specified item from the sequence.
        /// </summary>
        public bool Remove(T item, IEqualityComparer <T> comp = null)
        {
            Shield.AssertInTransaction();
            if (comp == null)
            {
                comp = EqualityComparer <T> .Default;
            }

            var        curr     = _head;
            ItemKeeper previous = null;

            while (curr.Value != null)
            {
                if (comp.Equals(item, curr.Value.Value))
                {
                    if (curr.Value.Next.Value == null)
                    {
                        _tail.Value = previous;
                    }
                    Skip(curr);
                    return(true);
                }
                else
                {
                    previous = curr;
                    curr     = curr.Value.Next;
                }
            }
            return(false);
        }
Пример #5
0
 /// <summary>
 /// Remove the item at the given index.
 /// </summary>
 public void RemoveAt(int index)
 {
     Shield.AssertInTransaction();
     if (index == 0)
     {
         if (_head.Value == null)
         {
             throw new IndexOutOfRangeException();
         }
         Skip(_head);
         if (_head.Value == null)
         {
             _tail.Value = null;
         }
     }
     else
     {
         // slightly more tricky, in case we need to change _tail
         var r = RefToIndex(index - 1).Value;
         Skip(r.Next);
         if (r.Next.Value == null)
         {
             _tail.Value = r;
         }
     }
 }
Пример #6
0
        /// <summary>
        /// Remove from the sequence all items that satisfy the given predicate.
        /// Returns the number of removed items in an out param, guaranteed to
        /// equal actual number of removed items even if the condition lambda throws.
        /// </summary>
        public void RemoveAll(Func <T, bool> condition, out int removed)
        {
            Shield.AssertInTransaction();
            var        curr     = _head;
            var        tail     = _tail.Value;
            ItemKeeper previous = null;

            removed = 0;
            while (curr.Value != null)
            {
                if (condition(curr.Value.Value))
                {
                    removed++;
                    if (tail == curr.Value)
                    {
                        _tail.Value = previous;
                        if (previous == null)
                        {
                            _head.Value = null;
                            break;
                        }
                    }
                    Skip(curr);
                }
                else
                {
                    previous = curr;
                    curr     = curr.Value.Next;
                }
            }
        }
Пример #7
0
 /// <summary>
 /// Removes all items, but one by one.
 /// </summary>
 public void Clear()
 {
     Shield.AssertInTransaction();
     foreach (var key in Keys)
     {
         Remove(key);
     }
 }
Пример #8
0
 /// <summary>
 /// Add the specified key and value to the dictionary.
 /// </summary>
 /// <exception cref="ArgumentException">Thrown if the key is already present in the dictionary.</exception>
 public void Add(TKey key, TItem value)
 {
     Shield.AssertInTransaction();
     if (ContainsKey(key))
     {
         throw new ArgumentException("The given key is already present in the dictionary.");
     }
     this[key] = value;
 }
Пример #9
0
        /// <summary>
        /// Get an enumerator for the dictionary contents. Iterating over this dictionary
        /// does not conflict with other transactions that are adding new items, so it
        /// is not fully safe. For read-only transactions, however, no problem.
        /// </summary>
        public IEnumerator <KeyValuePair <TKey, TItem> > GetEnumerator()
        {
            Shield.AssertInTransaction();
            var keys = _localDict.HasValue ?
                       _dict.Keys.Union(_localDict.Value.Items.Keys, _comparer) : _dict.Keys;

            foreach (var key in keys)
            {
                var v = Read(key);
                if (v == null || v.Empty)
                {
                    continue;
                }
                yield return(new KeyValuePair <TKey, TItem>(key, v.Value));
            }
        }
Пример #10
0
        private void InsertInternal(TKey key, TValue item)
        {
            Shield.AssertInTransaction();
            Shielded <Node> parent     = null;
            var             targetLoc  = _head.Value;
            int             comparison = 0;

            while (targetLoc != null)
            {
                parent = targetLoc;
                if ((comparison = _comparer.Compare(targetLoc.Value.Key, key)) > 0)
                {
                    targetLoc = targetLoc.Value.Left;
                }
                else
                {
                    targetLoc = targetLoc.Value.Right;
                }
            }
            var shN = new Shielded <Node>(new Node()
            {
                //Color = Color.Red, // the default anyway.
                Parent = parent,
                Key    = key,
                Value  = item
            }, _owner);

            if (parent != null)
            {
                if (comparison > 0)
                {
                    parent.Modify((ref Node p) => p.Left = shN);
                }
                else
                {
                    parent.Modify((ref Node p) => p.Right = shN);
                }
            }
            else
            {
                _head.Value = shN;
            }
            InsertProcedure(shN);
            OnInsert();
        }
Пример #11
0
        /// <summary>
        /// Enumerate all key-value pairs, whose keys are in the given range, but in descending
        /// key order. The range is inclusive, both from and to are included in the result (if
        /// the tree contains those keys). If from is smaller than to, the enumerable will not
        /// return anything. For forward enumeration you must explicitly use <see cref="Range"/>.
        /// </summary>
        public IEnumerable <KeyValuePair <TKey, TValue> > RangeDescending(TKey from, TKey to)
        {
            if (_comparer.Compare(from, to) < 0)
            {
                yield break;
            }
            Shield.AssertInTransaction();
            Stack <Shielded <Node> > centerStack = new Stack <Shielded <Node> >();
            var curr = _head.Value;

            while (curr != null)
            {
                while (curr.Value.Right != null &&
                       _comparer.Compare(curr.Value.Key, from) <= 0)
                {
                    centerStack.Push(curr);
                    curr = curr.Value.Right;
                }

                if (_comparer.Compare(curr.Value.Key, to) < 0)
                {
                    yield break;
                }

                if (_comparer.Compare(curr.Value.Key, from) <= 0)
                {
                    yield return(new KeyValuePair <TKey, TValue>(curr.Value.Key, curr.Value.Value));
                }

                while (curr.Value.Left == null &&
                       centerStack.Count > 0)
                {
                    curr = centerStack.Pop();
                    if (_comparer.Compare(curr.Value.Key, to) >= 0)
                    {
                        yield return(new KeyValuePair <TKey, TValue>(curr.Value.Key, curr.Value.Value));
                    }
                    else
                    {
                        yield break;
                    }
                }
                curr = curr.Value.Left;
            }
        }
Пример #12
0
        /// <summary>
        /// Enumerates only over the nodes in the range. Borders included.
        /// </summary>
        private IEnumerable <Shielded <Node> > RangeInternal(TKey from, TKey to)
        {
            if (_comparer.Compare(from, to) > 0)
            {
                yield break;
            }
            Shield.AssertInTransaction();
            Stack <Shielded <Node> > centerStack = new Stack <Shielded <Node> >();
            var curr = _head.Value;

            while (curr != null)
            {
                while (curr.Value.Left != null &&
                       _comparer.Compare(curr.Value.Key, from) >= 0)
                {
                    centerStack.Push(curr);
                    curr = curr.Value.Left;
                }

                if (_comparer.Compare(curr.Value.Key, to) > 0)
                {
                    yield break;
                }

                if (_comparer.Compare(curr.Value.Key, from) >= 0)
                {
                    yield return(curr);
                }

                while (curr.Value.Right == null &&
                       centerStack.Count > 0)
                {
                    curr = centerStack.Pop();
                    if (_comparer.Compare(curr.Value.Key, to) <= 0)
                    {
                        yield return(curr);
                    }
                    else
                    {
                        yield break;
                    }
                }
                curr = curr.Value.Right;
            }
        }
Пример #13
0
        /// <summary>
        /// Get an enumerator for the sequence. Although it is just a read, it must be
        /// done in a transaction since concurrent changes would make the result unstable.
        /// However, if you just read the first item (e.g. by calling Any or First), that
        /// will work out of transaction too.
        /// </summary>
        public IEnumerator <T> GetEnumerator()
        {
            var curr = _head.Value;

            if (curr == null)
            {
                yield break;
            }
            yield return(curr.Value);

            Shield.AssertInTransaction();
            curr = curr.Next;
            while (curr != null)
            {
                yield return(curr.Value);

                curr = curr.Next;
            }
        }
Пример #14
0
        /// <summary>
        /// Gets an enumerator for all the key-value pairs in the tree.
        /// </summary>
        public IEnumerator <KeyValuePair <TKey, TValue> > GetEnumerator()
        {
            Shield.AssertInTransaction();
            Stack <Shielded <Node> > centerStack = new Stack <Shielded <Node> >();
            var curr = _head.Value;

            while (curr != null)
            {
                while (curr.Value.Left != null)
                {
                    centerStack.Push(curr);
                    curr = curr.Value.Left;
                }

                yield return(new KeyValuePair <TKey, TValue>(curr.Value.Key, curr.Value.Value));

                while (curr.Value.Right == null && centerStack.Count > 0)
                {
                    curr = centerStack.Pop();
                    yield return(new KeyValuePair <TKey, TValue>(curr.Value.Key, curr.Value.Value));
                }
                curr = curr.Value.Right;
            }
        }