packages feed

lrucaching 0.2.1 → 0.3.0

raw patch · 5 files changed

+97/−5 lines, 5 filesdep ~hspecPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: hspec

API changes (from Hackage documentation)

- Data.LruCache.IO: newStripedHandle :: Int -> Int -> IO (StripedLruHandle k v)
+ Data.LruCache.IO: newStripedLruHandle :: Int -> Int -> IO (StripedLruHandle k v)
+ Data.LruCache.IO.Finalizer: LruHandle :: (IORef (LruCache k (v, v -> IO ()))) -> LruHandle k v
+ Data.LruCache.IO.Finalizer: StripedLruHandle :: (Vector (LruHandle k v)) -> StripedLruHandle k v
+ Data.LruCache.IO.Finalizer: cached :: (Hashable k, Ord k) => LruHandle k v -> k -> IO v -> (v -> IO ()) -> IO v
+ Data.LruCache.IO.Finalizer: newLruHandle :: Int -> IO (LruHandle k v)
+ Data.LruCache.IO.Finalizer: newStripedLruHandle :: Int -> Int -> IO (StripedLruHandle k v)
+ Data.LruCache.IO.Finalizer: newtype LruHandle k v
+ Data.LruCache.IO.Finalizer: newtype StripedLruHandle k v
+ Data.LruCache.IO.Finalizer: stripedCached :: (Hashable k, Ord k) => StripedLruHandle k v -> k -> IO v -> (v -> IO ()) -> IO v

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+0.3.0+-----+* Add `Data.LruCache.IO.Finalizer` for automatically running finalizer+  when evicting cache entrvies.+* Rename `newStripedHandle` to `newStripedLruHandle`+ 0.2.1 ----- * Fix build with GHC 7.8
README.md view
@@ -1,7 +1,7 @@ # lrucaching  [![Build Status](https://travis-ci.org/cocreature/lrucaching.svg?branch=master)](https://travis-ci.org/cocreature/lrucaching)-[![Hackage](https://img.shields.io/hackage/v/lrucaching.svg?maxAge=2592000)]()+[![Hackage](https://img.shields.io/hackage/v/lrucaching.svg)](https://hackage.haskell.org/package/lrucaching)  An implementation of lrucaches based on a [blogpost](https://jaspervdj.be/posts/2015-02-24-lru-cache.html) by
lrucaching.cabal view
@@ -1,5 +1,5 @@ name:                  lrucaching-version:               0.2.1+version:               0.3.0 synopsis:              LRU cache description:           Please see README.md homepage:              https://github.com/cocreature/lrucaching#readme@@ -19,6 +19,7 @@   hs-source-dirs:      src   exposed-modules:     Data.LruCache                        Data.LruCache.IO+                       Data.LruCache.IO.Finalizer                        Data.LruCache.Internal   build-depends:       base        >= 4.7  && < 5                      , base-compat >= 0.9  && < 0.10
src/Data/LruCache/IO.hs view
@@ -5,6 +5,8 @@ License     : BSD3 Maintainer  : moritz.kiefer@purelyfunctional.org Convenience module for the common case of caching results of IO actions.+See 'Data.LruCache.IO.Finalizer' if you want to run finalizers+automatically when cache entries are evicted -} module Data.LruCache.IO   ( LruHandle(..)@@ -12,7 +14,7 @@   , newLruHandle   , StripedLruHandle(..)   , stripedCached-  , newStripedHandle+  , newStripedLruHandle   ) where  import           Control.Applicative ((<$>))@@ -53,8 +55,8 @@  -- | Create a new 'StripedHandle' with the given number of stripes and -- the given capacity for each stripe.-newStripedHandle :: Int -> Int -> IO (StripedLruHandle k v)-newStripedHandle numStripes capacityPerStripe =+newStripedLruHandle :: Int -> Int -> IO (StripedLruHandle k v)+newStripedLruHandle numStripes capacityPerStripe =   StripedLruHandle <$> Vector.replicateM numStripes (newLruHandle capacityPerStripe)  -- | Striped version of 'cached'.
+ src/Data/LruCache/IO/Finalizer.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE BangPatterns #-}+{-|+Module      : Data.LruCache.IO.Finalizer+Copyright   : (c) Moritz Kiefer, 2016+              (c) Jasper Van der Jeugt, 2015+License     : BSD3+Maintainer  : moritz.kiefer@purelyfunctional.org+Convenience module for the common case of caching results of IO actions +when finalizers have to be run when cache entries are evicted.+-}+module Data.LruCache.IO.Finalizer+  ( LruHandle(..)+  , newLruHandle+  , cached+  , StripedLruHandle(..)+  , newStripedLruHandle+  , stripedCached+  ) where++import           Control.Applicative ((<$>))+import           Data.Foldable (traverse_)+import           Data.Hashable (Hashable, hash)+import           Data.IORef (IORef, atomicModifyIORef', newIORef)+import           Data.Tuple (swap)+import           Data.Vector (Vector)+import qualified Data.Vector as Vector+import           Prelude hiding (lookup)++import           Data.LruCache++-- | Store a LRU cache in an 'IORef to be able to conveniently update it.+newtype LruHandle k v = LruHandle (IORef (LruCache k (v, v -> IO ())))++-- | Create a new LRU cache of the given size.+newLruHandle :: Int -> IO (LruHandle k v)+newLruHandle capacity = LruHandle <$> newIORef (empty capacity)++-- | Return the cached result of the action or, in the case of a cache+-- miss, execute the action and insert it in the cache.+cached ::+  (Hashable k, Ord k) =>+  LruHandle k v ->+  k ->+  IO v ->+  (v -> IO ()) {- ^ finalizer -} ->+  IO v+cached (LruHandle ref) k io finalizer =+  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+            evicted <- atomicModifyIORef' ref $ \c -> +              swap (insertView k (v,finalizer) c)+            traverse_ (\(_,(v',finalize')) -> finalize' v') evicted+            return v++-- | Using a stripe of multiple handles can improve the performance in+-- the case of concurrent accesses since several handles can be+-- accessed in parallel.+newtype StripedLruHandle k v = StripedLruHandle (Vector (LruHandle k v))++-- | Create a new 'StripedHandle' with the given number of stripes and+-- the given capacity for each stripe.+newStripedLruHandle :: Int -> Int -> IO (StripedLruHandle k v)+newStripedLruHandle numStripes capacityPerStripe =+  StripedLruHandle <$> Vector.replicateM numStripes (newLruHandle capacityPerStripe)++-- | Striped version of 'cached'.+stripedCached ::+  (Hashable k, Ord k) =>+  StripedLruHandle k v ->+  k ->+  IO v ->+  (v -> IO ()) {- ^ finalizer -} ->+  IO v+stripedCached (StripedLruHandle v) k =+    cached (v Vector.! idx) k+  where+    idx = hash k `mod` Vector.length v