dunai-0.1.1.0: src/Data/MonadicStreamFunction/ReactHandle.hs
-- | ReactHandle
-- Sometimes it is beneficial to give control to an external main loop,
-- for example OpenGL or a hardware-clocked audio server like JACK.
-- This module makes Dunai compatible with external main loops.
module Data.MonadicStreamFunction.ReactHandle where
-- External
import Control.Monad.IO.Class
import Data.IORef
-- Internal
import Data.MonadicStreamFunction
-- | A storage for the current state of an MSF
type ReactHandle m = IORef (MSF m () ())
-- | Needs to be called before the external main loop is dispatched
reactInit :: MonadIO m => MSF m () () -> m (ReactHandle m)
reactInit = liftIO . newIORef
-- | The callback that needs to be called by the main loop at every cycle
react :: MonadIO m => ReactHandle m -> m ()
react handle = do
msf <- liftIO $ readIORef handle
(_, msf') <- unMSF msf ()
liftIO $ writeIORef handle msf'
-- | Creates two ends of a synchronisation wormhole
-- Often, the external framework may have several parallel loops,
-- for example, OpenGL with a display callback, an idle callback and a keyboard callback.
-- In such cases, one would like to let the different parts communicate.
-- This is done through a wormhole, which is a shared mutable variable
-- that can be written from one part and read from the other.
createWormhole :: MonadIO m => a -> m (MSF m a (), MSF m () a)
createWormhole a = liftIO $ do
ref <- newIORef a
return (arrM $ liftIO . writeIORef ref, arrM_ $ liftIO $ readIORef ref)