Figured the barrier race condition might be a failure to find an op throwing during complete_async_op, in which case the op would never get removed and therefore would become stuck. Therefore made failure to find op a fatal exception, and made the op removal exception safe. Sadly, no difference to race condition.
Added an optimisation pass to barrier() which pre-sweeps the input ops for readiness, and
for those not ready a batch wait_for_all() is done. This should avoid a potential syscall
per input op.
Made barrier() hold its input ops weakly to see if that might fix stuck ops which are really just circular shared_ptr. It didn't.
Finally nailed that race condition which was randomly hanging the unit tests and leaving stuck ops around.
Removed the earlier temporary code making barrier() take weak references.