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

Simplify RootResourceManager

parent 7b605952
No related branches found
No related tags found
No related merge requests found
Pipeline #2510 passed
...@@ -244,64 +244,55 @@ instance Exception CombinedException where ...@@ -244,64 +244,55 @@ instance Exception CombinedException where
exceptionMessages = (displayException <$> toList exceptions) exceptionMessages = (displayException <$> toList exceptions)
data RootResourceManagerState
= RootResourceManagerNormal
| RootResourceManagerDisposing
| RootResourceManagerDisposed
deriving stock Eq
data RootResourceManager data RootResourceManager
= RootResourceManager = RootResourceManager ResourceManager (TVar Bool) (TVar (Maybe (Seq SomeException))) (Awaitable ())
ResourceManager
(TVar RootResourceManagerState)
(TVar (Seq SomeException))
(Awaitable ())
instance IsResourceManager RootResourceManager where instance IsResourceManager RootResourceManager where
attachDisposable (RootResourceManager child _ _ _) disposable = attachDisposable child disposable attachDisposable (RootResourceManager child _ _ _) disposable = attachDisposable child disposable
throwToResourceManager (RootResourceManager _ stateVar exceptionsVar _) ex = do throwToResourceManager (RootResourceManager _ disposingVar exceptionsVar _) ex = do
-- TODO only log exceptions when disposing does not finish in time -- TODO only log exceptions after a timeout
traceIO $ "Exception thrown to root resource manager: " <> displayException ex traceIO $ "Exception thrown to root resource manager: " <> displayException ex
disposed <- liftIO $ atomically do liftIO $ join $ atomically do
state <- readTVar stateVar stateTVar exceptionsVar \case
-- Start disposing Just exceptions -> (pure (), Just (exceptions |> toException ex))
when (state == RootResourceManagerNormal) $ writeTVar stateVar RootResourceManagerDisposing Nothing -> (fail @IO "Could not throw to resource manager: RootResourceManager is already disposed", Nothing)
let disposed = state == RootResourceManagerDisposed
unless disposed $ modifyTVar exceptionsVar (|> toException ex)
pure disposed
when disposed $ fail "Could not throw to resource manager: RootResourceManager is already disposed"
instance IsDisposable RootResourceManager where instance IsDisposable RootResourceManager where
dispose (RootResourceManager _ stateVar _ isDisposedAwaitable) = do dispose (RootResourceManager _ disposingVar _ isDisposedAwaitable) = liftIO do
liftIO $ atomically do isDisposedAwaitable <$ atomically do
state <- readTVar stateVar disposing <- readTVar disposingVar
-- Start disposing unless disposing $ writeTVar disposingVar True
when (state == RootResourceManagerNormal) $ writeTVar stateVar RootResourceManagerDisposing
pure isDisposedAwaitable
isDisposed (RootResourceManager _ _ _ isDisposedAwaitable) = isDisposedAwaitable isDisposed (RootResourceManager _ _ _ isDisposedAwaitable) = isDisposedAwaitable
newUnmanagedRootResourceManager :: MonadIO m => m ResourceManager newUnmanagedRootResourceManager :: MonadIO m => m ResourceManager
newUnmanagedRootResourceManager = liftIO $ toResourceManager <$> do newUnmanagedRootResourceManager = liftIO $ toResourceManager <$> do
stateVar <- newTVarIO RootResourceManagerNormal disposingVar <- newTVarIO False
exceptionsVar <- newTVarIO Empty exceptionsVar <- newTVarIO (Just Empty)
mfix \root -> do mfix \root -> do
isDisposedAwaitable <- toAwaitable <$> unmanagedFork (disposeThread root) isDisposedAwaitable <- toAwaitable <$> unmanagedFork (disposeThread root)
child <- newUnmanagedDefaultResourceManager (toResourceManager root) child <- newUnmanagedDefaultResourceManager (toResourceManager root)
pure $ RootResourceManager child stateVar exceptionsVar isDisposedAwaitable pure $ RootResourceManager child disposingVar exceptionsVar isDisposedAwaitable
where where
disposeThread :: RootResourceManager -> IO () disposeThread :: RootResourceManager -> IO ()
disposeThread (RootResourceManager child stateVar exceptionsVar _) = do disposeThread (RootResourceManager child disposingVar exceptionsVar _) = do
-- Wait until disposing
atomically do atomically do
state <- readTVar stateVar disposing <- readTVar disposingVar
when (state == RootResourceManagerNormal) retry hasExceptions <- (> 0) . Seq.length <$> (maybe impossibleCodePathM pure =<< readTVar exceptionsVar)
-- TODO start thread: wait for timeout, then report exceptions or report hang check $ disposing || hasExceptions
-- TODO start the thread that reports exceptions (or a potential hang) after a timeout
await =<< dispose child await =<< dispose child
atomically do
exceptions <- nonEmpty . toList <$> readTVar exceptionsVar mExceptions <- atomically do
mapM_ (throwM . CombinedException) exceptions -- The var is set to `Nothing` to signal that no more exceptions can be received
nonEmpty . toList <$> (maybe impossibleCodePathM pure =<< swapTVar exceptionsVar Nothing)
-- If there are any exceptions will be stored in the awaitable (isDisposedAwaitable) by throwing them here
mapM_ (throwM . CombinedException) mExceptions
withRootResourceManager :: (MonadAwait m, MonadMask m, MonadIO m) => ReaderT ResourceManager IO a -> m a withRootResourceManager :: (MonadAwait m, MonadMask m, MonadIO m) => ReaderT ResourceManager IO a -> m a
......
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