Skip to content
Snippets Groups Projects
Commit 73e448b1 authored by Jens Nolte's avatar Jens Nolte
Browse files

Move AsyncVar to Quasar.Awaitable and remove some helper functions

parent 50f7fb99
No related branches found
No related tags found
No related merge requests found
module Quasar.Awaitable (
-- * Awaitable
IsAwaitable(..),
awaitSTM,
Awaitable,
......@@ -7,8 +8,20 @@ module Quasar.Awaitable (
completedAwaitable,
awaitableFromSTM,
peekAwaitable,
) where
-- * AsyncVar
AsyncVar,
newAsyncVar,
newAsyncVarSTM,
putAsyncVarEither,
putAsyncVarEitherSTM,
putAsyncVar,
putAsyncVar_,
failAsyncVar,
failAsyncVar_,
putAsyncVarEither_,
putAsyncVarEitherSTM_,
) where
import Control.Concurrent.STM
import Control.Monad.Catch
......@@ -65,3 +78,45 @@ awaitableFromSTM fn = do
pure value
Right value -> pure value
-- ** AsyncVar
-- | The default implementation for an `Awaitable` that can be fulfilled later.
newtype AsyncVar r = AsyncVar (TMVar (Either SomeException r))
instance IsAwaitable r (AsyncVar r) where
peekSTM (AsyncVar var) = tryReadTMVar var
newAsyncVarSTM :: STM (AsyncVar r)
newAsyncVarSTM = AsyncVar <$> newEmptyTMVar
newAsyncVar :: MonadIO m => m (AsyncVar r)
newAsyncVar = liftIO $ AsyncVar <$> newEmptyTMVarIO
putAsyncVarEither :: forall a m. MonadIO m => AsyncVar a -> Either SomeException a -> m Bool
putAsyncVarEither var = liftIO . atomically . putAsyncVarEitherSTM var
putAsyncVarEitherSTM :: AsyncVar a -> Either SomeException a -> STM Bool
putAsyncVarEitherSTM (AsyncVar var) = tryPutTMVar var
putAsyncVar :: MonadIO m => AsyncVar a -> a -> m Bool
putAsyncVar var = putAsyncVarEither var . Right
putAsyncVar_ :: MonadIO m => AsyncVar a -> a -> m ()
putAsyncVar_ var = void . putAsyncVar var
failAsyncVar :: MonadIO m => AsyncVar a -> SomeException -> m Bool
failAsyncVar var = putAsyncVarEither var . Left
failAsyncVar_ :: MonadIO m => AsyncVar a -> SomeException -> m ()
failAsyncVar_ var = void . failAsyncVar var
putAsyncVarEither_ :: MonadIO m => AsyncVar a -> Either SomeException a -> m ()
putAsyncVarEither_ var = void . putAsyncVarEither var
putAsyncVarEitherSTM_ :: AsyncVar a -> Either SomeException a -> STM ()
putAsyncVarEitherSTM_ var = void . putAsyncVarEitherSTM var
......@@ -6,11 +6,6 @@ module Quasar.Core (
runAsyncIO,
awaitResult,
-- * AsyncVar
AsyncVar,
newAsyncVar,
putAsyncVar,
-- * Cancellation
withCancellationToken,
) where
......@@ -136,52 +131,6 @@ awaitResult = (await =<<)
-- asyncThread :: m r -> AsyncIO r
-- * Async helpers
-- ** AsyncVar
-- | The default implementation for an `Awaitable` that can be fulfilled later.
newtype AsyncVar r = AsyncVar (TMVar (Either SomeException r))
instance IsAwaitable r (AsyncVar r) where
peekSTM (AsyncVar var) = tryReadTMVar var
tryPutAsyncVarEitherSTM :: AsyncVar a -> Either SomeException a -> STM Bool
tryPutAsyncVarEitherSTM (AsyncVar var) = tryPutTMVar var
tryPutAsyncVarEither :: forall a m. MonadIO m => AsyncVar a -> Either SomeException a -> m Bool
tryPutAsyncVarEither var = liftIO . atomically . tryPutAsyncVarEitherSTM var
newAsyncVarSTM :: STM (AsyncVar r)
newAsyncVarSTM = AsyncVar <$> newEmptyTMVar
newAsyncVar :: MonadIO m => m (AsyncVar r)
newAsyncVar = liftIO $ AsyncVar <$> newEmptyTMVarIO
putAsyncVar :: MonadIO m => AsyncVar a -> a -> m ()
putAsyncVar var = putAsyncVarEither var . Right
tryPutAsyncVar :: MonadIO m => AsyncVar a -> a -> m Bool
tryPutAsyncVar var = tryPutAsyncVarEither var . Right
tryPutAsyncVar_ :: MonadIO m => AsyncVar a -> a -> m ()
tryPutAsyncVar_ var = void . tryPutAsyncVar var
failAsyncVar :: MonadIO m => AsyncVar a -> SomeException -> m Bool
failAsyncVar var = tryPutAsyncVarEither var . Left
failAsyncVar_ :: MonadIO m => AsyncVar a -> SomeException -> m ()
failAsyncVar_ var = void . failAsyncVar var
putAsyncVarEither :: MonadIO m => AsyncVar a -> Either SomeException a -> m ()
putAsyncVarEither avar value = liftIO $ do
success <- tryPutAsyncVarEither avar value
unless success $ fail "An AsyncVar can only be fulfilled once"
tryPutAsyncVarEither_ :: MonadIO m => AsyncVar a -> Either SomeException a -> m ()
tryPutAsyncVarEither_ var = void . tryPutAsyncVarEither var
-- * Awaiting multiple asyncs
......
......@@ -2,7 +2,7 @@ module Quasar.AsyncSpec (spec) where
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad (void, (<=<))
import Control.Monad (void)
import Control.Monad.IO.Class
import Prelude
import Test.Hspec
......@@ -22,7 +22,7 @@ spec = parallel $ do
it "accepts a value" $ do
avar <- newAsyncVar :: IO (AsyncVar ())
putAsyncVar avar ()
putAsyncVar_ avar ()
describe "AsyncIO" $ do
it "binds pure operations" $ do
......@@ -40,26 +40,26 @@ spec = parallel $ do
it "can fmap the result of an already finished async" $ do
avar <- newAsyncVar :: IO (AsyncVar ())
putAsyncVar avar ()
putAsyncVar_ avar ()
runAsyncIO (id <$> await avar)
it "can fmap the result of an async that is completed later" $ do
avar <- newAsyncVar :: IO (AsyncVar ())
void $ forkIO $ do
threadDelay 100000
putAsyncVar avar ()
putAsyncVar_ avar ()
runAsyncIO (id <$> await avar)
it "can bind the result of an already finished async" $ do
avar <- newAsyncVar :: IO (AsyncVar ())
putAsyncVar avar ()
putAsyncVar_ avar ()
runAsyncIO (await avar >>= pure)
it "can bind the result of an async that is completed later" $ do
avar <- newAsyncVar :: IO (AsyncVar ())
void $ forkIO $ do
threadDelay 100000
putAsyncVar avar ()
putAsyncVar_ avar ()
runAsyncIO (await avar >>= pure)
it "can terminate when encountering an asynchronous exception" $ do
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment