{-# LANGUAGE DeriveDataTypeable #-} module Control.Concurrent.Cache (Cache, newCache, fetch) where import Control.Concurrent.MVar import Control.Monad (liftM) import Data.Typeable (Typeable) -- | A thread-safe write-once cache. If you need more functionality, -- (e.g. multiple write, cache clearing) use an 'MVar' instead. newtype Cache a = Cache (MVar (Maybe a)) deriving (Eq, Typeable) -- | Fetch the value stored in the cache, -- or call the supplied fallback and store the result, -- if the cache is empty. fetch :: Cache a -> IO a -> IO a fetch (Cache var) action = go where go = readMVar var >>= \m -> case m of Just a -> return a Nothing -> do modifyMVar_ var $ \m' -> case m' of Just a -> return (Just a) Nothing -> liftM Just action go -- | Create an empty cache. newCache :: IO (Cache a) newCache = do var <- newMVar Nothing return (Cache var)