protected virtual void ReturnNode(Node *node)
        {
            // Set the finished reading flag for this node (the node is reserved so no need for locks)
            node->DoneRead = 1;

            // Keep it clean and reset AmountWritten to prepare it for next Write
            node->AmountWritten = 0;

            // Move the read pointer forward as far as possible
            // always starting from ReadEnd to make all contiguous
            // read nodes available for writing.
            for (; ;)
            {
                int blockIndex = _nodeHeader->ReadEnd;
                node = this[blockIndex];
                #pragma warning disable 0420 // ignore ref to volatile warning - Interlocked API
                if (Interlocked.CompareExchange(ref node->DoneRead, 0, 1) != 1)
                {
                    // If we get here then another read thread has already moved the pointer
                    // or we have moved ReadEnd as far forward as we can
                    return;
                }

                // Move the pointer forward one node
                Interlocked.CompareExchange(ref _nodeHeader->ReadEnd, node->Next, blockIndex);
                #pragma warning restore 0420

                // If a writer thread is waiting on "node available" signal the event
                if (node->Prev == _nodeHeader->WriteStart)
                {
                    NodeAvailable.Set();
                }
            }
        }
        protected virtual Node *GetNodeForWriting(int timeout)
        {
            for (; ;)
            {
                int   blockIndex = _nodeHeader->WriteStart;
                Node *node       = this[blockIndex];
                if (node->Next == _nodeHeader->ReadEnd)
                {
                    // No room is available, wait for room to become available
                    if (NodeAvailable.WaitOne(timeout))
                    {
                        continue;
                    }

                    // Timeout
                    return(null);
                }

                #pragma warning disable 0420 // ignore ref to volatile warning - Interlocked API
                if (Interlocked.CompareExchange(ref _nodeHeader->WriteStart, node->Next, blockIndex) == blockIndex)
                {
                    return(node);
                }
                #pragma warning restore 0420

                // Another thread has already acquired this node for writing, try again.
                continue;
            }
        }