module Engine.DataRecycler where
import RIO
import Control.Concurrent.Chan.Unagi qualified as Unagi
data DataRecycler a = DataRecycler
{ forall a. DataRecycler a -> DumpResource a
drDump :: DumpResource a
, forall a. DataRecycler a -> WaitResource a
drWait :: WaitResource a
}
type DumpResource a = a -> IO ()
type WaitResource a = IO (Either (IO a) a)
new :: MonadIO m => m (DataRecycler a)
new :: forall (m :: * -> *) a. MonadIO m => m (DataRecycler a)
new = do
(InChan a
recycleWrite, OutChan a
recycleRead) <- IO (InChan a, OutChan a) -> m (InChan a, OutChan a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (InChan a, OutChan a)
forall a. IO (InChan a, OutChan a)
Unagi.newChan
DataRecycler a -> m (DataRecycler a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure DataRecycler :: forall a. DumpResource a -> WaitResource a -> DataRecycler a
DataRecycler
{ $sel:drDump:DataRecycler :: DumpResource a
drDump = InChan a -> DumpResource a
forall a. InChan a -> a -> IO ()
Unagi.writeChan InChan a
recycleWrite
, $sel:drWait:DataRecycler :: WaitResource a
drWait = do
(Element a
tryOp, IO a
blockOp) <- OutChan a -> IO (Element a, IO a)
forall a. OutChan a -> IO (Element a, IO a)
Unagi.tryReadChan OutChan a
recycleRead
Maybe a
res <- Element a -> IO (Maybe a)
forall a. Element a -> IO (Maybe a)
Unagi.tryRead Element a
tryOp
pure $ Either (IO a) a
-> (a -> Either (IO a) a) -> Maybe a -> Either (IO a) a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (IO a -> Either (IO a) a
forall a b. a -> Either a b
Left IO a
blockOp) a -> Either (IO a) a
forall a b. b -> Either a b
Right Maybe a
res
}