@@ -23,12 +23,12 @@ module Network.Wai.Handler.Warp.FdCache (
2323 ) where
2424
2525import Control.Applicative ((<$>), (<*>))
26−import Control.Concurrent (forkIO, threadDelay)
27−import Control.Exception (bracket)
28−import Control.Monad (void)
26+import Control.Concurrent (threadDelay)
27+import Control.Exception (bracket, mask_)
2928import Data.Hashable (hash)
3029import Data.IORef (IORef, newIORef, readIORef, writeIORef, atomicModifyIORef)
3130import Network.Wai.Handler.Warp.MultiMap
31+import Network.Wai.Handler.Warp.Thread
3232import System.Posix.IO (openFd, OpenFileFlags(..), defaultFileFlags, OpenMode(ReadOnly), closeFd)
3333import System.Posix.Types (Fd)
3434
@@ -67,17 +67,17 @@ type Hash = Int
6767type FdCache = MMap Hash FdEntry
6868newtype MutableFdCache = MutableFdCache (IORef FdCache)
6969
70−newMutableFdCache :: IO MutableFdCache
71−newMutableFdCache = MutableFdCache <$> newIORef empty
72−
7370fdCache :: MutableFdCache -> IO FdCache
7471fdCache (MutableFdCache ref) = readIORef ref
7572
76−swapWithNew :: MutableFdCache -> IO FdCache
77−swapWithNew (MutableFdCache ref) = atomicModifyIORef ref (\t -> (empty, t))
73+swapWithNew :: IORef FdCache -> IO FdCache
74+swapWithNew ref = atomicModifyIORef ref (\t -> (empty, t))
7875
7976update :: MutableFdCache -> (FdCache -> FdCache) -> IO ()
80−update (MutableFdCache ref) f = do
77+update (MutableFdCache ref) = update' ref
78+
79+update' :: IORef FdCache -> (FdCache -> FdCache) -> IO ()
80+update' ref f = do
8181 !_ <- atomicModifyIORef ref $ \t -> let !new = f t in (new, ())
8282 return ()
8383
@@ -103,24 +103,16 @@ withFdCache duration action = bracket (initialize duration)
103103initialize :: Int -> IO (Maybe MutableFdCache)
104104initialize 0 = return Nothing
105105initialize duration = do
106− mfc <- newMutableFdCache
107− -- FIXME: how to stop this thread?
108− void . forkIO $ cleanLoop duration mfc
109− return (Just mfc)
110−
111−cleanLoop :: Int -> MutableFdCache -> IO ()
112−cleanLoop duration mfc = loop
113− where
114− loop = do
115− clean mfc
116− threadDelay duration
117− loop
118−
119−clean :: MutableFdCache -> IO ()
120−clean mfc = do
121− old <- swapWithNew mfc
106+ ref' <- forkIOwithBreakableForever empty $ \ref -> do
107+ threadDelay duration
108+ clean ref
109+ return (Just (MutableFdCache ref'))
110+
111+clean :: IORef FdCache -> IO ()
112+clean ref = do
113+ old <- swapWithNew ref
122114 new <- pruneWith old prune
123− update mfc (merge new)
115+ update' ref (merge new)
124116
125117prune :: t -> Some FdEntry -> IO [(t, Some FdEntry)]
126118prune k v@(One (FdEntry _ fd mst)) = status mst >>= prune'
@@ -142,7 +134,9 @@ prune k (Tom ent@(FdEntry _ fd mst) vs) = status mst >>= prune'
142134
143135terminate :: Maybe MutableFdCache -> IO ()
144136terminate Nothing = return ()
145−terminate (Just (MutableFdCache mfc)) = readIORef mfc >>= mapM_ closeIt . toList
137+terminate (Just (MutableFdCache ref)) = mask_ $ do
138+ !t <- breakForever ref
139+ mapM_ closeIt $ toList t
146140 where
147141 closeIt (_, FdEntry _ fd _) = closeFd fd
148142