urbit/pkg/hs/urbit-king/lib/Urbit/Vere/Behn.hs

84 lines
2.0 KiB
Haskell
Raw Normal View History

2020-01-23 07:16:09 +03:00
{-|
Behn: Timer Driver
-}
2019-08-01 03:27:13 +03:00
module Urbit.Vere.Behn (behn, DriverApi(..), behn') where
2019-08-01 03:27:13 +03:00
import Urbit.Arvo hiding (Behn)
import Urbit.Prelude
import Urbit.Vere.Pier.Types
2019-08-01 03:27:13 +03:00
import Urbit.King.App (HasPierEnv(..), HasKingId(..))
2020-05-13 22:35:57 +03:00
import Urbit.Time (Wen)
import Urbit.Timer (Timer)
2020-01-23 07:16:09 +03:00
import qualified Urbit.Time as Time
import qualified Urbit.Timer as Timer
2019-08-01 03:27:13 +03:00
-- Behn Stuff ------------------------------------------------------------------
behn' :: HasPierEnv e => RAcquire e DriverApi
behn' = do
ventQ <- newTQueueIO
bornM <- newEmptyTMVarIO
fectM <- newEmptyTMVarIO
env <- ask
let (bootEvs, start) = behn env (writeTQueue ventQ)
for_ bootEvs (atomically . writeTQueue ventQ)
diOnEffect <- liftAcquire start
let diEventSource = fmap RRWork <$> tryReadTQueue ventQ
let diBlockUntilBorn = readTMVar bornM
-- TODO Do this after successful born event.
atomically $ putTMVar bornM ()
pure (DriverApi {..})
bornEv :: KingId -> Ev
bornEv king = EvBlip $ BlipEvBehn $ BehnEvBorn (king, ()) ()
2019-08-01 03:27:13 +03:00
wakeEv :: Ev
wakeEv = EvBlip $ BlipEvBehn $ BehnEvWake () ()
sysTime = view Time.systemTime
bornFailed :: e -> WorkError -> IO ()
bornFailed env _ = runRIO env $ do
pure () -- TODO Ship is fucked. Kill it?
wakeErr :: WorkError -> IO ()
wakeErr _ = pure ()
behn
:: HasKingId e
=> e
-> (EvErr -> STM ())
-> ([EvErr], Acquire (BehnEf -> IO ()))
2020-05-13 22:35:57 +03:00
behn env enqueueEv =
2019-08-01 03:27:13 +03:00
(initialEvents, runBehn)
where
2020-05-13 22:35:57 +03:00
king = fromIntegral (env ^. kingIdL)
initialEvents = [EvErr (bornEv king) (bornFailed env)]
2019-08-01 03:27:13 +03:00
2020-06-07 02:34:27 +03:00
runBehn :: Acquire (BehnEf -> IO ())
2019-08-01 03:27:13 +03:00
runBehn = do
tim <- mkAcquire Timer.init Timer.stop
2020-06-07 02:34:27 +03:00
pure (runRIO env . handleEf tim)
2019-08-01 03:27:13 +03:00
2019-08-29 03:26:59 +03:00
handleEf :: Timer -> BehnEf -> RIO e ()
handleEf b = io . \case
2019-08-01 03:27:13 +03:00
BehnEfVoid v -> absurd v
BehnEfDoze (i, ()) mWen -> do
when (i == king) (doze b mWen)
2019-08-01 03:27:13 +03:00
doze :: Timer -> Maybe Wen -> IO ()
doze tim = \case
Nothing -> Timer.stop tim
Just t -> Timer.start tim (sysTime t) $ atomically (enqueueEv (EvErr wakeEv wakeErr))