diff --git a/src/Quasar/Core.hs b/src/Quasar/Core.hs index 63006d12e90b1ab1321e12676a07068a5e49cbd6..2663c6c9a7835f8f92e66f721ef1ad4c8521725b 100644 --- a/src/Quasar/Core.hs +++ b/src/Quasar/Core.hs @@ -7,11 +7,13 @@ module Quasar.Core ( withDefaultResourceManager, withUnlimitedResourceManager, newResourceManager, - disposeResourceManager, + defaultResourceManagerConfiguration, + unlimitedResourceManagerConfiguration, -- * AsyncTask AsyncTask, cancelTask, + cancelTaskIO, toAsyncTask, successfulTask, @@ -30,6 +32,8 @@ module Quasar.Core ( noDisposable, disposeEventually, boundDisposable, + attachDisposeAction, + attachDisposeAction_, ) where import Control.Concurrent (ThreadId, forkIOWithUnmask, myThreadId) @@ -84,12 +88,14 @@ instance HasResourceManager AsyncIO where awaitResult :: IsAwaitable r a => AsyncIO a -> AsyncIO r awaitResult = (await =<<) --- TODO rename to ResourceManager data ResourceManager = ResourceManager { configuration :: ResourceManagerConfiguraiton, threads :: TVar (HashSet ThreadId) } +instance IsDisposable ResourceManager where + dispose x = pure $ pure () + -- | A task that is running asynchronously. It has a result and can fail. -- The result (or exception) can be aquired by using the `Awaitable` class (e.g. by calling `await` or `awaitIO`). @@ -100,6 +106,9 @@ newtype AsyncTask r = AsyncTask (Awaitable r) instance IsAwaitable r (AsyncTask r) where toAwaitable (AsyncTask awaitable) = awaitable +instance IsDisposable (AsyncTask r) where + dispose = undefined + instance Functor AsyncTask where fmap fn (AsyncTask x) = AsyncTask (fn <$> x) @@ -107,9 +116,11 @@ instance Applicative AsyncTask where pure = AsyncTask . pure liftA2 fn (AsyncTask fx) (AsyncTask fy) = AsyncTask $ liftA2 fn fx fy -cancelTask :: AsyncTask r -> IO () --- TODO resource management -cancelTask = const (pure ()) +cancelTask :: AsyncTask r -> IO (Awaitable ()) +cancelTask = dispose + +cancelTaskIO :: AsyncTask r -> IO () +cancelTaskIO = awaitIO <=< dispose -- | Creates an `AsyncTask` from an `Awaitable`. -- The resulting task only depends on an external resource, so disposing it has no effect. @@ -228,4 +239,12 @@ disposeEventually resourceManager disposable = liftIO $ do -- | Creates an `Disposable` that is bound to a ResourceManager. It will automatically be disposed when the resource manager is disposed. boundDisposable :: HasResourceManager m => IO (Awaitable ()) -> m Disposable -boundDisposable = undefined +boundDisposable action = do + resourceManager <- askResourceManager + attachDisposeAction resourceManager action + +attachDisposeAction :: MonadIO m => ResourceManager -> IO (Awaitable ()) -> m Disposable +attachDisposeAction = undefined + +attachDisposeAction_ :: MonadIO m => ResourceManager -> IO (Awaitable ()) -> m () +attachDisposeAction_ resourceManager action = void $ attachDisposeAction resourceManager action