{-# LANGUAGE ScopedTypeVariables #-}
module Data.Git.Storage.CacheFile (CacheFile, newCacheVal, getCacheVal) where
import Control.Concurrent.MVar
import qualified Control.Exception as E
import Data.Git.Imports
import Data.Git.OS
data CacheFile a = CacheFile
{ cacheFilepath :: LocalPath
, cacheRefresh :: IO a
, cacheIniVal :: a
, cacheLock :: MVar (MTime, a)
}
newCacheVal :: LocalPath -> IO a -> a -> IO (CacheFile a)
newCacheVal path refresh initialVal =
CacheFile path refresh initialVal <$> newMVar (MTime timeZero, initialVal)
getCacheVal :: CacheFile a -> IO a
getCacheVal cachefile = modifyMVar (cacheLock cachefile) getOrRefresh
where getOrRefresh s@(mtime, cachedVal) = do
cMTime <- tryGetMTime $ cacheFilepath cachefile
case cMTime of
Nothing -> return ((MTime timeZero, cacheIniVal cachefile), cacheIniVal cachefile)
Just newMtime | newMtime > mtime -> cacheRefresh cachefile >>= \v -> return ((newMtime, v), v)
| otherwise -> return (s, cachedVal)
tryGetMTime :: LocalPath -> IO (Maybe MTime)
tryGetMTime filepath = (Just <$> getMTime filepath) `E.catch` \(_ :: E.SomeException) -> return Nothing