{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE QualifiedDo #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# OPTIONS_HADDOCK hide #-}
module System.IO.Resource.Linear.Internal where
import Control.Exception (finally, mask, onException)
import qualified Control.Functor.Linear as Control
import qualified Control.Monad as Ur (fmap)
import qualified Data.Functor.Linear as Data
import Data.IORef (IORef)
import qualified Data.IORef as System
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IntMap
import Data.Monoid (Ap (..))
import Data.Text (Text)
import qualified Data.Text.IO as Text
import Prelude.Linear
( Additive ((+)),
Bool (..),
Char,
FilePath,
Int,
Integer,
Monoid,
Movable (..),
Semigroup,
Ur (..),
fst,
snd,
($),
)
import qualified System.IO as System
import qualified System.IO.Linear as Linear
import qualified Prelude
newtype ReleaseMap = ReleaseMap (IntMap (Linear.IO ()))
newtype RIO a = RIO (IORef ReleaseMap -> Linear.IO a)
deriving (forall a b. (a %1 -> b) -> RIO a %1 -> RIO b
forall (f :: * -> *).
(forall a b. (a %1 -> b) -> f a %1 -> f b) -> Functor f
fmap :: forall a b. (a %1 -> b) -> RIO a %1 -> RIO b
$cfmap :: forall a b. (a %1 -> b) -> RIO a %1 -> RIO b
Data.Functor, Functor RIO
forall a. a -> RIO a
forall a b. RIO (a %1 -> b) %1 -> RIO a %1 -> RIO b
forall a b c. (a %1 -> b %1 -> c) -> RIO a %1 -> RIO b %1 -> RIO c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a %1 -> b) %1 -> f a %1 -> f b)
-> (forall a b c. (a %1 -> b %1 -> c) -> f a %1 -> f b %1 -> f c)
-> Applicative f
liftA2 :: forall a b c. (a %1 -> b %1 -> c) -> RIO a %1 -> RIO b %1 -> RIO c
$cliftA2 :: forall a b c. (a %1 -> b %1 -> c) -> RIO a %1 -> RIO b %1 -> RIO c
<*> :: forall a b. RIO (a %1 -> b) %1 -> RIO a %1 -> RIO b
$c<*> :: forall a b. RIO (a %1 -> b) %1 -> RIO a %1 -> RIO b
pure :: forall a. a -> RIO a
$cpure :: forall a. a -> RIO a
Data.Applicative) via (Control.Data RIO)
deriving (RIO a %1 -> RIO a %1 -> RIO a
forall a. Semigroup a => RIO a %1 -> RIO a %1 -> RIO a
forall a. (a %1 -> a %1 -> a) -> Semigroup a
<> :: RIO a %1 -> RIO a %1 -> RIO a
$c<> :: forall a. Semigroup a => RIO a %1 -> RIO a %1 -> RIO a
Semigroup, RIO a
forall a. Semigroup a -> a -> Monoid a
forall {a}. Monoid a => Semigroup (RIO a)
forall a. Monoid a => RIO a
mempty :: RIO a
$cmempty :: forall a. Monoid a => RIO a
Monoid) via (Ap RIO a)
unRIO :: RIO a %1 -> IORef ReleaseMap -> Linear.IO a
unRIO :: forall a. RIO a %1 -> IORef ReleaseMap -> IO a
unRIO (RIO IORef ReleaseMap -> IO a
action) = IORef ReleaseMap -> IO a
action
run :: RIO (Ur a) -> System.IO a
run :: forall a. RIO (Ur a) -> IO a
run (RIO IORef ReleaseMap -> IO (Ur a)
action) = do
IORef ReleaseMap
rrm <- forall a. a -> IO (IORef a)
System.newIORef (IntMap (IO ()) -> ReleaseMap
ReleaseMap forall a. IntMap a
IntMap.empty)
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask
( \forall a. IO a -> IO a
restore ->
forall a b. IO a -> IO b -> IO a
onException
(forall a. IO a -> IO a
restore (forall a. IO (Ur a) -> IO a
Linear.withLinearIO (IORef ReleaseMap -> IO (Ur a)
action IORef ReleaseMap
rrm)))
( do
ReleaseMap IntMap (IO ())
releaseMap <- forall a. IORef a -> IO a
System.readIORef IORef ReleaseMap
rrm
[IO ()] -> IO ()
safeRelease forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Ur.fmap forall a b. (a, b) -> b
snd forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a. IntMap a -> [(Key, a)]
IntMap.toList IntMap (IO ())
releaseMap
)
)
where
safeRelease :: [Linear.IO ()] -> System.IO ()
safeRelease :: [IO ()] -> IO ()
safeRelease [] = forall (m :: * -> *) a. Monad m => a -> m a
Prelude.return ()
safeRelease (IO ()
finalizer : [IO ()]
fs) =
forall a. IO (Ur a) -> IO a
Linear.withLinearIO (forall a. Movable a => IO a %1 -> IO (Ur a)
moveLinearIO IO ()
finalizer)
forall a b. IO a -> IO b -> IO a
`finally` [IO ()] -> IO ()
safeRelease [IO ()]
fs
moveLinearIO :: (Movable a) => Linear.IO a %1 -> Linear.IO (Ur a)
moveLinearIO :: forall a. Movable a => IO a %1 -> IO (Ur a)
moveLinearIO IO a
action' = Control.do
a
result <- IO a
action'
forall (m :: * -> *) a. Monad m => a %1 -> m a
Control.return forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a. Movable a => a %1 -> Ur a
move a
result
unsafeFromSystemIO :: System.IO a %1 -> RIO a
unsafeFromSystemIO :: forall a. IO a %1 -> RIO a
unsafeFromSystemIO IO a
action = forall a. (IORef ReleaseMap -> IO a) -> RIO a
RIO (\IORef ReleaseMap
_ -> forall a. IO a %1 -> IO a
Linear.fromSystemIO IO a
action)
instance Control.Functor RIO where
fmap :: forall a b. (a %1 -> b) %1 -> RIO a %1 -> RIO b
fmap a %1 -> b
f (RIO IORef ReleaseMap -> IO a
action) = forall a. (IORef ReleaseMap -> IO a) -> RIO a
RIO forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ \IORef ReleaseMap
releaseMap ->
forall (f :: * -> *) a b.
Functor f =>
(a %1 -> b) %1 -> f a %1 -> f b
Control.fmap a %1 -> b
f (IORef ReleaseMap -> IO a
action IORef ReleaseMap
releaseMap)
instance Control.Applicative RIO where
pure :: forall a. a %1 -> RIO a
pure a
a = forall a. (IORef ReleaseMap -> IO a) -> RIO a
RIO forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ \IORef ReleaseMap
_releaseMap -> forall (f :: * -> *) a. Applicative f => a %1 -> f a
Control.pure a
a
<*> :: forall a b. RIO (a %1 -> b) %1 -> RIO a %1 -> RIO b
(<*>) = forall (m :: * -> *) a b.
Monad m =>
m (a %1 -> b) %1 -> m a %1 -> m b
Control.ap
instance Control.Monad RIO where
RIO a
x >>= :: forall a b. RIO a %1 -> (a %1 -> RIO b) %1 -> RIO b
>>= a %1 -> RIO b
f = forall a. (IORef ReleaseMap -> IO a) -> RIO a
RIO forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ \IORef ReleaseMap
releaseMap -> Control.do
a
a <- forall a. RIO a %1 -> IORef ReleaseMap -> IO a
unRIO RIO a
x IORef ReleaseMap
releaseMap
forall a. RIO a %1 -> IORef ReleaseMap -> IO a
unRIO (a %1 -> RIO b
f a
a) IORef ReleaseMap
releaseMap
RIO ()
x >> :: forall a. RIO () %1 -> RIO a %1 -> RIO a
>> RIO a
y = forall a. (IORef ReleaseMap -> IO a) -> RIO a
RIO forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ \IORef ReleaseMap
releaseMap -> Control.do
forall a. RIO a %1 -> IORef ReleaseMap -> IO a
unRIO RIO ()
x IORef ReleaseMap
releaseMap
forall a. RIO a %1 -> IORef ReleaseMap -> IO a
unRIO RIO a
y IORef ReleaseMap
releaseMap
type Handle = Resource System.Handle
openFile :: FilePath -> System.IOMode -> RIO Handle
openFile :: FilePath -> IOMode -> RIO Handle
openFile FilePath
path IOMode
mode =
forall a. IO (Ur a) -> (a -> IO ()) -> RIO (Resource a)
unsafeAcquire
(forall a. IO a -> IO (Ur a)
Linear.fromSystemIOU forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ FilePath -> IOMode -> IO Handle
System.openFile FilePath
path IOMode
mode)
(\Handle
h -> forall a. IO a %1 -> IO a
Linear.fromSystemIO forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ Handle -> IO ()
System.hClose Handle
h)
openBinaryFile :: FilePath -> System.IOMode -> RIO Handle
openBinaryFile :: FilePath -> IOMode -> RIO Handle
openBinaryFile FilePath
path IOMode
mode =
forall a. IO (Ur a) -> (a -> IO ()) -> RIO (Resource a)
unsafeAcquire
(forall a. IO a -> IO (Ur a)
Linear.fromSystemIOU forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ FilePath -> IOMode -> IO Handle
System.openFile FilePath
path IOMode
mode)
(\Handle
h -> forall a. IO a %1 -> IO a
Linear.fromSystemIO forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ Handle -> IO ()
System.hClose Handle
h)
hClose :: Handle %1 -> RIO ()
hClose :: Handle %1 -> RIO ()
hClose = forall a. Resource a %1 -> RIO ()
release
hIsEOF :: Handle %1 -> RIO (Ur Bool, Handle)
hIsEOF :: Handle %1 -> RIO (Ur Bool, Handle)
hIsEOF = forall a b. (a -> IO b) -> Resource a %1 -> RIO (Ur b, Resource a)
unsafeFromSystemIOResource Handle -> IO Bool
System.hIsEOF
hGetChar :: Handle %1 -> RIO (Ur Char, Handle)
hGetChar :: Handle %1 -> RIO (Ur Char, Handle)
hGetChar = forall a b. (a -> IO b) -> Resource a %1 -> RIO (Ur b, Resource a)
unsafeFromSystemIOResource Handle -> IO Char
System.hGetChar
hPutChar :: Handle %1 -> Char -> RIO Handle
hPutChar :: Handle %1 -> Char -> RIO Handle
hPutChar Handle
h Char
c = forall a. (a -> IO ()) -> Resource a %1 -> RIO (Resource a)
unsafeFromSystemIOResource_ (\Handle
h' -> Handle -> Char -> IO ()
System.hPutChar Handle
h' Char
c) Handle
h
hGetLine :: Handle %1 -> RIO (Ur Text, Handle)
hGetLine :: Handle %1 -> RIO (Ur Text, Handle)
hGetLine = forall a b. (a -> IO b) -> Resource a %1 -> RIO (Ur b, Resource a)
unsafeFromSystemIOResource Handle -> IO Text
Text.hGetLine
hPutStr :: Handle %1 -> Text -> RIO Handle
hPutStr :: Handle %1 -> Text -> RIO Handle
hPutStr Handle
h Text
s = forall a. (a -> IO ()) -> Resource a %1 -> RIO (Resource a)
unsafeFromSystemIOResource_ (\Handle
h' -> Handle -> Text -> IO ()
Text.hPutStr Handle
h' Text
s) Handle
h
hPutStrLn :: Handle %1 -> Text -> RIO Handle
hPutStrLn :: Handle %1 -> Text -> RIO Handle
hPutStrLn Handle
h Text
s = forall a. (a -> IO ()) -> Resource a %1 -> RIO (Resource a)
unsafeFromSystemIOResource_ (\Handle
h' -> Handle -> Text -> IO ()
Text.hPutStrLn Handle
h' Text
s) Handle
h
hSeek :: Handle %1 -> System.SeekMode -> Integer -> RIO Handle
hSeek :: Handle %1 -> SeekMode -> Integer -> RIO Handle
hSeek Handle
h SeekMode
mode Integer
i = forall a. (a -> IO ()) -> Resource a %1 -> RIO (Resource a)
unsafeFromSystemIOResource_ (\Handle
h' -> Handle -> SeekMode -> Integer -> IO ()
System.hSeek Handle
h' SeekMode
mode Integer
i) Handle
h
hTell :: Handle %1 -> RIO (Ur Integer, Handle)
hTell :: Handle %1 -> RIO (Ur Integer, Handle)
hTell = forall a b. (a -> IO b) -> Resource a %1 -> RIO (Ur b, Resource a)
unsafeFromSystemIOResource Handle -> IO Integer
System.hTell
data Resource a where
UnsafeResource :: Int -> a -> Resource a
type UnsafeResource = Resource
{-# DEPRECATED UnsafeResource "UnsafeResource has been renamed to Resource" #-}
release :: Resource a %1 -> RIO ()
release :: forall a. Resource a %1 -> RIO ()
release (UnsafeResource Key
key a
_) = forall a. (IORef ReleaseMap -> IO a) -> RIO a
RIO (\IORef ReleaseMap
st -> forall a. IO a -> IO a
Linear.mask_ (Key -> IORef ReleaseMap -> IO ()
releaseWith Key
key IORef ReleaseMap
st))
where
releaseWith :: Key -> IORef ReleaseMap -> IO ()
releaseWith Key
key IORef ReleaseMap
rrm = Control.do
Ur (ReleaseMap IntMap (IO ())
releaseMap) <- forall a. IORef a -> IO (Ur a)
Linear.readIORef IORef ReleaseMap
rrm
() <- IntMap (IO ())
releaseMap forall a. IntMap a -> Key -> a
IntMap.! Key
key
forall a. IORef a -> a -> IO ()
Linear.writeIORef IORef ReleaseMap
rrm (IntMap (IO ()) -> ReleaseMap
ReleaseMap (forall a. Key -> IntMap a -> IntMap a
IntMap.delete Key
key IntMap (IO ())
releaseMap))
unsafeRelease :: Resource a %1 -> RIO ()
unsafeRelease :: forall a. Resource a %1 -> RIO ()
unsafeRelease = forall a. Resource a %1 -> RIO ()
release
{-# DEPRECATED unsafeRelease "unsafeRelease has been renamed to release" #-}
unsafeAcquire ::
Linear.IO (Ur a) ->
(a -> Linear.IO ()) ->
RIO (Resource a)
unsafeAcquire :: forall a. IO (Ur a) -> (a -> IO ()) -> RIO (Resource a)
unsafeAcquire IO (Ur a)
acquire a -> IO ()
release = forall a. (IORef ReleaseMap -> IO a) -> RIO a
RIO forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ \IORef ReleaseMap
rrm ->
forall a. IO a -> IO a
Linear.mask_
( Control.do
Ur a
resource <- IO (Ur a)
acquire
Ur (ReleaseMap IntMap (IO ())
releaseMap) <- forall a. IORef a -> IO (Ur a)
Linear.readIORef IORef ReleaseMap
rrm
() <-
forall a. IORef a -> a -> IO ()
Linear.writeIORef
IORef ReleaseMap
rrm
( IntMap (IO ()) -> ReleaseMap
ReleaseMap
(forall a. Key -> a -> IntMap a -> IntMap a
IntMap.insert (forall {b}. IntMap b -> Key
releaseKey IntMap (IO ())
releaseMap) (a -> IO ()
release a
resource) IntMap (IO ())
releaseMap)
)
forall (m :: * -> *) a. Monad m => a %1 -> m a
Control.return forall a b (p :: Multiplicity) (q :: Multiplicity).
(a %p -> b) %q -> a %p -> b
$ forall a. Key -> a -> Resource a
UnsafeResource (forall {b}. IntMap b -> Key
releaseKey IntMap (IO ())
releaseMap) a
resource
)
where
releaseKey :: IntMap b -> Key
releaseKey IntMap b
releaseMap =
case forall a. IntMap a -> Bool
IntMap.null IntMap b
releaseMap of
Bool
True -> Key
0
Bool
False -> forall a b. (a, b) -> a
fst (forall a. IntMap a -> (Key, a)
IntMap.findMax IntMap b
releaseMap) forall a. Additive a => a %1 -> a %1 -> a
+ Key
1
unsafeFromSystemIOResource ::
(a -> System.IO b) ->
(Resource a %1 -> RIO (Ur b, Resource a))
unsafeFromSystemIOResource :: forall a b. (a -> IO b) -> Resource a %1 -> RIO (Ur b, Resource a)
unsafeFromSystemIOResource a -> IO b
action (UnsafeResource Key
key a
resource) =
forall a. IO a %1 -> RIO a
unsafeFromSystemIO
( do
b
c <- a -> IO b
action a
resource
forall (m :: * -> *) a. Monad m => a -> m a
Prelude.return (forall a. a -> Ur a
Ur b
c, forall a. Key -> a -> Resource a
UnsafeResource Key
key a
resource)
)
unsafeFromSystemIOResource_ ::
(a -> System.IO ()) ->
(Resource a %1 -> RIO (Resource a))
unsafeFromSystemIOResource_ :: forall a. (a -> IO ()) -> Resource a %1 -> RIO (Resource a)
unsafeFromSystemIOResource_ a -> IO ()
action Resource a
resource = Control.do
(Ur ()
_, Resource a
resource) <- forall a b. (a -> IO b) -> Resource a %1 -> RIO (Ur b, Resource a)
unsafeFromSystemIOResource a -> IO ()
action Resource a
resource
forall (m :: * -> *) a. Monad m => a %1 -> m a
Control.return Resource a
resource