packages feed

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 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'}