// for ordinary thread
        public Task PopBottom()
        {
            if (bottom == 0)
            {
                return(null);
            }
            Interlocked.Decrement(ref bottom);
            Task t = tasks[bottom];
            int  stamp;
            int  oldTop = top.Get(out stamp);
            int  newTop = 0;
            int  oldStamp = stamp, newStamp = oldStamp + 1;

            if (bottom > oldTop)
            {
                return(t);
            }
            if (bottom == oldTop)
            {
                bottom = 0;
                if (top.CompareAndSet(oldTop, newTop, oldStamp, newStamp))
                {
                    return(t);
                }
            }
            top.Set(newTop, newStamp);
            return(null);
        }
Esempio n. 2
0
        public Task PopBottom()
        {
            if (bottom == 0)
            {
                return(null);                               //если очередь пуста, немедленно возвращаемся
            }
            bottom--;                                       // уменьшаем значение нижней границы, чтобы воры увидели, что брать нечего, если это последняя задача
            Task t = tasks[bottom];                         //берем последнюю задачу
            int  stamp;
            int  oldTop = top.Get(out stamp);               //сохраняем верхний индекс со штампом
            int  newTop = 0;                                //объявляем новый верхний индекс
            int  oldStamp = stamp, newStamp = oldStamp + 1; // сохраняем старый штамп и делаем новый, увеличив старый на 1

            if (bottom > oldTop)                            //проверяем, больше ли лекущий нижний индекс, чем верхний // задачи есть
            {
                return(t);                                  //возвращаем задачу
            }
            //если верхний равен нижнему элементу
            if (bottom == oldTop)
            {
                //только одна задача и возможен конфликт с вором
                bottom = 0; // нижний индекс устанавливаем в 0
                if (top.CompareAndSet(oldTop, newTop, oldStamp, newStamp))
                {
                    //если сбросился верхний индекс в 0 и поменялся штамп на новый
                    return(t); //отдаем задачу
                }
            }
            top.Set(newTop, newStamp); //двигаем глобальную верхнюю вершину в 0 с новым штампом
            return(null);              //говорим, что нечего отдать
        }