packages feed

arbor-lru-cache 0.1.1.0 → 0.1.1.1

raw patch · 6 files changed

+106/−95 lines, 6 filesdep −generic-lensdep −lensdep ~containersdep ~hedgehogdep ~hspecPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: generic-lens, lens

Dependency ranges changed: containers, hedgehog, hspec, hw-hspec-hedgehog, stm

API changes (from Hackage documentation)

- Arbor.LruCache.Internal.PriorityQueue: PriorityQueue :: [(p, v)] -> PriorityQueue p v
- Arbor.LruCache.Internal.PriorityQueue: instance (GHC.Classes.Eq p, GHC.Classes.Eq v) => GHC.Classes.Eq (Arbor.LruCache.Internal.PriorityQueue.PriorityQueue p v)
- Arbor.LruCache.Internal.PriorityQueue: instance (GHC.Show.Show p, GHC.Show.Show v) => GHC.Show.Show (Arbor.LruCache.Internal.PriorityQueue.PriorityQueue p v)
- Arbor.LruCache.Internal.PriorityQueue: newtype PriorityQueue p v
+ Arbor.LruCache.Internal.PriorityQueue: PQueue :: [(p, v)] -> PQueue p v
+ Arbor.LruCache.Internal.PriorityQueue: forceSpine :: [a] -> [a]
+ Arbor.LruCache.Internal.PriorityQueue: instance (GHC.Classes.Eq p, GHC.Classes.Eq v) => GHC.Classes.Eq (Arbor.LruCache.Internal.PriorityQueue.PQueue p v)
+ Arbor.LruCache.Internal.PriorityQueue: instance (GHC.Show.Show p, GHC.Show.Show v) => GHC.Show.Show (Arbor.LruCache.Internal.PriorityQueue.PQueue p v)
+ Arbor.LruCache.Internal.PriorityQueue: newtype PQueue p v
+ Arbor.LruCache.Internal.PriorityQueue: size :: PQueue p v -> Int
- Arbor.LruCache: Cache :: CacheConfig -> TVar Int -> TVar (Map k (TVar (Maybe v))) -> TVar (PriorityQueue Int k) -> TVar Int -> TVar Int -> k -> IO v -> k -> v -> IO () -> Cache k v
+ Arbor.LruCache: Cache :: CacheConfig -> TVar Int -> TVar (Map k (TVar (Maybe v))) -> TVar (PQueue Int k) -> TVar Int -> TVar Int -> (k -> IO v) -> (k -> v -> IO ()) -> Cache k v
- Arbor.LruCache: [$sel:evictionQueue:Cache] :: Cache k v -> TVar (PriorityQueue Int k)
+ Arbor.LruCache: [$sel:evictionQueue:Cache] :: Cache k v -> TVar (PQueue Int k)
- Arbor.LruCache.Internal.PriorityQueue: empty :: PriorityQueue p v
+ Arbor.LruCache.Internal.PriorityQueue: empty :: PQueue p v
- Arbor.LruCache.Internal.PriorityQueue: insert :: Eq v => p -> v -> PriorityQueue p v -> PriorityQueue p v
+ Arbor.LruCache.Internal.PriorityQueue: insert :: Eq v => p -> v -> PQueue p v -> PQueue p v
- Arbor.LruCache.Internal.PriorityQueue: take :: Ord p => Int -> PriorityQueue p v -> ([v], PriorityQueue p v)
+ Arbor.LruCache.Internal.PriorityQueue: take :: Ord p => Int -> PQueue p v -> ([v], PQueue p v)
- Arbor.LruCache.Internal.PriorityQueue: toList :: Ord p => PriorityQueue p v -> [(p, v)]
+ Arbor.LruCache.Internal.PriorityQueue: toList :: Ord p => PQueue p v -> [(p, v)]
- Arbor.LruCache.Type: Cache :: CacheConfig -> TVar Int -> TVar (Map k (TVar (Maybe v))) -> TVar (PriorityQueue Int k) -> TVar Int -> TVar Int -> k -> IO v -> k -> v -> IO () -> Cache k v
+ Arbor.LruCache.Type: Cache :: CacheConfig -> TVar Int -> TVar (Map k (TVar (Maybe v))) -> TVar (PQueue Int k) -> TVar Int -> TVar Int -> (k -> IO v) -> (k -> v -> IO ()) -> Cache k v
- Arbor.LruCache.Type: [$sel:evictionQueue:Cache] :: Cache k v -> TVar (PriorityQueue Int k)
+ Arbor.LruCache.Type: [$sel:evictionQueue:Cache] :: Cache k v -> TVar (PQueue Int k)

Files

arbor-lru-cache.cabal view
@@ -1,63 +1,64 @@--- This file has been generated from package.yaml by hpack version 0.18.1.------ see: https://github.com/sol/hpack+cabal-version: 2.4 -name:           arbor-lru-cache-version:        0.1.1.0-description:    Please see the README on GitHub at <https://github.com/arbor/arbor-lru-cache#readme>-homepage:       https://github.com/arbor/arbor-lru-cache#readme-bug-reports:    https://github.com/arbor/arbor-lru-cache/issues-author:         Arbor Networks-maintainer:     mayhem@arbor.net-copyright:      2018 Arbor Networks-license:        MIT-license-file:   LICENSE-build-type:     Simple-cabal-version:  >= 1.10+name:               arbor-lru-cache+version:            0.1.1.1+description:        Please see the README on GitHub at <https://github.com/arbor/arbor-lru-cache#readme>+homepage:           https://github.com/arbor/arbor-lru-cache#readme+bug-reports:        https://github.com/arbor/arbor-lru-cache/issues+author:             Arbor Networks+maintainer:         mayhem@arbor.net+copyright:          2018-2019 Arbor Networks+category:           Data, Concurrency+synopsis:           LRU cache based on STM+license:            MIT+license-file:       LICENSE+tested-with:        GHC == 8.8.1, GHC == 8.6.5, GHC == 8.4.4, GHC == 8.2.2+build-type:         Simple+extra-source-files: README.md+                    ChangeLog.md -extra-source-files:-    ChangeLog.md-    README.md+common base                 { build-depends: base                 >= 4.7        && < 5      } +common containers           { build-depends: containers           >= 0.5        && < 0.7    }+common hedgehog             { build-depends: hedgehog             >= 0.5        && < 1.1    }+common hspec                { build-depends: hspec                >= 2.4        && < 2.8    }+common hw-hspec-hedgehog    { build-depends: hw-hspec-hedgehog    >= 0.1        && < 0.2    }+common stm                  { build-depends: stm                  >= 2.5        && < 3      }++common arbor-lru-cache+  build-depends:      arbor-lru-cache++common config+  default-language:   Haskell2010+  ghc-options:        -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints+ source-repository head   type: git   location: https://github.com/arbor/arbor-lru-cache  library-  hs-source-dirs:-      src-  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints-  build-depends:-      base >= 4.7 && < 5-    , containers-    , generic-lens-    , lens-    , stm-  exposed-modules:-      Arbor.LruCache-      Arbor.LruCache.Internal.PriorityQueue-      Arbor.LruCache.Type+  import:             base, config+                    , containers+                    , stm+  exposed-modules:    Arbor.LruCache+                      Arbor.LruCache.Internal.PriorityQueue+                      Arbor.LruCache.Type   other-modules:-      Paths_arbor_lru_cache-  default-language: Haskell2010+  hs-source-dirs:     src + test-suite arbor-lru-cache-test-  type: exitcode-stdio-1.0-  main-is: Spec.hs-  hs-source-dirs:-      test-  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N-  build-depends:-      base >= 4.7 && < 5-    , containers-    , generic-lens-    , lens-    , stm-    , hedgehog-    , hspec-    , hw-hspec-hedgehog-    , arbor-lru-cache-  other-modules:-      Arbor.LruCache.Internal.PriorityQueueSpec-      Arbor.LruCache.LruCacheSpec-  default-language: Haskell2010+  import:             base, config+                    , arbor-lru-cache+                    , containers+                    , hedgehog+                    , hspec+                    , hw-hspec-hedgehog+                    , stm+  type:               exitcode-stdio-1.0+  main-is:            Spec.hs+  build-tool-depends: hspec-discover:hspec-discover+  other-modules:      Arbor.LruCache.Internal.PriorityQueueSpec+                      Arbor.LruCache.LruCacheSpec+  hs-source-dirs:     test+  ghc-options:        -threaded -rtsopts -with-rtsopts=-N
src/Arbor/LruCache.hs view
@@ -1,8 +1,5 @@-{-# LANGUAGE DataKinds           #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections       #-}-{-# LANGUAGE TypeApplications    #-}- module Arbor.LruCache     ( lookup     , makeCache@@ -15,26 +12,26 @@  import Control.Concurrent import Control.Exception-import Control.Lens import Control.Monad-import Data.Generics.Product.Any+import Data.Function      ((&)) import Data.Maybe-import Prelude                   hiding (lookup)+import Prelude            hiding (lookup) +-- import qualified Arbor.LruCache.Internal.PriorityQueue as PQ import qualified Arbor.LruCache.Internal.PriorityQueue as PQ import qualified Arbor.LruCache.Type                   as Z import qualified Control.Concurrent.STM                as STM-import qualified Data.Map                              as M+import qualified Data.Map.Strict                       as M  lookup :: Ord k => k -> Z.Cache k v -> IO v lookup k cache = do   newTmv <- STM.newTVarIO Nothing-  let maxInFlight       = cache ^. the @"config" . the @"maxRequestsInFlight"-  let evict             = cache ^. the @"evict"-  let tRequestsInFlight = cache ^. the @"requestsInFlight"-  let retrieve          = cache ^. the @"retrieve"-  let tEntries          = cache ^. the @"entries"-  let tOccupancy        = cache ^. the @"occupancy"+  let maxInFlight       = cache & Z.config & Z.maxRequestsInFlight+  let evict             = cache & Z.evict+  let tRequestsInFlight = cache & Z.requestsInFlight+  let retrieve          = cache & Z.retrieve+  let tEntries          = cache & Z.entries+  let tOccupancy        = cache & Z.occupancy    join $ STM.atomically $ do     es <- STM.readTVar tEntries@@ -57,14 +54,14 @@                 STM.atomically $ do                   entries2 <- STM.readTVar tEntries                   forM_ (M.lookup k entries2) $ \tv -> STM.writeTVar tv (throw e)-                  STM.modifyTVar tRequestsInFlight pred+                  STM.modifyTVar' tRequestsInFlight pred                   STM.writeTVar tEntries (M.delete k entries2)                 throw e                kvsForEviction <- STM.atomically $ do                 STM.writeTVar newTmv (Just v)-                STM.modifyTVar tRequestsInFlight pred-                STM.modifyTVar tOccupancy succ+                STM.modifyTVar' tRequestsInFlight pred+                STM.modifyTVar' tOccupancy succ                  registerForEviction k cache                 takeEvictionsDue cache@@ -75,19 +72,19 @@  registerForEviction :: Eq k => k -> Z.Cache k v -> STM.STM () registerForEviction k cache = do-  let tEvictionQueue    = cache ^. the @"evictionQueue"-  let tEvictionPriority = cache ^. the @"evictionPriority"+  let tEvictionQueue    = cache & Z.evictionQueue+  let tEvictionPriority = cache & Z.evictionPriority -  STM.modifyTVar tEvictionPriority (+1)+  STM.modifyTVar' tEvictionPriority (+1)   evictionPriority <- STM.readTVar tEvictionPriority-  STM.modifyTVar tEvictionQueue (PQ.insert evictionPriority k)+  STM.modifyTVar' tEvictionQueue (PQ.insert evictionPriority k)  takeEvictionsDue :: Ord k => Z.Cache k v -> STM.STM [(k, v)] takeEvictionsDue cache = do-  let maxOccupancy      = cache ^. the @"config" . the @"maxOccupancy"-  let tEntries          = cache ^. the @"entries"-  let tOccupancy        = cache ^. the @"occupancy"-  let tEvictionQueue    = cache ^. the @"evictionQueue"+  let maxOccupancy      = cache & Z.config & Z.maxOccupancy+  let tEntries          = cache & Z.entries+  let tOccupancy        = cache & Z.occupancy+  let tEvictionQueue    = cache & Z.evictionQueue    evictionQueue <- STM.readTVar tEvictionQueue   occupancy <- STM.readTVar tOccupancy@@ -122,7 +119,7 @@  entries :: Ord k => Z.Cache k v -> IO (M.Map k (Maybe v)) entries cache = do-  let tEntries          = cache ^. the @"entries"+  let tEntries          = cache & Z.entries    STM.atomically $ do     m <- STM.readTVar tEntries
src/Arbor/LruCache/Internal/PriorityQueue.hs view
@@ -1,21 +1,33 @@+{-# LANGUAGE BangPatterns        #-} {-# LANGUAGE ScopedTypeVariables #-}  module Arbor.LruCache.Internal.PriorityQueue where +-- import Control.DeepSeq (seq) import Data.List (sortOn, splitAt) -newtype PriorityQueue p v = PriorityQueue [(p, v)]+newtype PQueue p v = PQueue [(p, v)]   deriving (Eq, Show) -insert :: Eq v => p -> v -> PriorityQueue p v -> PriorityQueue p v-insert p v (PriorityQueue qas) = PriorityQueue ((p, v):filter ((/= v) . snd) qas)+insert :: Eq v => p -> v -> PQueue p v -> PQueue p v+insert !p !v (PQueue qas) =+  let lst = (p, v):filter ((/= v) . snd) qas+  in PQueue (forceSpine lst) -take :: Ord p => Int -> PriorityQueue p v -> ([v], PriorityQueue p v)-take n (PriorityQueue qas) = case splitAt n (sortOn fst qas) of-  (as, bs) -> (snd <$> as, PriorityQueue bs)+take :: Ord p => Int -> PQueue p v -> ([v], PQueue p v)+take n (PQueue qas) = case splitAt n (sortOn fst qas) of+  (as, bs) -> (snd <$> as, PQueue bs) -empty :: PriorityQueue p v-empty = PriorityQueue []+empty :: PQueue p v+empty = PQueue [] -toList :: Ord p => PriorityQueue p v -> [(p, v)]-toList (PriorityQueue qas) = sortOn fst qas+toList :: Ord p => PQueue p v -> [(p, v)]+toList (PQueue qas) = sortOn fst qas++size :: PQueue p v -> Int+size (PQueue qas) = length qas++forceSpine :: [a] -> [a]+forceSpine as =+  let fc = foldr (const id) () as+  in fc `seq` as
src/Arbor/LruCache/Type.hs view
@@ -5,9 +5,10 @@  import GHC.Generics +-- import qualified Arbor.LruCache.Internal.PriorityQueue as PQ import qualified Arbor.LruCache.Internal.PriorityQueue as PQ import qualified Control.Concurrent.STM                as STM-import qualified Data.Map                              as M+import qualified Data.Map.Strict                       as M  data CacheConfig = CacheConfig   { maxRequestsInFlight :: Int@@ -18,7 +19,7 @@   { config           :: CacheConfig   , requestsInFlight :: STM.TVar Int   , entries          :: STM.TVar (M.Map k (STM.TVar (Maybe v)))-  , evictionQueue    :: STM.TVar (PQ.PriorityQueue Int k)+  , evictionQueue    :: STM.TVar (PQ.PQueue Int k)   , evictionPriority :: STM.TVar Int   , occupancy        :: STM.TVar Int   , retrieve         :: k -> IO v
test/Arbor/LruCache/Internal/PriorityQueueSpec.hs view
@@ -10,7 +10,7 @@ spec :: Spec spec = describe "Arbor.LruCache.Internal.PriorityQueueSpec" $ do   it "Insertion dedupes by value" $ requireTest $ do-    let actual = (PQ.empty :: PQ.PriorityQueue Int Int)+    let actual = (PQ.empty :: PQ.PQueue Int Int)           & PQ.insert 1 101           & PQ.insert 3 101           & PQ.insert 2 101@@ -19,7 +19,7 @@      PQ.toList actual === expected   it "Insert stores all non-duplicate values" $ requireTest $ do-    let actual = (PQ.empty :: PQ.PriorityQueue Int Int)+    let actual = (PQ.empty :: PQ.PQueue Int Int)           & PQ.insert 1 101           & PQ.insert 3 303           & PQ.insert 2 202@@ -28,7 +28,7 @@      PQ.toList actual === expected   it "Take removes most priority element from queue" $ requireTest $ do-    let actual = (PQ.empty :: PQ.PriorityQueue Int Int)+    let actual = (PQ.empty :: PQ.PQueue Int Int)           & PQ.insert 1 101           & PQ.insert 3 303           & PQ.insert 2 202@@ -38,7 +38,7 @@      PQ.toList actual === expected   it "Take yields most priority element from queue" $ requireTest $ do-    let actual = (PQ.empty :: PQ.PriorityQueue Int Int)+    let actual = (PQ.empty :: PQ.PQueue Int Int)           & PQ.insert 1 101           & PQ.insert 3 303           & PQ.insert 2 202
test/Arbor/LruCache/LruCacheSpec.hs view
@@ -46,8 +46,8 @@ retrieve :: TVar [Event] -> Int -> IO String retrieve th mk = do   let mv = show mk-  atomically $ modifyTVar th (RetrieveEvent mk mv:)+  atomically $ modifyTVar' th (RetrieveEvent mk mv:)   return mv  evict :: TVar [Event] -> Int -> String -> IO ()-evict th mk mv = atomically $ modifyTVar th (EvictEvent mk mv:)+evict th mk mv = atomically $ modifyTVar' th (EvictEvent mk mv:)