Commit df6523ef authored by Marc Gravell's avatar Marc Gravell

Preserve order: didn't (quite); fixed

parent d80ca807
...@@ -110,8 +110,14 @@ private static void ProcessAsyncCompletionQueue(object state) ...@@ -110,8 +110,14 @@ private static void ProcessAsyncCompletionQueue(object state)
} }
partial void OnCompletedAsync(); partial void OnCompletedAsync();
int activeAsyncWorkerThread = 0;
private void ProcessAsyncCompletionQueueImpl() private void ProcessAsyncCompletionQueueImpl()
{ {
int currentThread = Environment.CurrentManagedThreadId;
try
{
if (Interlocked.CompareExchange(ref activeAsyncWorkerThread, currentThread, 0) != 0) return;
int total = 0; int total = 0;
do do
{ {
...@@ -121,32 +127,41 @@ private void ProcessAsyncCompletionQueueImpl() ...@@ -121,32 +127,41 @@ private void ProcessAsyncCompletionQueueImpl()
next = asyncCompletionQueue.Count == 0 ? null next = asyncCompletionQueue.Count == 0 ? null
: asyncCompletionQueue.Dequeue(); : asyncCompletionQueue.Dequeue();
} }
if(next == null && Thread.Yield()) // give it a moment and try again if (next == null)
{ {
// give it a moment and try again, noting that we might lose the battle
// when we pause
Interlocked.CompareExchange(ref activeAsyncWorkerThread, 0, currentThread);
if (Thread.Yield() && Interlocked.CompareExchange(ref activeAsyncWorkerThread, currentThread, 0) == 0)
{
// we paused, and we got the lock back; anything else?
lock (asyncCompletionQueue) lock (asyncCompletionQueue)
{ {
next = asyncCompletionQueue.Count == 0 ? null next = asyncCompletionQueue.Count == 0 ? null
: asyncCompletionQueue.Dequeue(); : asyncCompletionQueue.Dequeue();
} }
} }
if (next == null) break; // nothing to do }
if (next == null) break; // nothing to do <===== exit point
try try
{ {
multiplexer.Trace("Completing async (ordered): " + next, name); multiplexer.Trace("Completing async (ordered): " + next, name);
next.TryComplete(true); next.TryComplete(true);
Interlocked.Increment(ref completedAsync); Interlocked.Increment(ref completedAsync);
} }
catch(Exception ex) catch (Exception ex)
{ {
multiplexer.Trace("Async completion error: " + ex.Message, name); multiplexer.Trace("Async completion error: " + ex.Message, name);
Interlocked.Increment(ref failedAsync); Interlocked.Increment(ref failedAsync);
} }
total++; total++;
} while (true); } while (true);
multiplexer.Trace("Async completion worker processed " + total + " operations", name); multiplexer.Trace("Async completion worker processed " + total + " operations", name);
} }
finally
{
Interlocked.CompareExchange(ref activeAsyncWorkerThread, 0, currentThread);
}
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment