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

Remove CancellationToken

parent 1d10e90e
No related branches found
No related tags found
No related merge requests found
...@@ -5,9 +5,6 @@ module Quasar.Core ( ...@@ -5,9 +5,6 @@ module Quasar.Core (
await, await,
runAsyncIO, runAsyncIO,
awaitResult, awaitResult,
-- * Cancellation
withCancellationToken,
) where ) where
import Control.Concurrent (forkIOWithUnmask) import Control.Concurrent (forkIOWithUnmask)
...@@ -165,45 +162,3 @@ peekEitherSTM x y = ...@@ -165,45 +162,3 @@ peekEitherSTM x y =
Just (Left ex) -> pure (Just (Left ex)) Just (Left ex) -> pure (Just (Left ex))
Just (Right r) -> pure (Just (Right (Right r))) Just (Right r) -> pure (Just (Right (Right r)))
Nothing -> pure Nothing Nothing -> pure Nothing
-- * Cancellation
newtype CancellationToken = CancellationToken (AsyncVar Void)
instance IsAwaitable Void CancellationToken where
toAwaitable (CancellationToken var) = toAwaitable var
newCancellationToken :: IO CancellationToken
newCancellationToken = CancellationToken <$> newAsyncVar
cancel :: Exception e => CancellationToken -> e -> IO ()
cancel (CancellationToken var) = failAsyncVar_ var . toException
isCancellationRequested :: CancellationToken -> IO Bool
isCancellationRequested (CancellationToken var) = isJust <$> peekAwaitable var
cancellationState :: CancellationToken -> IO (Maybe SomeException)
cancellationState (CancellationToken var) = (either Just (const Nothing) =<<) <$> peekAwaitable var
throwIfCancellationRequested :: CancellationToken -> IO ()
throwIfCancellationRequested (CancellationToken var) =
peekAwaitable var >>= \case
Just (Left ex) -> throwIO ex
_ -> pure ()
awaitUnlessCancellationRequested :: IsAwaitable a b => CancellationToken -> b -> AsyncIO a
awaitUnlessCancellationRequested cancellationToken = fmap (either absurd id) . awaitEither cancellationToken . toAwaitable
withCancellationToken :: (CancellationToken -> IO a) -> IO a
withCancellationToken action = do
cancellationToken <- newCancellationToken
resultMVar :: MVar (Either SomeException a) <- newEmptyMVar
uninterruptibleMask $ \unmask -> do
void $ forkIOWithUnmask $ \threadUnmask -> do
putMVar resultMVar =<< try (threadUnmask (action cancellationToken))
-- TODO test if it is better to run readMVar recursively or to keep it uninterruptible
either throwIO pure =<< (unmask (readMVar resultMVar) `catchAll` (\ex -> cancel cancellationToken ex >> readMVar resultMVar))
...@@ -69,12 +69,3 @@ spec = parallel $ do ...@@ -69,12 +69,3 @@ spec = parallel $ do
-- Use bind to create an AsyncIOPlumbing, which is the interesting case that uses `uninterruptibleMask` when run -- Use bind to create an AsyncIOPlumbing, which is the interesting case that uses `uninterruptibleMask` when run
await never >>= pure await never >>= pure
result `shouldBe` Nothing result `shouldBe` Nothing
describe "CancellationToken" $ do
it "propagates outer exceptions to the cancellation token" $ do
result <- timeout 100000 $ withCancellationToken (runAsyncIO . await)
result `shouldBe` Nothing
it "can return a value after cancellation" $ do
result <- timeout 100000 $ withCancellationToken (fmap (either (const True) (const False)) . atomically . awaitSTM)
result `shouldBe` Just True
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