2012-03-26 20 views
1

在捕捉源Snap.Internal.Http.Server.TimeoutManagerTimeoutManager使用tryPutMVar把什麼

------------------------------------------------------------------------------ 
-- | Register a new connection with the TimeoutManager. 
register :: IO()    --^action to run when the timeout deadline is 
           -- exceeded. 
     -> TimeoutManager  --^manager to register with. 
     -> IO TimeoutHandle 
register killAction tm = do 
    now <- getTime 
    let !state = Deadline $ now + toEnum defaultTimeout 
    stateRef <- newIORef state 

    let !h = TimeoutHandle killAction stateRef getTime 
    atomicModifyIORef connections $ \x -> (h:x,()) 

    inact <- readIORef inactivity 
    when inact $ do 
     -- wake up manager thread 
     writeIORef inactivity False 
     _ <- tryPutMVar morePlease() 
     return() 
    return h 

    where 
    getTime  = _getTime tm 
    inactivity  = _inactivity tm 
    morePlease  = _morePlease tm 
    connections = _connections tm 
    defaultTimeout = _defaultTimeout tm 

爲什麼有_morePlease場?
_ <- tryPutMVar morePlease()是做什麼用的?

+0

在irC#haskell中,shachaf和edwardk說'MVar()'通常用於阻止目的 – wenlong 2012-03-26 10:22:36

回答

1
managerThread :: TimeoutManager -> IO() 
managerThread tm = loop `finally` (readIORef connections >>= destroyAll) 
    where 
    -------------------------------------------------------------------------- 
    connections = _connections tm 
    getTime  = _getTime tm 
    inactivity = _inactivity tm 
    morePlease = _morePlease tm 
    waitABit = threadDelay 5000000 

    -------------------------------------------------------------------------- 
    loop = do 
     waitABit 
     handles <- atomicModifyIORef connections (\x -> ([],x)) 

     if null handles 
      then do 
      -- we're inactive, go to sleep until we get new threads 
      writeIORef inactivity True 
      takeMVar morePlease 
      else do 
      now <- getTime 
      dlist <- processHandles now handles id 
      atomicModifyIORef connections (\x -> (dlist x,())) 

     loop 

    -------------------------------------------------------------------------- 
    processHandles !now handles initDlist = go handles initDlist 
     where 
     go [] !dlist = return dlist 

     go (x:xs) !dlist = do 
      state <- readIORef $ _state x 
      !dlist' <- case state of 
         Canceled -> return dlist 
         Deadline t -> if t <= now 
             then do 
              _killAction x 
              return dlist 
             else return (dlist . (x:)) 
      go xs dlist' 

    -------------------------------------------------------------------------- 
    destroyAll = mapM_ diediedie 

    -------------------------------------------------------------------------- 
    diediedie x = do 
     state <- readIORef $ _state x 
     case state of 
      Canceled -> return() 
      _  -> _killAction x 

如果不存在要處理的把手,managerThread將由takeMVar morePlease阻斷。 _ <- tryPutMVar morePlease()叫醒他。