Ejemplo n.º 1
0
        /// <summary>
        /// Sets the provided item (ref or null) to all available cells.
        /// The Drive must be N.
        /// </summary>
        /// <remarks>The method is synchronized.</remarks>
        /// <param name="item">The ref to be set</param>
        /// <exception cref="System.InvalidOperationException">Drive is not N or Straight</exception>
        public void Format(T item)
        {
            lock (commonLock)
            {
                Interlocked.Increment(ref i[CCOPS]);

                try
                {
                    if (Drive != TesseractGear.N)
                    {
                        throw new InvalidOperationException("Wrong drive");
                    }

                    var p = new TesseractPos(AllocatedSlots - 1);

                    for (int d0 = 0; d0 <= p.D0; d0++)
                    {
                        for (int d1 = 0; d1 <= p.D1; d1++)
                        {
                            for (int d2 = 0; d2 <= p.D2; d2++)
                            {
                                for (int d3 = 0; d3 <= p.D3; d3++)
                                {
                                    blocks[d0][d1][d2][d3] = item;
                                }
                            }
                        }
                    }
                }
                finally
                {
                    Interlocked.Decrement(ref i[CCOPS]);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Sets value at index if the current value equals the comparand.
        /// </summary>
        /// <param name="index">The index must be less than AllocatedSlots.</param>
        /// <param name="value">The value to be set at index.</param>
        /// <param name="comparand">Will be compared to this[index]</param>
        /// <returns>The original value at index.</returns>
        public T CAS(int index, T value, T comparand)
        {
            if (Drive == TesseractGear.P)
            {
                throw new InvalidOperationException("Wrong drive");
            }
            if (index < 0 || index >= AllocatedSlots)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            var p = new TesseractPos(index);
            var r = Interlocked.CompareExchange(ref blocks[p.D0][p.D1][p.D2][p.D3], value, comparand);

            if (CountNotNulls)
            {
                if (r != null)
                {
                    if (value == null)
                    {
                        Interlocked.Decrement(ref i[NNCNT]);
                    }
                }
                else if (value != null)
                {
                    Interlocked.Increment(ref i[NNCNT]);
                }
            }

            return(r);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Access to the individual cells.
        /// </summary>
        /// <param name="index">Must be less than AllocatedSlots</param>
        /// <returns>The object reference at the index</returns>
        /// <exception cref="ArgumentOutOfRangeException">index</exception>
        /// <exception cref="System.InvalidOperationException">If the Drive is wrong</exception>
        public T this[int index]
        {
            get
            {
                if (Drive == TesseractGear.P)
                {
                    throw new InvalidOperationException("Wrong drive");
                }
                if (index < 0 || index >= AllocatedSlots)
                {
                    throw new ArgumentOutOfRangeException("index");
                }

                var p = new TesseractPos(index);

                return(Volatile.Read(ref blocks[p.D0][p.D1][p.D2][p.D3]));
            }
            set
            {
                if (Drive == TesseractGear.P)
                {
                    throw new InvalidOperationException("Wrong drive");
                }
                if (index < 0 || index >= AllocatedSlots)
                {
                    throw new ArgumentOutOfRangeException("index");
                }

                set(index, value);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Searches for an item by traversing all cells up to AppendIndex.
        /// The reads are volatile, the comparison Object.Equals().
        /// </summary>
        /// <param name="item">The object ref</param>
        /// <returns>A positive value if the item is found, -1 otherwise.</returns>
        public int IndexOf(T item)
        {
            int result = -1;
            int aIdx   = AppendIndex;
            var p      = new TesseractPos(0);

            for (var i = 0; i <= aIdx; i++)
            {
                p.Set(i);

                var r = Volatile.Read(ref blocks[p.D0][p.D1][p.D2][p.D3]);

                if (r != null && r.Equals(item))
                {
                    result = i;
                    break;
                }
            }

            return(result);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Iterates all cells from 0 up to AppendIndex and yields each item
        /// if it's not null at the time of the check.
        /// </summary>
        /// <param name="assertGear">If true volatile-reads the Drive at each iteration. False by default. </param>
        /// <returns>A not null item.</returns>
        /// <exception cref="InvalidOperationException">If the Drive is P</exception>
        public IEnumerable <T> NotNullItems(bool assertGear = false, bool allSlots = false)
        {
            T   item = null;
            var j    = allSlots ? AllocatedSlots - 1 : AppendIndex;
            var p    = new TesseractPos(j);

            for (int i = 0; i <= j; i++)
            {
                if (assertGear && Drive == TesseractGear.P)
                {
                    throw new InvalidOperationException("Wrong drive");
                }

                p.Set(i);
                item = Volatile.Read(ref blocks[p.D0][p.D1][p.D2][p.D3]);

                if (item != null)
                {
                    yield return(item);
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Expands or shrinks the virtual array to the number of SIDE tiles fitting the requested length.
        /// If the AppendIndex is greater that the new length, it's cut to length -1.
        /// If shrinking and counting, the number of not-null values (ItemsCount) is also updated.
        /// The Drive must be P when shrinking.
        /// </summary>
        /// <param name="length">The new length.</param>
        /// <param name="expand">The intent of the caller.</param>
        /// <exception cref="System.ArgumentOutOfRangeException">If length is negative</exception>
        /// <exception cref="System.InvalidOperationException">
        /// If the Drive is not P when shrinking.</exception>
        public bool Resize(int length, bool expand)
        {
            Interlocked.Increment(ref i[CCOPS]);
            TesseractGear inDrive = Drive;

            try
            {
                var slots = Volatile.Read(ref i[SLOTS]);
                if (length < 0)
                {
                    throw new ArgumentOutOfRangeException("length");
                }
                if (length == slots)
                {
                    return(false);
                }

                lock (commonLock)
                {
                    var als = Volatile.Read(ref i[SLOTS]);

                    if (length == als)
                    {
                        return(false);
                    }
                    if (length > als)
                    {
                        return(expand ? alloc(length, als) > als : false);
                    }
                    else
                    {
                        if (expand)
                        {
                            return(false);
                        }

                        if (inDrive != TesseractGear.P)
                        {
                            throw new InvalidOperationException("Wrong drive");
                        }

                        var toSize = length > 0 ? length + SIDE : 0;
                        var p      = new TesseractPos(als);

                        while (als > toSize)
                        {
                            p.D2--;
                            if (p.D2 < 1)
                            {
                                blocks[p.D0][p.D1] = null;
                                p.D1--;
                                if (p.D1 < 1)
                                {
                                    p.D0--;
                                    p.D1 = SIDE - 1;
                                }
                                p.D2 = SIDE - 1;
                            }
                            else
                            {
                                blocks[p.D0][p.D1][p.D2] = null;
                            }

                            als -= SIDE;
                        }

                        Volatile.Write(ref i[SLOTS], als);

                        if (AppendIndex >= length)
                        {
                            Interlocked.Exchange(ref i[INDEX], length - 1);
                        }
                        if (CountNotNulls)
                        {
                            int notNull = 0;
                            foreach (var c in NotNullItems())
                            {
                                notNull++;
                            }
                            Interlocked.Exchange(ref i[NNCNT], notNull);
                        }

                        return(true);
                    }
                }
            }
            finally
            {
                if (Interlocked.Decrement(ref i[CCOPS]) == 0 && inDrive != Drive)
                {
                    gearShift.Set();
                }
            }
        }