module Control.Concurrent.Cache (Cache, newCache, fetch) where import Control.Concurrent.MVar import Data.IORef -- | A thread-safe write-once cache. newtype Cache a = Cache { -- | Fetch the value stored in the cache, -- or call the supplied fallback and store the result, -- if the cache is empty. fetch :: IO a -> IO a } -- | Create an empty cache. newCache :: IO (Cache a) newCache = do b <- newMVar True r <- newIORef undefined return (cache b r) cache :: MVar Bool -> IORef a -> Cache a cache b r = Cache $ \action -> do modifyMVar_ b $ \isEmpty -> if isEmpty then do v <- action writeIORef r v return False else return False readIORef r