From a8df4479e35b9337614359a5f91e1fae780adcc4 Mon Sep 17 00:00:00 2001 From: Jens Nolte <git@queezle.net> Date: Fri, 6 Aug 2021 16:12:38 +0200 Subject: [PATCH] Change dispose signature --- src/Quasar/Core.hs | 59 ++++++++++++++++++++++++++++++++++++++-- src/Quasar/Disposable.hs | 44 +----------------------------- src/Quasar/Observable.hs | 6 ++-- 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/src/Quasar/Core.hs b/src/Quasar/Core.hs index 7477f44..07a3c2d 100644 --- a/src/Quasar/Core.hs +++ b/src/Quasar/Core.hs @@ -20,6 +20,14 @@ module Quasar.Core ( async, await, awaitResult, + + -- * Disposable + IsDisposable(..), + Disposable, + disposeIO, + mkDisposable, + synchronousDisposable, + noDisposable, ) where import Control.Concurrent (ThreadId, forkIOWithUnmask, myThreadId) @@ -103,8 +111,8 @@ cancelTask = const (pure ()) -- | Creates an `AsyncTask` from an `Awaitable`. -- The resulting task only depends on an external resource, so disposing it has no effect. -toAsyncTask :: Awaitable r -> AsyncTask r -toAsyncTask = AsyncTask +toAsyncTask :: IsAwaitable r a => a -> AsyncTask r +toAsyncTask = AsyncTask . toAwaitable successfulTask :: r -> AsyncTask r successfulTask = AsyncTask . successfulAwaitable @@ -157,3 +165,50 @@ newResourceManager configuration = do disposeResourceManager :: ResourceManager -> IO () -- TODO resource management disposeResourceManager = const (pure ()) + + + +-- * Disposable + +class IsDisposable a where + -- TODO document laws: must not throw exceptions, is idempotent + + -- | Dispose a resource. + dispose :: a -> IO (Awaitable ()) + dispose = dispose . toDisposable + + toDisposable :: a -> Disposable + toDisposable = mkDisposable . dispose + + {-# MINIMAL toDisposable | dispose #-} + +-- | Dispose a resource in the IO monad. +disposeIO :: IsDisposable a => a -> IO () +disposeIO = awaitIO <=< dispose + +instance IsDisposable a => IsDisposable (Maybe a) where + dispose = maybe (pure (pure ())) dispose + + +newtype Disposable = Disposable (IO (Awaitable ())) + +instance IsDisposable Disposable where + dispose (Disposable fn) = fn + toDisposable = id + +instance Semigroup Disposable where + x <> y = mkDisposable $ liftA2 (<>) (dispose x) (dispose y) + +instance Monoid Disposable where + mempty = mkDisposable $ pure $ pure () + mconcat disposables = mkDisposable $ mconcat <$> traverse dispose disposables + + +mkDisposable :: IO (Awaitable ()) -> Disposable +mkDisposable = Disposable + +synchronousDisposable :: IO () -> Disposable +synchronousDisposable = mkDisposable . fmap pure . liftIO + +noDisposable :: Disposable +noDisposable = mempty diff --git a/src/Quasar/Disposable.hs b/src/Quasar/Disposable.hs index 3e59d75..73f3b9a 100644 --- a/src/Quasar/Disposable.hs +++ b/src/Quasar/Disposable.hs @@ -1,53 +1,11 @@ module Quasar.Disposable ( IsDisposable(..), Disposable, + disposeIO, mkDisposable, synchronousDisposable, noDisposable, ) where import Quasar.Core -import Quasar.Prelude --- * Disposable - -class IsDisposable a where - -- TODO document laws: must not throw exceptions, is idempotent - - -- | Dispose a resource. - dispose :: a -> AsyncIO () - - -- | Dispose a resource in the IO monad. - disposeIO :: a -> IO () - disposeIO = withDefaultResourceManager . dispose - - toDisposable :: a -> Disposable - toDisposable = mkDisposable . dispose - -instance IsDisposable a => IsDisposable (Maybe a) where - dispose = mapM_ dispose - disposeIO = mapM_ disposeIO - - -newtype Disposable = Disposable (AsyncIO ()) - -instance IsDisposable Disposable where - dispose (Disposable fn) = fn - toDisposable = id - -instance Semigroup Disposable where - x <> y = mkDisposable $ liftA2 (<>) (dispose x) (dispose y) - -instance Monoid Disposable where - mempty = mkDisposable $ pure () - mconcat disposables = mkDisposable $ traverse_ dispose disposables - - -mkDisposable :: AsyncIO () -> Disposable -mkDisposable = Disposable - -synchronousDisposable :: IO () -> Disposable -synchronousDisposable = mkDisposable . liftIO - -noDisposable :: Disposable -noDisposable = mempty diff --git a/src/Quasar/Observable.hs b/src/Quasar/Observable.hs index b14c79d..dbf3902 100644 --- a/src/Quasar/Observable.hs +++ b/src/Quasar/Observable.hs @@ -188,8 +188,10 @@ instance forall v o i. (IsObservable i o, IsObservable v i) => IsObservable v (J innerDisposableMVar <- newMVar Nothing outerDisposable <- observe outer (outerCallback innerDisposableMVar) pure $ mkDisposable $ do - dispose outerDisposable - mapM_ dispose =<< liftIO (readMVar innerDisposableMVar) + -- TODO use `disposeEventually` to immediately deregister handler (ignoring messages from the old callback after that) + undefined + --dispose outerDisposable + --mapM_ dispose =<< liftIO (readMVar innerDisposableMVar) where outerCallback :: MVar (Maybe Disposable) -> ObservableMessage i -> IO () outerCallback innerDisposableMVar message = do -- GitLab