ring-buffer 0.1.3 → 0.2.0
raw patch · 3 files changed
+55/−1 lines, 3 filesdep +QuickCheckdep +ring-bufferdep ~basedep ~vector
Dependencies added: QuickCheck, ring-buffer
Dependency ranges changed: base, vector
Files
- Properties.hs +16/−0
- ring-buffer.cabal +10/−1
- src/Data/RingBuffer.hs +29/−0
+ Properties.hs view
@@ -0,0 +1,16 @@+import Control.Monad.IO.Class+import Test.QuickCheck+import Test.QuickCheck.Monadic+import qualified Data.RingBuffer as R+import qualified Data.Vector as V++testAppend :: (Eq a)+ => Positive Int -> [a] -> Property+testAppend (Positive cap) xs = monadicIO $ do+ r <- liftIO $ R.new cap :: PropertyM IO (R.RingBuffer V.Vector a)+ liftIO $ mapM_ (`R.append` r) (reverse xs)+ xs' <- liftIO $ R.toList r+ return $ xs' == take cap xs++main :: IO ()+main = quickCheck (testAppend :: Positive Int -> [Int] -> Property)
ring-buffer.cabal view
@@ -1,5 +1,5 @@ name: ring-buffer-version: 0.1.3+version: 0.2.0 synopsis: A concurrent, mutable ring-buffer description: A concurrent, mutable ring-buffer homepage: http://github.com/bgamari/ring-buffer@@ -24,3 +24,12 @@ primitive >=0.5 && <0.7 hs-source-dirs: src default-language: Haskell2010++test-suite properties+ type: exitcode-stdio-1.0+ main-is: Properties.hs+ default-language: Haskell2010+ build-depends: base >= 4.9,+ QuickCheck >= 2.7,+ vector >= 0.11,+ ring-buffer
src/Data/RingBuffer.hs view
@@ -8,6 +8,8 @@ , concat , capacity , length+ , latest+ , toList , withItems ) where @@ -49,8 +51,11 @@ put $ RingState (full || a > 0) pos' -- | Create a new ring of a given length+--+-- /Note:/ size must be non-zero new :: (VG.Vector v a) => Int -> IO (RingBuffer v a) new n = do+ when (n < 1) $ fail "Data.RingBuffer.new: invalid ring size" buffer <- VGM.new n state <- newMVar $ RingState False 0 return $ RingBuffer { ringBuffer=buffer, ringState=state }@@ -106,6 +111,30 @@ -- | The current filled length of the ring length :: (VG.Vector v a) => RingBuffer v a -> IO Int length rb = withRing rb length'++-- | Retrieve the $n$th most-recently added item of the ring+latest :: (VG.Vector v a) => RingBuffer v a -> Int -> IO (Maybe a)+latest rb n = withRing rb $ do+ len <- length'+ if n >= len+ then return Nothing+ else Just <$> latest' n++latest' :: (VGM.MVector v a, MonadIO m) => Int -> RingM m v a a+latest' n = do+ len <- length'+ cap <- capacity'+ when (n >= len) $ error "Data.RingBuffer.latest': invalid index"+ let idx = (cap + len - n - 1) `mod` cap+ buf <- ask+ liftIO $ VGM.unsafeRead buf idx++-- | Get the entire contents of the ring, with the most recently added element+-- at the head. Note that this is rather inefficient.+toList :: (VG.Vector v a) => RingBuffer v a -> IO [a]+toList rb = withRing rb $ do+ len <- length'+ mapM latest' [0..len-1] -- | Execute the given action with the items of the ring. -- Note that no references to the vector may leak out of the action as