justinstenning / SharedMemory

C# shared memory classes for sharing data between processes (Array, Buffer and Circular Buffer)
https://www.nuget.org/packages/SharedMemory
Other
566 stars 118 forks source link

Add cancellation support for blocking methods #71

Open ekalchev opened 8 months ago

ekalchev commented 8 months ago

There is no way to interrupt a method like CircularBuffer.Read before the timeout limit is exceeded. This is problem is you want to gracefully wait for exit of a worker thread, you must wait the timeout of Read method. This applies to all methods that accept timeouts. To support cancellation for Read method, GetNodeForReading method should be modified like this

protected unsafe virtual Node* GetNodeForReading(int timeout, CancellationToken cancellationToken)
{
    Node* ptr;
    while (true)
    {
        int readStart = _nodeHeader->ReadStart;
        ptr = this[readStart];
        if (readStart == _nodeHeader->WriteEnd)
        {
            int result = WaitHandle.WaitAny(new WaitHandle[] { cancellationToken.WaitHandle, DataExists }, timeout, false);

            if(result == WaitHandle.WaitTimeout || result == 0)
            {
                return null;
            }
        }
        else if (Interlocked.CompareExchange(ref _nodeHeader->ReadStart, ptr->Next, readStart) == readStart)
        {
            break;
        }
    }

same goes for other methods that are having wait handles.
    return ptr;
}