module Cache.Internal where
import Prelude hiding (lookup)
import Data.Maybe
import qualified Data.HashMap.Lazy as H
import Data.Hashable
import Data.Sequence as S
data Cache k v = Cache {
_limit :: Maybe Int,
_size :: Int,
_cache :: H.HashMap k v,
_queue :: Seq k
} deriving (Show, Eq)
instance (Hashable k, Eq k) => IsCache Cache k where
lookup k cache = H.lookup k $ _cache cache
insert k v cache = (if needDump then dump 1 cache else cache) {
_cache = H.insert k v $ _cache cache,
_queue = (_queue cache) |> k,
_size = 1 + _size cache
}
where needDump = isNothing (limit cache) || fromJust (limit cache) > size cache
limit = _limit
size = _size
setLimit lm cache = cache {_limit = lm}
dumpOldest cache = cache {
_cache = H.delete k _c,
_queue = S.drop 1 _q,
_size = size cache 1
} where
_c = _cache cache
_q = _queue cache
k = _queue cache `index` 0
newCache lm = Cache {
_limit = lm,
_size = 0,
_cache = H.empty,
_queue = S.empty
}
class IsCache m k where
newCache :: Maybe Int -> m k v
newUnlimitedCache :: m k v
newUnlimitedCache = newCache Nothing
lookup :: k -> m k v -> Maybe v
insert :: k -> v -> m k v -> m k v
dumpOldest :: m k v -> m k v
size :: m k v -> Int
limit :: m k v -> Maybe Int
setLimit :: Maybe Int -> m k v -> m k v
dump :: Int -> m k v -> m k v
dump 0 cache = cache
dump n cache = dump (n 1) (dumpOldest cache)