packages feed

agda-language-server-0.0.3.0: src/Server/CommandController.hs

module Server.CommandController
  ( CommandController,
    new,
    take,
    release,
    put,
  )
where

import Agda.Interaction.Base (IOTCM)
import Control.Concurrent
import Control.Concurrent.SizedChan
import Control.Monad (forM_)
import Prelude hiding (take)

data CommandController
  = CommandController
      (SizedChan IOTCM)
      -- ^ Unbounded Command queue
      (MVar IOTCM)
      -- ^ MVar for the Command consumer

new :: IO CommandController
new = CommandController <$> newSizedChan <*> newEmptyMVar

-- | Blocks if the front is empty
take :: CommandController -> IO IOTCM
take (CommandController _ front) = takeMVar front

-- | Move the payload from the queue to the front
-- Does not block if the front or the queue is empty
release :: CommandController -> IO ()
release (CommandController queue front) = do
  result <- tryReadSizedChan queue
  forM_ result (tryPutMVar front)

-- | Does not block
-- Move the payload to the front if the front is empty
put :: CommandController -> IOTCM -> IO ()
put (CommandController queue front) command = do
  isEmpty <- isEmptyMVar front
  if isEmpty
    then putMVar front command
    else writeSizedChan queue command