// // 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); }