Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Q
quasar
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jens Nolte
quasar
Commits
00b2871d
Commit
00b2871d
authored
3 years ago
by
Legy (Beini)
Committed by
Jens Nolte
3 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Rework IsResourceManager class
Co-authored-by:
Jens Nolte
<
git@queezle.net
>
parent
6aeaac46
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/Quasar/ResourceManager.hs
+103
-57
103 additions, 57 deletions
src/Quasar/ResourceManager.hs
with
103 additions
and
57 deletions
src/Quasar/ResourceManager.hs
+
103
−
57
View file @
00b2871d
...
...
@@ -4,7 +4,6 @@ module Quasar.ResourceManager (
registerDisposable
,
registerDisposeAction
,
disposeEventually
,
withResourceManagerM
,
withSubResourceManagerM
,
onResourceManager
,
captureDisposable
,
...
...
@@ -13,12 +12,22 @@ module Quasar.ResourceManager (
-- ** ResourceManager
IsResourceManager
(
..
),
ResourceManager
,
withResourceManager
,
newResourceManager
,
newUnmanagedResourceManager
,
attachDisposable
,
attachDisposeAction
,
attachDisposeAction_
,
-- ** Initialization
withRootResourceManager
,
withRootResourceManagerM
,
-- ** Resource manager implementations
newUnmanagedRootResourceManager
,
--newUnmanagedDefaultResourceManager,
-- ** Deprecated
withResourceManager
,
withResourceManagerM
,
newUnmanagedResourceManager
,
)
where
...
...
@@ -34,7 +43,7 @@ import Data.Sequence qualified as Seq
import
Quasar.Awaitable
import
Quasar.Disposable
import
Quasar.Prelude
import
System.IO
(
hPutStrLn
,
stderr
)
import
System.IO
(
fixIO
,
hPutStrLn
,
stderr
)
...
...
@@ -76,22 +85,30 @@ entryIsEmpty :: ResourceManagerEntry -> STM Bool
entryIsEmpty
(
ResourceManagerEntry
var
)
=
isEmptyTMVar
var
class
IsResourceManager
a
where
class
IsDisposable
a
=>
IsResourceManager
a
where
toResourceManager
::
a
->
ResourceManager
toResourceManager
=
ResourceManager
-- TODO move to class
--attachDisposable :: (IsDisposable b, MonadIO m) => a -> b -> m ()
-- | Attaches an `Disposable` to a ResourceManager. It will automatically be disposed when the resource manager is disposed.
attachDisposable
::
(
IsDisposable
b
,
MonadIO
m
)
=>
a
->
b
->
m
()
attachDisposable
self
=
attachDisposable
(
toResourceManager
self
)
--subResourceManager :: MonadResourceManager m => m (DisposableResourceThingy)
-- | Forward an exception that happened asynchronously.
throwToResourceManager
::
Exception
e
=>
a
->
e
->
IO
()
throwToResourceManager
=
throwToResourceManager
.
toResourceManager
{-# MINIMAL toResourceManager | (attachDisposable, throwToResourceManager) #-}
data
ResourceManager
=
forall
a
.
IsResourceManager
a
=>
ResourceManager
a
instance
IsResourceManager
ResourceManager
where
toResourceManager
=
id
-- TODO delegate to parent
throwToResourceManager
_
ex
=
hPutStrLn
stderr
$
displayException
ex
attachDisposable
(
ResourceManager
x
)
=
attachDisposable
x
throwToResourceManager
(
ResourceManager
x
)
=
throwToResourceManager
x
instance
IsDisposable
ResourceManager
where
toDisposable
(
ResourceManager
x
)
=
toDisposable
x
class
(
MonadAwait
m
,
MonadMask
m
,
MonadIO
m
,
MonadFix
m
)
=>
MonadResourceManager
m
where
-- | Get the underlying resource manager.
...
...
@@ -153,16 +170,66 @@ captureDisposable action = do
data
ResourceManager
=
ResourceManager
{
-- * Resource manager implementations
data
RootResourceManager
=
RootResourceManager
ResourceManager
(
TMVar
SomeException
)
instance
IsResourceManager
RootResourceManager
where
attachDisposable
(
RootResourceManager
child
_
)
disposable
=
attachDisposable
child
disposable
throwToResourceManager
(
RootResourceManager
child
storedException
)
ex
=
do
liftIO
$
atomically
$
void
$
tryPutTMVar
storedException
(
toException
ex
)
-- TODO fix log merging bug
hPutStrLn
stderr
$
displayException
ex
void
$
dispose
child
instance
IsDisposable
RootResourceManager
where
dispose
(
RootResourceManager
child
_
)
=
dispose
child
isDisposed
(
RootResourceManager
child
_
)
=
isDisposed
child
withRootResourceManager
::
(
MonadAwait
m
,
MonadMask
m
,
MonadIO
m
)
=>
(
ResourceManager
->
m
a
)
->
m
a
-- TODO abort thread on resource manager exception (that behavior should also be generalized)
withRootResourceManager
=
bracket
newUnmanagedRootResourceManager
(
await
<=<
liftIO
.
dispose
)
withRootResourceManagerM
::
(
MonadAwait
m
,
MonadMask
m
,
MonadIO
m
)
=>
ReaderT
ResourceManager
m
a
->
m
a
withRootResourceManagerM
action
=
withResourceManager
(`
onResourceManager
`
action
)
newUnmanagedRootResourceManager
::
MonadIO
m
=>
m
ResourceManager
newUnmanagedRootResourceManager
=
liftIO
$
fixIO
\
self
->
do
var
<-
liftIO
newEmptyTMVarIO
childResourceManager
<-
newUnmanagedDefaultResourceManager
self
pure
$
toResourceManager
(
RootResourceManager
childResourceManager
var
)
data
DefaultResourceManager
=
DefaultResourceManager
{
parentResourceManager
::
ResourceManager
,
disposingVar
::
TVar
Bool
,
disposedVar
::
TVar
Bool
,
exceptionVar
::
TMVar
SomeException
,
entriesVar
::
TVar
(
Seq
ResourceManagerEntry
)
}
instance
IsDisposable
ResourceManager
where
instance
IsResourceManager
DefaultResourceManager
where
throwToResourceManager
DefaultResourceManager
{
parentResourceManager
}
=
throwToResourceManager
parentResourceManager
attachDisposable
resourceManager
disposable
=
liftIO
$
mask
\
unmask
->
do
entry
<-
newEntry
disposable
join
$
atomically
do
disposed
<-
readTVar
(
disposedVar
resourceManager
)
when
disposed
$
throwM
(
userError
"Cannot attach a disposable to a disposed resource manager"
)
modifyTVar
(
entriesVar
resourceManager
)
(
|>
entry
)
disposing
<-
readTVar
(
disposingVar
resourceManager
)
pure
do
-- IO that is run after the STM transaction is completed
when
disposing
$
unmask
(
void
(
dispose
disposable
))
`
catchAll
`
throwToResourceManager
resourceManager
instance
IsDisposable
DefaultResourceManager
where
dispose
resourceManager
=
liftIO
$
mask
\
unmask
->
unmask
dispose'
`
catchAll
`
\
ex
->
setException
resourceManager
ex
>>
throwIO
ex
unmask
dispose'
`
catchAll
`
\
ex
->
pure
()
<$
throwToResourceManager
resourceManager
ex
where
dispose'
::
IO
(
Awaitable
()
)
dispose'
=
do
...
...
@@ -177,44 +244,50 @@ instance IsDisposable ResourceManager where
isDisposed
resourceManager
=
unsafeAwaitSTM
do
(
throwM
=<<
readTMVar
(
exceptionVar
resourceManager
))
`
orElse
`
((
\
disposed
->
unless
disposed
retry
)
=<<
readTVar
(
disposedVar
resourceManager
))
disposed
<-
readTVar
(
disposedVar
resourceManager
)
unless
disposed
retry
{-# DEPRECATED withResourceManager "Use withRootResourceManager insted" #-}
withResourceManager
::
(
MonadAwait
m
,
MonadMask
m
,
MonadIO
m
)
=>
(
ResourceManager
->
m
a
)
->
m
a
withResourceManager
=
bracket
newUnmanagedResourceManager
(
await
<=<
liftIO
.
dispose
)
withResourceManager
=
withRootResourceManager
withResourceManagerM
::
(
MonadAwait
m
,
MonadMask
m
,
MonadIO
m
)
=>
(
ReaderT
ResourceManager
m
a
)
->
m
a
withResourceManagerM
action
=
withResourceManager
\
resourceManager
->
onResourceManager
resourceManager
action
{-# DEPRECATED withResourceManagerM "Use withRootResourceManagerM insted" #-}
withResourceManagerM
::
(
MonadAwait
m
,
MonadMask
m
,
MonadIO
m
)
=>
ReaderT
ResourceManager
m
a
->
m
a
withResourceManagerM
=
withResourceManagerM
{-# DEPRECATED newUnmanagedResourceManager "Use newUnmanagedRootResourceManager insted" #-}
newUnmanagedResourceManager
::
MonadIO
m
=>
m
ResourceManager
newUnmanagedResourceManager
=
newUnmanagedRootResourceManager
newResourceManager
::
MonadResourceManager
m
=>
m
ResourceManager
newResourceManager
=
mask_
do
resourceManager
<-
newUnmanagedResourceManager
parent
<-
askResourceManager
-- TODO: return efficent resource manager
resourceManager
<-
newUnmanagedDefaultResourceManager
parent
registerDisposable
resourceManager
pure
resourceManager
newUnmanagedResourceManager
::
MonadIO
m
=>
m
ResourceManager
newUnmanagedResourceManager
=
liftIO
do
newUnmanaged
Default
ResourceManager
::
MonadIO
m
=>
ResourceManager
->
m
ResourceManager
newUnmanaged
DefaultResourceManager
parent
ResourceManager
=
liftIO
do
disposingVar
<-
newTVarIO
False
disposedVar
<-
newTVarIO
False
exceptionVar
<-
newEmptyTMVarIO
entriesVar
<-
newTVarIO
Empty
let
resourceManager
=
ResourceManager
{
let
resourceManager
=
DefaultResourceManager
{
parentResourceManager
,
disposingVar
,
disposedVar
,
exceptionVar
,
entriesVar
}
void
$
mask_
$
forkIOWithUnmask
\
unmask
->
unmask
(
collect
Garbage
resourceManager
)
`
catchAll
`
\
ex
->
setException
resourceManager
ex
unmask
(
free
Garbage
resourceManager
)
`
catchAll
`
throwToResourceManager
resourceManager
pure
resourceManager
pure
$
toResourceManager
resourceManager
collect
Garbage
::
ResourceManager
->
IO
()
collect
Garbage
resourceManager
=
go
free
Garbage
::
Default
ResourceManager
->
IO
()
free
Garbage
resourceManager
=
go
where
go
::
IO
()
go
=
do
...
...
@@ -257,33 +330,6 @@ collectGarbage resourceManager = go
entriesVar'
=
entriesVar
resourceManager
setException
::
ResourceManager
->
SomeException
->
IO
()
setException
resourceManager
ex
=
-- TODO re-throw exception unchanged or wrap it?
atomically
$
void
$
tryPutTMVar
(
exceptionVar
resourceManager
)
ex
-- | Attaches an `Disposable` to a ResourceManager. It will automatically be disposed when the resource manager is disposed.
attachDisposable
::
(
IsDisposable
a
,
MonadIO
m
)
=>
ResourceManager
->
a
->
m
()
attachDisposable
resourceManager
disposable
=
liftIO
$
mask
\
unmask
->
do
entry
<-
newEntry
disposable
join
$
atomically
do
mapM_
throwM
=<<
tryReadTMVar
(
exceptionVar
resourceManager
)
disposed
<-
readTVar
(
disposedVar
resourceManager
)
when
disposed
$
throwM
(
userError
"Cannot attach a disposable to a disposed resource manager"
)
modifyTVar
(
entriesVar
resourceManager
)
(
|>
entry
)
disposing
<-
readTVar
(
disposingVar
resourceManager
)
pure
do
-- IO that is run after the STM transaction is completed
when
disposing
$
void
$
unmask
(
dispose
disposable
)
`
catchAll
`
\
ex
->
setException
resourceManager
ex
>>
throwIO
ex
-- | Creates an `Disposable` that is bound to a ResourceManager. It will automatically be disposed when the resource manager is disposed.
attachDisposeAction
::
MonadIO
m
=>
ResourceManager
->
IO
(
Awaitable
()
)
->
m
Disposable
attachDisposeAction
resourceManager
action
=
liftIO
$
mask_
$
do
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment