Пример #1
0
        /// <summary>
        /// This operation will grow the inner array and sweep up deleted nodes
        /// This is an expensive operation that we should minimize the usage of if possible
        /// </summary>
        /// <returns></returns>
        protected void GrowInnerArray()
        {
            var oldNodes = InnerArray;

            int newArraySize;

            if (PrimeNumberEnumerator.MoveNext() != false)
            {
                newArraySize = (int)PrimeNumberEnumerator.Current;
            }
            else
            {
                throw new ArgumentOutOfRangeException("The ODDictionary has reached its maximum capacity.");
            }

            InnerArray = new ODDictionaryNode <TKey, TValue> [newArraySize];

            foreach (var node in oldNodes)
            {
                if (node != null && node.IsDeleted == false)
                {
                    // get the initial probe value
                    int keyLocation = GetIndexForKey(node.Key);

                    // confirm that key is not present and get first available insert location
                    bool keyAlreadyPresent;
                    keyLocation = FirstAvailable(keyLocation, node.Key, out keyAlreadyPresent);

                    //we don't need to worry about keyAlreadyPresent because we're repopulating a new array
                    InnerArray[keyLocation] = node;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Finds the first available non-key location in the index to perform an insert. Or the key location if it is already present.
        /// Instead of an out parameter, throw could be used, but in this case, finding a key is to be expected, and try/catch should not be used
        /// for control flow.
        /// </summary>
        /// <param name="keyLocation">Starting index to probe</param>
        /// <param name="key">The to be inserted</param>
        /// <param name="keyAlreadyPresent">Outpool boolean, flag is true is the key is already present</param>
        /// <returns>Location to perform insert or the location of the key if already present</returns>
        protected int FirstAvailable(int keyLocation, TKey key, out bool keyAlreadyPresent)
        {
            ODDictionaryNode <TKey, TValue> currentNode = InnerArray[keyLocation];
            int firstGoodLocation = -1;

            keyAlreadyPresent = false;
            // probe the values, if it's null we're good
            while (currentNode != null)
            {
                // We found an indentical key, insert is not logically possible, stop searching
                if (currentNode.Key.Equals(key) && !currentNode.IsDeleted)
                {
                    keyAlreadyPresent = true;
                    break;
                }

                // we found a deleted location, remember it for later to use it
                if (currentNode.IsDeleted && firstGoodLocation == -1)
                {
                    firstGoodLocation = keyLocation;
                }

                keyLocation = (keyLocation + 1) % InnerArray.Length;
                currentNode = InnerArray[keyLocation];
            }

            // if we didn't find the key, but we found a first location that's prior to our first null, then return that.
            if (!keyAlreadyPresent && firstGoodLocation != -1)
            {
                keyLocation = firstGoodLocation;
            }

            return(keyLocation);
        }
Пример #3
0
        private bool OptimisticConcurrencyControl; // simple control to detect concurrency exceptions rather than locking resources

        public ODDictionary()
        {
            PrimeNumberEnumerator = SetPrimeNumbers();
            PrimeNumberEnumerator.MoveNext();
            CurrentSize                  = 0;
            InnerArray                   = new ODDictionaryNode <TKey, TValue> [(int)PrimeNumberEnumerator.Current];
            EnumeratorsToInvalidate      = new List <ODDictionaryEnumerator <TKey, TValue> >();
            OptimisticConcurrencyControl = false;
        }
Пример #4
0
        /// <summary>
        /// Allows the user to set the initial value of the inner array
        /// </summary>
        /// <param name="initialArraySize">Int32 for the size of the inner array</param>
        public ODDictionary(int initialArraySize)
        {
            PrimeNumberEnumerator = SetPrimeNumbers();

            while (PrimeNumberEnumerator.MoveNext() != false)
            {
                // next grow will be at least initialArraySize *2
                if ((int)PrimeNumberEnumerator.Current > (initialArraySize * 2))
                {
                    break;
                }
            }

            CurrentSize                  = 0;
            InnerArray                   = new ODDictionaryNode <TKey, TValue> [initialArraySize];
            EnumeratorsToInvalidate      = new List <ODDictionaryEnumerator <TKey, TValue> >();
            OptimisticConcurrencyControl = false;
        }
Пример #5
0
        /// <summary>
        /// Add a Key/Value pair to the collection.  Throws exception if key already present.
        /// </summary>
        /// <param name="key">Key to be used for retrieval, may not be null</param>
        /// <param name="value">Value to be returned on retrieval</param>
        public void Add(TKey key, TValue value)
        {
            // check concurrency control
            if (OptimisticConcurrencyControl == true)
            {
                throw new Exception("Optimistic concurrency control violated");
            }
            // set control
            OptimisticConcurrencyControl = true;

            // validation
            if (key == null || value == null)
            {
                OptimisticConcurrencyControl = false;
                throw new ArgumentNullException("Neither key nor value may be null.");
            }

            // To minimize collisions, we will grow the collection when it is half full
            if (CurrentSize > InnerArray.Length / 2)
            {
                GrowInnerArray();
            }

            // get the initial probe value
            int keyLocation = GetIndexForKey(key);

            // confirm that key is not present and get first available insert location
            bool keyAlreadyPresent;

            keyLocation = FirstAvailable(keyLocation, key, out keyAlreadyPresent);

            if (keyAlreadyPresent)
            {
                OptimisticConcurrencyControl = false;
                throw new ArgumentException("An item with the same key has already been added.");
            }

            var odDictionaryNode = new ODDictionaryNode <TKey, TValue>(key, value);

            InnerArray[keyLocation]      = odDictionaryNode;
            OptimisticConcurrencyControl = false; // release control
            InvalidateEnumerators();
            CurrentSize++;
        }
Пример #6
0
        /// <summary>
        /// The find & return method.  Specify a key and get the return value requested or set value.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public TValue this[TKey key]
        {
            get
            {
                // check concurrency control
                if (OptimisticConcurrencyControl == true)
                {
                    throw new Exception("Optimistic concurrency control violated");
                }
                OptimisticConcurrencyControl = true;

                // validation
                if (key == null)
                {
                    OptimisticConcurrencyControl = false;
                    throw new ArgumentNullException("Key may not be null.");
                }

                int keyLocation = GetIndexForKey(key);

                // Find the key
                bool keyAlreadyPresent;
                keyLocation = FirstAvailable(keyLocation, key, out keyAlreadyPresent);

                if (!keyAlreadyPresent)
                {
                    OptimisticConcurrencyControl = false;
                    throw new KeyNotFoundException("The given key was not present in the dictionary.");
                }

                var value = InnerArray[keyLocation].Value;
                OptimisticConcurrencyControl = false;
                return(value);
            }
            set
            {
                // check concurrency control
                if (OptimisticConcurrencyControl == true)
                {
                    throw new Exception("Optimistic concurrency control violated");
                }
                OptimisticConcurrencyControl = true;

                int keyLocation = GetIndexForKey(key);

                // Find the key
                bool keyAlreadyPresent;
                keyLocation = FirstAvailable(keyLocation, key, out keyAlreadyPresent);

                // if it's not yet in the dictionary, add it
                if (!keyAlreadyPresent)
                {
                    var odDictionaryNode = new ODDictionaryNode <TKey, TValue>(key, value);
                    InnerArray[keyLocation] = odDictionaryNode;
                    CurrentSize++;
                    OptimisticConcurrencyControl = false;
                }
                else
                {
                    // else just update the value
                    InnerArray[keyLocation].Value = value;
                    OptimisticConcurrencyControl  = false;
                }
                InvalidateEnumerators();
            }
        }