diff options
| author | bjorn <bjorn@bringert.net> | 2008-10-20 08:24:01 +0000 |
|---|---|---|
| committer | bjorn <bjorn@bringert.net> | 2008-10-20 08:24:01 +0000 |
| commit | d20501147054cc655540e0629f7ec286d5e1c601 (patch) | |
| tree | 1cb4184387b50d3790539934888bc416a3fcee82 /src | |
| parent | 0205f341f5d817fcf3a43057db9d0ef2a23af98c (diff) | |
fastcgi: better grammar cache implementation: don't deadlock on exceptions
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/Cache.hs | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/src/server/Cache.hs b/src/server/Cache.hs index c56e122ae..c99f212e3 100644 --- a/src/server/Cache.hs +++ b/src/server/Cache.hs @@ -1,6 +1,6 @@ module Cache (Cache,newCache,readCache) where -import Control.Concurrent +import Control.Concurrent.MVar import Data.Map (Map) import qualified Data.Map as Map import System.Directory (getModificationTime) @@ -8,7 +8,7 @@ import System.Time (ClockTime) data Cache a = Cache { cacheLoad :: FilePath -> IO a, - cacheObjects :: MVar (Map FilePath (MVar (ClockTime, a))) + cacheObjects :: MVar (Map FilePath (MVar (Maybe (ClockTime, a)))) } newCache :: (FilePath -> IO a) -> IO (Cache a) @@ -18,19 +18,17 @@ newCache load = readCache :: Cache a -> FilePath -> IO a readCache c file = - do t' <- getModificationTime file - objs <- takeMVar (cacheObjects c) - case Map.lookup file objs of - -- object is in cache - Just v -> do (t,x) <- takeMVar v - putMVar (cacheObjects c) objs - -- check timestamp - x' <- if t == t' then return x else cacheLoad c file - putMVar v (t',x') - return x' - -- first time this object is requested - Nothing -> do v <- newEmptyMVar - putMVar (cacheObjects c) (Map.insert file v objs) - x' <- cacheLoad c file - putMVar v (t',x') - return x' + do v <- modifyMVar (cacheObjects c) findEntry + modifyMVar v readObject + where + -- Find the cache entry, inserting a new one if neccessary. + findEntry objs = case Map.lookup file objs of + Just v -> return (objs,v) + Nothing -> do v <- newMVar Nothing + return (Map.insert file v objs, v) + -- Check time stamp, and reload if different than the cache entry + readObject m = do t' <- getModificationTime file + x' <- case m of + Just (t,x) | t' == t -> return x + _ -> cacheLoad c file + return (Just (t',x'), x') |
