-- | The Cache module allows us to cache results of expensive stateful -- computations in memory. -- Possible improvements - -- (1) use hashing instead module Util.Cache( Cache, -- a cache (a stateful object). Takes parameters key and elt. -- key must be an instance of Ord. newCache, -- :: Ord key => (key -> IO elt) -> IO(Cache key elt) getCached -- :: Ord key => Cache key elt -> key -> IO elt ) where import qualified Data.Map as Map import Control.Concurrent data Ord key => Cache key elt = Cache (MVar(Map.Map key (MVar elt))) (key -> IO elt) newCache :: Ord key => (key -> IO elt) -> IO(Cache key elt) newCache getAct = do cacheMVar <- newMVar Map.empty return (Cache cacheMVar getAct) {- We do this in two stages so as not to hold up the whole cache at once. -} getCached :: Ord key => Cache key elt -> key -> IO elt getCached (Cache cacheMVar getAct) key = do cacheMap <- takeMVar cacheMVar case Map.lookup key cacheMap of Just mVar -> do putMVar cacheMVar cacheMap readMVar mVar Nothing -> do mVar <- newEmptyMVar putMVar cacheMVar (Map.insert key mVar cacheMap) value <- getAct key putMVar mVar value return value