registerCondition :: Lock -> IO (Condition Lock)
registerCondition l = mask_ $ do
  conds <- takeMVar $ lockConditions l
  newCond <- newEmptyMVar
  putMVar (lockConditions l) $ conds { conditions = V.snoc (conditions conds) newCond }
  let destroyImpl = modifyMVarMasked_ (lockConditions l) $ \laterConds -> do
        putMVar newCond ()
        let updatedConditions = V.filter (/= newCond) (conditions laterConds)
        return $ laterConds { conditions = updatedConditions
                            , lastNotified = if lastNotified laterConds > V.length updatedConditions
                                               then 0
                                               else lastNotified laterConds
                            }
      -- release lock, block until signal, then reacquire lock
      awaitImpl = mask_ (putMVar (lock l) () >> takeMVar newCond >> takeMVar (lock l))
  return $ Condition awaitImpl (signalImpl l) (signalAllImpl l) destroyImpl
registerCondition :: Lock -> IO (Condition Lock)
registerCondition l = mask_ $ do
  conds <- takeMVar $ lockConditions l
  newCond <- newEmptyMVar
  putMVar (lockConditions l) $ conds { conditions = V.snoc (conditions conds) newCond }
  let destroyImpl = modifyMVarMasked_ (lockConditions l) $ \laterConds -> do
        putMVar newCond ()
        let updatedConditions = V.filter (/= newCond) (conditions laterConds)
        return $ laterConds { conditions = updatedConditions
                            , lastNotified = if lastNotified laterConds > V.length updatedConditions
                                               then 0
                                               else lastNotified laterConds
                            }
      -- release lock, block until signal, then reacquire lock
      awaitImpl = mask_ (putMVar (lock l) () >> takeMVar newCond >> takeMVar (lock l))
  return $ Condition awaitImpl (signalImpl l) (signalAllImpl l) destroyImpl
registerCondition l = mask_ $ do
  conds <- takeMVar $ lockConditions l
  newCond <- newEmptyMVar
  putMVar (lockConditions l) $ conds { conditions = V.snoc (conditions conds) newCond }
  let destroyImpl = modifyMVarMasked_ (lockConditions l) $ \laterConds -> do
        putMVar newCond ()
        let updatedConditions = V.filter (/= newCond) (conditions laterConds)
        return $ laterConds { conditions = updatedConditions
                            , lastNotified = if lastNotified laterConds > V.length updatedConditions
                                               then 0
                                               else lastNotified laterConds
                            }
      -- release lock, block until signal, then reacquire lock
      awaitImpl = mask_ (putMVar (lock l) () >> takeMVar newCond >> takeMVar (lock l))
  return $ Condition awaitImpl (signalImpl l) (signalAllImpl l) destroyImpl