I had a fun five minutes today trying to express a wait on three WaitHandles X, Y and Z in which I want both of X and Y to be signalled, but have Z as an early escape. It’s soon clear that you can’t express:
(X && Y) || Z
With WaitAll and WaitOne, e.g. as
WaitHandle.WaitAll{ X, Y } || Z.WaitOne
because WaitAll blocks.
Thanks to the fact that boolean operations are distributive I can recompose (X && Y) || Z as
(X || Z) && (Y || Z)
and apply that structure in this case as
WaitHandle.WaitAny{ X, Z } && WaitHandle.WaitAny{ Y, Z }
with the proviso that the state of Z is unchanged by the Wait – for example, as long as Z does not autoreset.
My particular example was in managing a task workflow – the kind of thing that’s (almost certainly) made redundant by the TPL in .NET 4+. In my case, X and Y are a throttle on in-flight tasks, and a turnstile that admits workers when tasks are newly runnable. Z is an early escape in case of shutdown or exception.
I’m hoping that some clever bod will spot this and point out there’s a perfectly natural and convenient way of expressing this more simply.
No comments:
Post a Comment