gloss-relative-0.1.1.0: src/Graphics/Gloss/Relative/Internal/Cache.hs
module Graphics.Gloss.Relative.Internal.Cache where
import Graphics.Gloss.Relative.Internal.Window
import Graphics.Gloss.Relative.Internal.Dimension
import Graphics.Gloss.Relative.Internal.Data
import Data.Map.Strict (Map(..))
import qualified Data.Map.Strict as Map
import Data.IORef
import System.Mem.StableName
import Control.Monad.Trans
type CacheKey = (ScreenSize,String,Int)
type CacheVal = (WindowOutput,Int)
type CacheTable = IORef (Map CacheKey CacheVal)
newCacheTable :: IO CacheTable
newCacheTable = newIORef Map.empty
insertCacheTable :: Int -> CacheTable -> CacheKey -> WindowOutput -> IO ()
insertCacheTable i cache key val = do
atomicModifyIORef' cache $ \m -> (Map.insert key (val,i) m, ())
lookupCacheTable :: Int -> CacheTable -> CacheKey -> IO (Maybe WindowOutput)
lookupCacheTable i cache key = do
table <- readIORef cache
case Map.lookup key table of
Nothing -> return Nothing
Just (v,_) -> do
writeIORef cache $! Map.insert key (v,i) table
return $ Just v
cachedRenderFrame :: Int -> CacheTable -> (String -> Frame -> Window IO ()) -> String -> Frame -> Window IO ()
cachedRenderFrame i cache render label f = do
dim <- askDimension
let screen = dimensionToScreenSize dim
sn <- liftIO $ makeStableName f
let key = (screen,label,hashStableName sn)
mb <- liftIO $ lookupCacheTable i cache key
case mb of
Just wo -> tellWindowOutput wo
Nothing -> do
wo <- lift $ execWindow dim (render label f)
liftIO $ insertCacheTable i cache key wo
tellWindowOutput wo
evictOldCacheTable :: Int -> Int -> CacheTable -> IO ()
evictOldCacheTable frame maxAge cache = atomicModifyIORef' cache $ \m -> (Map.filter (\ce -> frame - snd ce <= maxAge) m,())