ref-extras-0.2.0: src/RefExtras/UVar.hs
module RefExtras.UVar
( UVar
, newUVar
, takeUVar
, isTakenUVar
, cloneUVar
) where
import Control.Monad.IO.Class (MonadIO)
import UnliftIO.MVar (MVar, isEmptyMVar, newEmptyMVar, newMVar, tryTakeMVar)
-- | A "unique var" - something that can only be taken once.
newtype UVar a = UVar { unUVar :: MVar a }
newUVar :: MonadIO m => a -> m (UVar a)
newUVar = fmap UVar . newMVar
takeUVar :: MonadIO m => UVar a -> m (Maybe a)
takeUVar = tryTakeMVar . unUVar
isTakenUVar :: MonadIO m => UVar a -> m Bool
isTakenUVar = isEmptyMVar . unUVar
-- | Create a new 'UVar' with the contents of this.
-- If this is taken, the created 'UVar' is empty.
-- Otherwise, takes this and creates the other.
-- In all cases, this is left taken.
cloneUVar :: MonadIO m => UVar a -> m (UVar a)
cloneUVar u = takeUVar u >>= maybe (fmap UVar newEmptyMVar) newUVar