module Data.LruCache.IO
( LruHandle(..)
, cached
, newLruHandle
, StripedLruHandle(..)
, stripedCached
, newStripedLruHandle
) where
import Control.Applicative ((<$>))
import Data.Hashable (Hashable, hash)
import Data.IORef (IORef, atomicModifyIORef', newIORef)
import Data.Vector (Vector)
import qualified Data.Vector as Vector
import Prelude hiding (lookup)
import Data.LruCache
newtype LruHandle k v = LruHandle (IORef (LruCache k v))
newLruHandle :: Int -> IO (LruHandle k v)
newLruHandle capacity = LruHandle <$> newIORef (empty capacity)
cached :: (Hashable k, Ord k) => LruHandle k v -> k -> IO v -> IO v
cached (LruHandle ref) k io =
do lookupRes <- atomicModifyIORef' ref $ \c ->
case lookup k c of
Nothing -> (c, Nothing)
Just (v, c') -> (c', Just v)
case lookupRes of
Just v -> return v
Nothing ->
do v <- io
atomicModifyIORef' ref $ \c -> (insert k v c, ())
return v
newtype StripedLruHandle k v = StripedLruHandle (Vector (LruHandle k v))
newStripedLruHandle :: Int -> Int -> IO (StripedLruHandle k v)
newStripedLruHandle numStripes capacityPerStripe =
StripedLruHandle <$> Vector.replicateM numStripes (newLruHandle capacityPerStripe)
stripedCached ::
(Hashable k, Ord k) =>
StripedLruHandle k v ->
k ->
IO v ->
IO v
stripedCached (StripedLruHandle v) k =
cached (v Vector.! idx) k
where
idx = hash k `mod` Vector.length v