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