{-# OPTIONS_HADDOCK not-home #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Data.Cache.LRU.IO.Internal where
import Prelude hiding ( lookup, mod, take )
import Control.Applicative ( (<$>) )
import Control.Concurrent.MVar ( MVar )
import qualified Control.Concurrent.MVar as MV
import Control.Exception ( bracketOnError )
import Data.Cache.LRU ( LRU )
import qualified Data.Cache.LRU as LRU
import Data.Typeable (Typeable)
newtype AtomicLRU key val = C (MVar (LRU key val)) deriving Typeable
newAtomicLRU :: Ord key => Maybe Integer
-> IO (AtomicLRU key val)
newAtomicLRU = fmap C . MV.newMVar . LRU.newLRU
fromList :: Ord key => Maybe Integer
-> [(key, val)] -> IO (AtomicLRU key val)
fromList s l = fmap C . MV.newMVar $ LRU.fromList s l
toList :: Ord key => AtomicLRU key val -> IO [(key, val)]
toList (C mvar) = LRU.toList <$> MV.readMVar mvar
maxSize :: AtomicLRU key val -> IO (Maybe Integer)
maxSize (C mvar) = LRU.maxSize <$> MV.readMVar mvar
insert :: Ord key => key -> val -> AtomicLRU key val -> IO ()
insert key val (C mvar) = modifyMVar_' mvar $ return . LRU.insert key val
lookup :: Ord key => key -> AtomicLRU key val -> IO (Maybe val)
lookup key (C mvar) = modifyMVar' mvar $ return . LRU.lookup key
delete :: Ord key => key -> AtomicLRU key val -> IO (Maybe val)
delete key (C mvar) = modifyMVar' mvar $ return . LRU.delete key
pop :: Ord key => AtomicLRU key val -> IO (Maybe (key, val))
pop (C mvar) = modifyMVar' mvar $ return . LRU.pop
size :: AtomicLRU key val -> IO Int
size (C mvar) = LRU.size <$> MV.readMVar mvar
modifyAtomicLRU :: (LRU.LRU key val -> LRU.LRU key val)
-> AtomicLRU key val
-> IO ()
modifyAtomicLRU f = modifyAtomicLRU' $ return . f
modifyAtomicLRU' :: (LRU.LRU key val -> IO (LRU.LRU key val))
-> AtomicLRU key val
-> IO ()
modifyAtomicLRU' f (C mvar) = modifyMVar_' mvar f
modifyMVar_' :: MVar a -> (a -> IO a) -> IO ()
modifyMVar_' mvar f = do
let take = MV.takeMVar mvar
replace = MV.putMVar mvar
mod x = do
x' <- f x
MV.putMVar mvar $! x'
bracketOnError take replace mod
modifyMVar' :: MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar' mvar f = do
let take = MV.takeMVar mvar
replace = MV.putMVar mvar
mod x = do
(x', result) <- f x
MV.putMVar mvar $! x'
return result
bracketOnError take replace mod