public PopResult PopBottom(out T obj)
        {
            obj = default(T);

            int b    = CustomInterlocked.Decrement(ref bottom);
            var a    = array;
            int t    = top;
            int size = b - t;

            if (size < 0)
            {
                // Set bottom to t
                CustomInterlocked.Add(ref bottom, t - b);
                return(PopResult.Empty);
            }

            obj = a.segment[b % a.size];
            if (size > 0)
            {
                return(PopResult.Succeed);
            }
            CustomInterlocked.Add(ref bottom, t + 1 - b);

            if (CustomInterlocked.CompareExchange(ref top, t + 1, t) != t)
            {
                return(PopResult.Empty);
            }

            return(PopResult.Succeed);
        }
        public void PushRange(T[] items, int startIndex, int count)
        {
            RangeArgumentsCheck(items, startIndex, count);

            Node insert = null;
            Node first  = null;

            for (int i = startIndex; i < count; i++)
            {
                Node temp = new Node();
                temp.Value = items[i];
                temp.Next  = insert;
                insert     = temp;

                if (first == null)
                {
                    first = temp;
                }
            }

            do
            {
                first.Next = Head;
            } while (CustomInterlocked.CompareExchange(ref head, insert, first.Next) != first.Next);

            CustomInterlocked.Add(ref this.count, count);
        }
            public void EnterReadLock()
            {
                SpinWait sw = new SpinWait();

                do
                {
                    while ((rwlock & (RwWrite | RwWait)) > 0)
                    {
                        sw.SpinOnce();
                    }

                    if ((CustomInterlocked.Add(ref rwlock, RwRead) & (RwWait | RwWait)) == 0)
                    {
                        return;
                    }

                    CustomInterlocked.Add(ref rwlock, -RwRead);
                } while (true);
            }
        public int TryPopRange(T[] items, int startIndex, int count)
        {
            RangeArgumentsCheck(items, startIndex, count);

            Node temp;
            Node end;

            do
            {
                temp = Head;
                if (temp == null)
                {
                    return(0);
                }
                end = temp;
                for (int j = 0; j < count; j++)
                {
                    end = end.Next;
                    if (end == null)
                    {
                        break;
                    }
                }
            } while (CustomInterlocked.CompareExchange(ref head, end, temp) != temp);

            int i;

            for (i = startIndex; i < startIndex + count && temp != null; i++)
            {
                items[i] = temp.Value;
                end      = temp;
                temp     = temp.Next;
            }
            CustomInterlocked.Add(ref this.count, -(i - startIndex));

            return(i - startIndex);
        }
 public void ExitWriteLock()
 {
     CustomInterlocked.Add(ref rwlock, -RwWrite);
 }
 public void ExitReadLock()
 {
     CustomInterlocked.Add(ref rwlock, -RwRead);
 }