DispatchQueueWrapper.resume() was made more reliable
DispatchQueueWrapper.resume() was made more reliable

resume() will now busy-wait while the state variable equals "Transient".
suspend() does not: when suspend() fails to dispatch_suspend(), the queue will get another chance to suspend itself.

If resume() fails, it could mean that neither queue is running, a deadlock situation.

The busy-wait eliminates a failure situation where a resume() call happens shortly after a suspend() call from another thread. In such a case, resume() could get to the OSAtomicCompareAndSwap() call while state equals Transient; it would previously have exited with no effect. In just the wrong situation, two alternating queues could both be left in a suspended state, deadlocked. With the busy-wait in place, resume() only fails to call dispatch_resume() when it loses a race with another resume() call on a different thread; that is not a problem.

glessard/swift-channels,glessard/swift-channels