keid-core-0.1.0.0: src/Engine/Events/Sink.hs
module Engine.Events.Sink
( Sink(..)
, spawn
) where
import RIO
import Control.Concurrent.Chan.Unagi qualified as Unagi
import Control.Exception (AsyncException(ThreadKilled))
import UnliftIO.Concurrent (forkFinally, killThread)
import UnliftIO.Resource (ReleaseKey)
import UnliftIO.Resource qualified as Resource
import Engine.Types (StageRIO)
newtype Sink event st = Sink
{ signal :: event -> StageRIO st ()
}
spawn
:: (event -> StageRIO rs ())
-> StageRIO rs (ReleaseKey, Sink event rs)
spawn handleEvent = do
(eventsIn, eventsOut) <- liftIO Unagi.newChan
let sink = Sink \event -> liftIO (Unagi.writeChan eventsIn event)
let
handler = forever $
liftIO (Unagi.readChan eventsOut) >>= handleEvent
tid <- forkFinally handler
\case
Left exc ->
case fromException exc of
Just ThreadKilled ->
logDebug "Event thread killed"
_others ->
logError $ "Event thread crashed: " <> displayShow exc
Right () ->
logWarn "Event thread exited prematurely"
key <- Resource.register $ killThread tid
pure (key, sink)