packages feed

cache 0.1.0.1 → 0.1.1.0

raw patch · 3 files changed

+107/−23 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Cache: copyCacheSTM :: Cache k v -> STM (Cache k v)
+ Data.Cache: deleteSTM :: (Eq k, Hashable k) => k -> Cache k v -> STM ()
+ Data.Cache: insertSTM :: (Eq k, Hashable k) => k -> v -> Cache k v -> Maybe TimeSpec -> STM ()
+ Data.Cache: keysSTM :: Cache k v -> STM [k]
+ Data.Cache: lookupSTM :: (Eq k, Hashable k) => Bool -> k -> Cache k v -> TimeSpec -> STM (Maybe v)
+ Data.Cache: newCacheSTM :: Maybe TimeSpec -> STM (Cache k v)
+ Data.Cache: purgeExpiredSTM :: (Eq k, Hashable k) => Cache k v -> TimeSpec -> STM ()
+ Data.Cache: sizeSTM :: Cache k v -> STM Int
+ Data.Cache.Internal: Cache :: TVar (HashMap k (CacheItem v)) -> Maybe TimeSpec -> Cache k v
+ Data.Cache.Internal: CacheItem :: v -> Maybe TimeSpec -> CacheItem v
+ Data.Cache.Internal: [container] :: Cache k v -> TVar (HashMap k (CacheItem v))
+ Data.Cache.Internal: [defaultExpiration] :: Cache k v -> Maybe TimeSpec
+ Data.Cache.Internal: [itemExpiration] :: CacheItem v -> Maybe TimeSpec
+ Data.Cache.Internal: [item] :: CacheItem v -> v
+ Data.Cache.Internal: data Cache k v
+ Data.Cache.Internal: data CacheItem v
+ Data.Cache.Internal: nowSTM :: STM TimeSpec

Files

cache.cabal view
@@ -1,5 +1,5 @@ name:           cache-version:        0.1.0.1+version:        0.1.1.0 synopsis:       An in-memory key/value store with expiration support homepage:       https://github.com/hverr/haskell-cache#readme license:        BSD3@@ -11,7 +11,6 @@ build-type:     Simple cabal-version:  >= 1.10 tested-with:    GHC == 7.10.3, GHC == 8.0.1-homepage:       https://github.com/hverr/haskell-cache bug-reports:    https://github.com/hverr/haskell-cache/issues description:     An in-memory key/value store with expiration support, similar@@ -24,6 +23,7 @@   ghc-options:         -Wall   hs-source-dirs:      src   exposed-modules:     Data.Cache+                     , Data.Cache.Internal   build-depends:       base >= 4.8 && < 5                      , clock >= 0.7 && < 0.8                      , hashable >= 1.0.1.1
src/Data/Cache.hs view
@@ -1,9 +1,9 @@ -- | -- Module:      Data.Cache -- Copyright:   (c) 2016 Henri Verroken--- LIcense:     BSD3+-- License:     BSD3 -- Maintainer:  Henri Verroken <henriverroken@gmail.com>--- Stability:   experimental+-- Stability:   stable -- -- An in-memory key/value store with expiration support, similar -- to patrickmn/go-cache for Go.@@ -18,26 +18,34 @@     -- * Creating a cache     Cache   , newCache+  , newCacheSTM      -- * Cache properties   , defaultExpiration   , setDefaultExpiration   , copyCache+  , copyCacheSTM      -- * Managing items     -- ** Insertion   , insert   , insert'+  , insertSTM     -- ** Querying   , lookup   , lookup'+  , lookupSTM   , keys+  , keysSTM     -- ** Deletion   , delete+  , deleteSTM   , purgeExpired+  , purgeExpiredSTM      -- * Cache information   , size+  , sizeSTM ) where  import Prelude hiding (lookup)@@ -45,32 +53,18 @@ import Control.Concurrent.STM import Control.Monad import Control.Monad.Trans.Maybe+import Data.Cache.Internal import qualified Data.HashMap.Strict as HM import Data.Hashable import Data.Maybe import System.Clock --- | The cache with keys of type @k@ and values of type @v@.------ Create caches with the 'newCache' and 'copyCache' functions.-data Cache k v = Cache {-    container :: TVar (HM.HashMap k (CacheItem v))-    -- | The default expiration value of newly added cache items.-    ---    -- See 'newCache' for more information on the default expiration value.-  , defaultExpiration :: Maybe TimeSpec-}- -- | Change the default expiration value of newly added cache items. -- -- See 'newCache' for more information on the default expiration value. setDefaultExpiration :: Cache k v -> Maybe TimeSpec -> Cache k v setDefaultExpiration c t = c { defaultExpiration = t } -data CacheItem v = CacheItem {-    item :: v-  , itemExpiration :: Maybe TimeSpec-}  isExpired :: TimeSpec -> CacheItem v -> Bool isExpired t i = fromMaybe False (itemExpiration i >>= f t)@@ -91,6 +85,12 @@     m <- newTVarIO HM.empty     return Cache { container = m, defaultExpiration = d } +-- | STM variant of 'newCache'+newCacheSTM :: Maybe TimeSpec -> STM (Cache k v)+newCacheSTM d = do+    m <- newTVar HM.empty+    return Cache { container = m, defaultExpiration = d }+ copyCacheSTM :: Cache k v -> STM (Cache k v) copyCacheSTM c = do     m <- newTVar =<< readTVar (container c)@@ -100,6 +100,7 @@ copyCache :: Cache k v -> IO (Cache k v) copyCache = atomically . copyCacheSTM +-- | STM variant of 'size' sizeSTM :: Cache k v -> STM Int sizeSTM c = HM.size <$> readTVar (container c) @@ -107,6 +108,7 @@ size :: Cache k v -> IO Int size = atomically . sizeSTM +-- | STM variant of 'delete'. deleteSTM :: (Eq k, Hashable k) => k -> Cache k v -> STM () deleteSTM k c = writeTVar v =<< (HM.delete k <$> readTVar v) where v = container c @@ -145,25 +147,59 @@ lookup :: (Eq k, Hashable k) => Cache k v -> k -> IO (Maybe v) lookup c k = runMaybeT $ item <$> MaybeT (lookupItem True k c) +-- | Lookup an item with a given key in the 'STM' monad, given the current 'Monotonic' time.+--+-- STM variant of 'lookup' and 'lookup''+lookupSTM :: (Eq k, Hashable k) => Bool             -- ^ Whether or not to eagerly delete the item if its expired+                                -> k                -- ^ The key to lookup+                                -> Cache k v        -- ^ The cache+                                -> TimeSpec         -- ^ The current 'Monotonic' time, i.e. @getTime Monotonic@+                                -> STM (Maybe v)+lookupSTM f k c t = do+    mv <- lookupItemT f k c t+    return $! item <$> mv+ insertItem :: (Eq k, Hashable k) => k -> CacheItem v -> Cache k v -> STM () insertItem k a c = writeTVar v =<< (HM.insert k a <$> readTVar v) where v = container c -insertT :: (Eq k, Hashable k) => k -> v -> Cache k v -> Maybe TimeSpec -> STM ()-insertT k a c t = insertItem k (CacheItem a t) c+-- | Insert an item in the cache, with an explicit expiration value, in the+-- 'STM' monad.+--+-- If the expiration value is 'Nothing', the item will never expire. The+-- default expiration value of the cache is ignored.+--+-- The expiration value is the absolute 'Monotonic' time the item expires. You+-- should manually construct the absolute 'Monotonic' time, as opposed to the+-- behaviour of 'insert''.+--+-- E.g.+--+-- > action :: Cache -> IO ()+-- > action c = do+-- >     t <- getTime Monotonic+-- >     let t' = t + (defaultExpiration c)+-- >     atomically $ insertSTM 0 0 c (Just t')+--+insertSTM :: (Eq k, Hashable k) => k -> v -> Cache k v -> Maybe TimeSpec -> STM ()+insertSTM k a c t = insertItem k (CacheItem a t) c  -- | Insert an item in the cache, with an explicit expiration value. -- -- If the expiration value is 'Nothing', the item will never expire. The -- default expiration value of the cache is ignored.+--+-- The expiration value is relative to the current 'Monotonic' time, i.e. it+-- will be automatically added to the result of @getTime Monotonic@. insert' :: (Eq k, Hashable k) =>  Cache k v -> Maybe TimeSpec -> k -> v -> IO ()-insert' c Nothing k a  = atomically $ insertT k a c Nothing-insert' c (Just d) k a = atomically . insertT k a c =<< Just . (d +) <$> now+insert' c Nothing k a  = atomically $ insertSTM k a c Nothing+insert' c (Just d) k a = atomically . insertSTM k a c =<< Just . (d +) <$> now  -- | Insert an item in the cache, using the default expiration value of -- the cache. insert :: (Eq k, Hashable k) => Cache k v -> k -> v -> IO () insert c = insert' c (defaultExpiration c) +-- | STM variant of 'keys'. keysSTM :: Cache k v -> STM [k] keysSTM c = HM.keys <$> readTVar (container c) @@ -174,6 +210,10 @@ now :: IO TimeSpec now = getTime Monotonic +-- | STM variant of 'purgeExpired'.+--+-- The 'TimeSpec' argument should be the current 'Monotonic' time, i.e.+-- @getTime Monotonic@. purgeExpiredSTM :: (Eq k, Hashable k) => Cache k v -> TimeSpec -> STM () purgeExpiredSTM c t = mapM_ (\k -> lookupItemT True k c t) =<< keysSTM c 
+ src/Data/Cache/Internal.hs view
@@ -0,0 +1,44 @@+-- |+-- Module:      Data.Cache.Internal+-- Copyright:   (c) 2018 Henri Verroken+-- License:     BSD3+-- Maintainer:  Henri Verroken <henriverroken@gmail.com>+-- Stability:   stable+--+-- This modules exposes some of the internals of 'Data.Cache' as well as some+-- auxiliary functions for expert users.++module Data.Cache.Internal (+    -- * Cache constructor+    Cache(..)+  , CacheItem(..)++    -- * Unsafe auxiliary functions+  , nowSTM+) where++import Control.Concurrent.STM+import GHC.Conc (unsafeIOToSTM)+import System.Clock+import qualified Data.HashMap.Strict as HM++-- | The cache with keys of type @k@ and values of type @v@.+--+-- Create caches with the 'newCache' and 'copyCache' functions.+data Cache k v = Cache {+    container :: TVar (HM.HashMap k (CacheItem v))+    -- | The default expiration value of newly added cache items.+    --+    -- See 'newCache' for more information on the default expiration value.+  , defaultExpiration :: Maybe TimeSpec+}++-- | A container data type holding a cache item.+data CacheItem v = CacheItem {+    item :: v+  , itemExpiration :: Maybe TimeSpec+}++-- | Get the current time in the 'STM' monad using 'unsafeIOToSTM'.+nowSTM :: STM TimeSpec+nowSTM = unsafeIOToSTM $ getTime Monotonic