mighttpd2-3.0.0: Program/Mighty/State.hs
module Program.Mighty.State (
-- * Types
Status(..)
, Stater
-- * Creating Stater
, initStater
-- * Accessing Stater
, getConnectionCounter
, getServerStatus
, isRetiring
-- * Modifying Stater
, increment
, decrement
, setMyWarpThreadId
, addAnotherWarpThreadId
, goRetiring
-- * Misc
, ifWarpThreadsAreActive
) where
import Control.Applicative
import Control.Concurrent
import Data.IORef
import Program.Mighty.IORef
----------------------------------------------------------------
-- | Server status
data Status = Serving | Retiring deriving (Eq, Show)
data Two a = Zero | One a | Two a a
data State = State {
connectionCounter :: !Int
, serverStatus :: !Status
, warpThreadId :: !(Two ThreadId)
}
initialState :: State
initialState = State 0 Serving Zero
----------------------------------------------------------------
-- | Reference to a server state.
newtype Stater = Stater (IORef State)
-- | Creating a new 'Stater'.
initStater :: IO Stater
initStater = Stater <$> newIORef initialState
----------------------------------------------------------------
getConnectionCounter :: Stater -> IO Int
getConnectionCounter (Stater sref) = connectionCounter <$> readIORef sref
increment :: Stater -> IO ()
increment (Stater sref) =
strictAtomicModifyIORef sref $ \st -> st {
connectionCounter = connectionCounter st + 1
}
decrement :: Stater -> IO ()
decrement (Stater sref) =
strictAtomicModifyIORef sref $ \st -> st {
connectionCounter = connectionCounter st - 1
}
----------------------------------------------------------------
getServerStatus :: Stater -> IO Status
getServerStatus (Stater sref) = serverStatus <$> readIORef sref
isRetiring :: Stater -> IO Bool
isRetiring stt = (== Retiring) <$> getServerStatus stt
-- | Setting status to 'Retiring'.
goRetiring :: Stater -> IO ()
goRetiring (Stater sref) =
strictAtomicModifyIORef sref $ \st -> st {
serverStatus = Retiring
, warpThreadId = Zero
}
----------------------------------------------------------------
getWarpThreadId :: Stater -> IO (Two ThreadId)
getWarpThreadId (Stater sref) = warpThreadId <$> readIORef sref
setWarpThreadId :: Stater -> Two ThreadId -> IO ()
setWarpThreadId (Stater sref) ttids =
strictAtomicModifyIORef sref $ \st -> st {
warpThreadId = ttids
}
setMyWarpThreadId :: Stater -> IO ()
setMyWarpThreadId stt = do
myid <- myThreadId
setWarpThreadId stt (One myid)
addAnotherWarpThreadId :: Stater -> ThreadId -> IO ()
addAnotherWarpThreadId stt aid = do
ttids <- getWarpThreadId stt
case ttids of
One tid -> setWarpThreadId stt (Two tid aid)
_ -> error "addAnotherWarpThreadId"
-- | If Warp threads are active, first terminate them and
-- run new 'IO'.
ifWarpThreadsAreActive :: Stater -> IO () -> IO ()
ifWarpThreadsAreActive stt act = do
ttids <- getWarpThreadId stt
case ttids of
Zero -> return ()
One tid -> do
killThread tid
act
Two tid1 tid2 -> do
killThread tid1
killThread tid2
act