combobuffer 0.1 → 0.2
raw patch · 3 files changed
+99/−2 lines, 3 filesdep ~template-haskellPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: template-haskell
API changes (from Hackage documentation)
+ Data.RingBuffer.Vector: data VBuffer el
+ Data.RingBuffer.Vector: instance (Eq el, Unbox el) => Eq (VBuffer el)
+ Data.RingBuffer.Vector: instance Unbox el => Initializable (VBuffer el)
+ Data.RingBuffer.Vector: instance Unbox el => RingBuffer (VBuffer el)
Files
- combobuffer.cabal +3/−2
- src/Data/RingBuffer/TGen.hs +5/−0
- src/Data/RingBuffer/Vector.hs +91/−0
combobuffer.cabal view
@@ -1,5 +1,5 @@ Name: combobuffer-Version: 0.1+Version: 0.2 Synopsis: Various buffer implementations Description: Various buffer implementations Homepage: https://github.com/JohnLato/combobuffer@@ -21,10 +21,11 @@ ,Data.RingBuffer.SeqBuffer ,Data.RingBuffer.SVec ,Data.RingBuffer.TGen+ ,Data.RingBuffer.Vector Build-depends: base >= 3 && < 5 ,containers >= 0.3 && < 0.6- ,template-haskell >= 2.6 && < 2.9+ ,template-haskell -- ,type-level >= 0.2 && < 0.3 -- ,tuple >= 0.2 && < 0.3 ,vector >= 0.5 && < 0.11
src/Data/RingBuffer/TGen.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}@@ -38,7 +39,11 @@ let fields = replicate sz (IsStrict, elname) in return [DataD [] nm binders [NormalC nm fields] []] +#if MIN_VERSION_template_haskell(2,9,0)+mkElInst tname elname = return [TySynInstD ''El $ TySynEqn [tname] (elname) ]+#else mkElInst tname elname = return [TySynInstD ''El [tname] (elname) ]+#endif mkInitInst vsz nm tname = let nmStr = show nm in [d| instance Initializable $(tname) where {-# INLINE newInit #-}; newInit el sz | sz >= 0 && sz <= vsz = $(appsE $ conE nm:replicate vsz [| el |]) ; newInit el sz = error ("cannot initialize " ++ nmStr ++ " with size: " ++ show sz) |]
+ src/Data/RingBuffer/Vector.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}++{-# OPTIONS_GHC -Wall -funbox-strict-fields #-}++-- | A vector-based 'RingBuffer'implementation+module Data.RingBuffer.Vector (+ VBuffer+)++where++import Prelude hiding (length)++import qualified Data.Vector.Unboxed as V+import qualified Data.Vector.Unboxed.Mutable as VM+import Control.Exception+import Control.Monad+import Data.IORef+import System.IO.Unsafe (unsafePerformIO)++import Data.RingBuffer.Class++data VBuffer el = VBuffer+ { size :: !Int+ , offset :: !Int+ , fullBuffer :: !(V.Vector el)+ , partial :: !(V.Vector el)+ , stale :: IORef Bool+ } deriving (Eq)++{-+class RingBuffer c where+ length :: c -> Int+ push :: c -> El c -> c+ (!) :: c -> Int -> El c+ slice :: c -> Int -> Int -> [El c]+ {-# INLINE slice #-}+ slice c start num = [ c ! ix | ix <- [start .. start+num]]+-}++type instance El (VBuffer el) = el++instance V.Unbox el => Initializable (VBuffer el) where+ {-# INLINE newInit #-}+ newInit val size = unsafePerformIO $ do+ -- we need to make sure that the two vectors aren't shared, and CSE may+ -- common them up if we just do (V.replicate size val)+ fullBuffer <- V.unsafeFreeze =<< VM.replicate size val+ partial <- V.unsafeFreeze =<< VM.replicate size val+ stale <- newIORef False+ let offset = 0+ return $ VBuffer { size, offset, fullBuffer, partial, stale }++instance V.Unbox el => RingBuffer (VBuffer el) where+ {-# INLINE length #-}+ length = size+ {-# INLINE (!) #-}+ (!) = index+ {-# INLINE push #-}+ push = pushBuf+ -- {-# INLINE slice #-}+ -- slice vec start num = V.toList $ V.slice start num vec++index :: (V.Unbox el) => VBuffer el -> Int -> el+index VBuffer{..} ix =+ if ix < offset+ then partial `V.unsafeIndex` ((offset-ix)-1)+ else fullBuffer `V.unsafeIndex` (size + offset - ix - 1)++pushBuf :: (V.Unbox el) => VBuffer el -> el -> VBuffer el+pushBuf VBuffer{..} el = unsafePerformIO $ do+ isStale <- atomicModifyIORef stale (True,)+ when isStale (throwIO $ ErrorCall "VBuffer: attempt to push to stale buffer")+ if offset < size+ then do+ v <- V.unsafeThaw partial+ VM.unsafeWrite v offset el+ newPartial <- V.unsafeFreeze v+ stale' <- newIORef False+ return $ VBuffer { size, offset=offset+1, fullBuffer+ , partial=newPartial+ , stale=stale' }+ else do+ stale' <- newIORef False+ return $ VBuffer { size, offset=1+ , fullBuffer=partial+ , partial = V.replicate size el+ , stale = stale'}