Exemplo n.º 1
0
        //
        // Executes the prologue of the BlockingQueue<T>.TryTake method.
        //

        internal override WaitNode TryTakePrologue(StParker pk, int key, out T di, ref WaitNode ignored)
        {
            //
            // Acquire the queue's lock and check if the queue's is empty.
            //

            qlock.Enter();
            if (count != 0)
            {
                //
                // The queue isn't empty; so, ...
                //

                if (!pk.TryLock())
                {
                    qlock.Exit();
                    di = default(T);
                    return(null);
                }
                pk.UnparkSelf(key);

                //
                // Retrieve a data item from the queue.
                //

                di = items[head];
                if (++head == length)
                {
                    head = 0;
                }
                count--;

                //
                // If the wait queue isn't empty, try to use the freed
                // slot to release one of the waiter threads.
                //

                if (!waitQueue.IsEmpty)
                {
                    do
                    {
                        WaitNode w   = waitQueue.Dequeue();
                        StParker pk2 = w.parker;
                        if (pk2.TryLock())
                        {
                            items[tail] = w.channel;
                            if (++tail == length)
                            {
                                tail = 0;
                            }
                            count++;
                            qlock.Exit();
                            pk2.Unpark(w.waitKey);
                            return(null);
                        }
                    } while (!waitQueue.IsEmpty);
                }

                //
                // Release the queue's lock and return null to signal that the
                // take operation was accomplished.
                //

                qlock.Exit();
                return(null);
            }

            //
            // The queue's buffer is empty; so, create ...
            //

            WaitNode wn = new WaitNode(pk, key);

            if (lifoQueue)
            {
                waitQueue.EnqueueHead(wn);
            }
            else
            {
                waitQueue.Enqueue(wn);
            }

            //
            // Release the queue's lock and return the wait node
            // inserted in the wait queue.
            //

            qlock.Exit();
            di = default(T);
            return(wn);
        }