atomic-counter 0.1.2.1 → 0.1.2.2
raw patch · 10 files changed
+94/−32 lines, 10 filesdep ~basePVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Control.Concurrent.Counter: add :: Counter -> Int -> IO Int
+ Control.Concurrent.Counter: and :: Counter -> Int -> IO Int
+ Control.Concurrent.Counter: cas :: Counter -> Int -> Int -> IO Int
+ Control.Concurrent.Counter: data Counter
+ Control.Concurrent.Counter: get :: Counter -> IO Int
+ Control.Concurrent.Counter: nand :: Counter -> Int -> IO Int
+ Control.Concurrent.Counter: new :: Int -> IO Counter
+ Control.Concurrent.Counter: or :: Counter -> Int -> IO Int
+ Control.Concurrent.Counter: set :: Counter -> Int -> IO ()
+ Control.Concurrent.Counter: sub :: Counter -> Int -> IO Int
+ Control.Concurrent.Counter: xor :: Counter -> Int -> IO Int
Files
- Changelog.md +6/−0
- Counter.cmm +4/−1
- Readme.md +12/−5
- atomic-counter.cabal +29/−8
- bench/BenchMain.hs +2/−3
- src/Control/Concurrent/Counter.hs +21/−1
- src/Control/Concurrent/Counter/Lifted/IO.hs +2/−4
- src/Control/Concurrent/Counter/Lifted/ST.hs +3/−5
- src/Control/Concurrent/Counter/Unlifted.hs +13/−2
- test/TestMain.hs +2/−3
Changelog.md view
@@ -1,3 +1,9 @@+# 0.1.2.2++- Lower minimum supported GHC to 8.6 and base to 4.12+- Improve generated documentation+- Faster `stg_newCounterzh`+ # 0.1.2.1 - Disable cmm on 32 bit x86 architecture
Counter.cmm view
@@ -1,5 +1,7 @@ #include "Cmm.h" +#define SIZEOF_StgCounter (SIZEOF_StgHeader + WDS(1))+ INFO_TABLE(stg_Counter, 0, 1, MUT_PRIM, "Counter", "Counter") () { foreign "C" barf("stg_Counter entered!", NULL) never returns;@@ -8,7 +10,8 @@ stg_newCounterzh (W_ x) { P_ c;- ("ptr" c) = ccall allocate(MyCapability() "ptr", BYTES_TO_WDS(SIZEOF_StgHeader + WDS(1)));+ ALLOC_PRIM_N (SIZEOF_StgCounter, stg_newCounterzh, x);+ c = Hp - SIZEOF_StgCounter + WDS(1); SET_HDR(c, stg_Counter_info, CCCS); W_[c + SIZEOF_StgHeader] = x; return (c);
Readme.md view
@@ -28,6 +28,9 @@ setting where it does seem like a clear winner (please see benchmarks below). +Still even is single-threaded scenario the `Counter` can serve as an+efficient mutable integer cell that does not box the integer.+ # Benchmark ### Summary@@ -720,8 +723,12 @@ # Memory overhead -Each unlifted value of type `Counter` is a singleton mutable array-from GHC primitives under the hood. Thus it occupies at least-`platform integer size` + `array size` + `header` bytes which should-typically be at least 3 machine words. Lifted values may occupy more-depending on optimizations.+In pure Haskell (i.e. with `no-cmm` flag enabled) each unlifted value of+type `Counter` is a singleton mutable array from GHC primitives under+the hood. Thus it occupies at least `platform integer size` + `array+size` + `header` bytes which should typically be at least 3 machine+words. Lifted values may occupy more depending on optimizations.++By default CMM will be enabled which should save one word of overhead+because there would be no array any more hence no need to store+trivial size.
atomic-counter.cabal view
@@ -5,7 +5,7 @@ name: atomic-counter version:- 0.1.2.1+ 0.1.2.2 synopsis: Mutable counters that can be modified with atomic operatinos @@ -31,6 +31,16 @@ category: Concurrency, Data, Data Structures +tested-with:+ GHC == 8.6,+ GHC == 8.8,+ GHC == 8.10,+ GHC == 9.2,+ GHC == 9.4,+ GHC == 9.6,+ GHC == 9.8,+ GHC == 9.10+ build-type: Simple @@ -74,7 +84,6 @@ -Wno-missed-specialisations -Wno-missing-import-lists -Wno-missing-local-signatures- -Wno-missing-safe-haskell-mode -Wno-safe -Wno-type-defaults -Wno-unsafe@@ -83,10 +92,20 @@ ghc-options: -Wno-missing-deriving-strategies + if impl(ghc >= 8.10)+ ghc-options:+ -Wno-missing-safe-haskell-mode+ -Wno-prepositive-qualified-module+ if impl(ghc >= 9.2) ghc-options: -Wno-missing-kind-signatures + if impl(ghc >= 9.8)+ ghc-options:+ -Wno-missing-role-annotations+ -Wno-missing-poly-kind-signatures+ library import: ghc-options exposed-modules:@@ -97,7 +116,7 @@ hs-source-dirs: src build-depends:- , base >= 4.14 && < 5+ , base >= 4.12 && < 5 if impl(ghc >= 9.4) && !arch(javascript) && !arch(i386) && !flag(no-cmm) cmm-sources: Counter.cmm@@ -109,6 +128,8 @@ library test-utils import: ghc-options+ visibility:+ private exposed-modules: TestUtils hs-source-dirs:@@ -116,7 +137,7 @@ build-depends: , QuickCheck , async >= 2- , base >= 4.14+ , base >= 4.12 && < 5 test-suite test import: ghc-options@@ -129,10 +150,10 @@ build-depends: , QuickCheck , atomic-counter- , base >= 4.14+ , base >= 4.12 , tasty , tasty-quickcheck- , test-utils+ , atomic-counter:test-utils ghc-options: -rtsopts -threaded@@ -150,13 +171,13 @@ build-depends: , QuickCheck , atomic-counter- , base >= 4.14+ , base >= 4.12 , primitive , stm , tasty >= 1.4.2 , tasty-bench >= 0.3.4 , tasty-quickcheck- , test-utils+ , atomic-counter:test-utils ghc-options: -rtsopts -threaded
bench/BenchMain.hs view
@@ -8,7 +8,6 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}-{-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE UnboxedTuples #-}@@ -27,9 +26,9 @@ import Test.Tasty hiding (defaultMain) import Test.Tasty.Bench import Test.Tasty.Patterns.Printer-import Test.Tasty.QuickCheck qualified as QC+import qualified Test.Tasty.QuickCheck as QC -import Control.Concurrent.Counter.Lifted.IO qualified as C+import qualified Control.Concurrent.Counter.Lifted.IO as C import TestUtils
src/Control/Concurrent/Counter.hs view
@@ -10,7 +10,27 @@ ---------------------------------------------------------------------------- module Control.Concurrent.Counter- ( module Control.Concurrent.Counter.Lifted.IO+ ( Counter++ -- * Create+ , new++ -- * Read/write+ , get+ , set+ , cas++ -- * Arithmetic operations+ , add+ , sub++ -- * Bitwise operations+ , and+ , or+ , xor+ , nand ) where++import Prelude hiding (and, or) import Control.Concurrent.Counter.Lifted.IO
src/Control/Concurrent/Counter/Lifted/IO.hs view
@@ -9,8 +9,7 @@ -- operate in the 'IO' monad. ---------------------------------------------------------------------------- -{-# LANGUAGE ImportQualifiedPost #-}-{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeApplications #-} module Control.Concurrent.Counter.Lifted.IO ( Counter@@ -41,8 +40,7 @@ import GHC.IO import GHC.ST -import Control.Concurrent.Counter.Lifted.ST qualified as Lifted-+import qualified Control.Concurrent.Counter.Lifted.ST as Lifted -- | Memory location that supports select few atomic operations. --
src/Control/Concurrent/Counter/Lifted/ST.hs view
@@ -10,9 +10,8 @@ -- same operation (terms and conditions apply). ---------------------------------------------------------------------------- -{-# LANGUAGE ImportQualifiedPost #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-} module Control.Concurrent.Counter.Lifted.ST ( Counter@@ -41,8 +40,7 @@ import GHC.Exts (Int(..), Int#, State#) import GHC.ST -import Control.Concurrent.Counter.Unlifted qualified as Unlifted-+import qualified Control.Concurrent.Counter.Unlifted as Unlifted -- | Memory location that supports select few atomic operations. --
src/Control/Concurrent/Counter/Unlifted.hs view
@@ -22,8 +22,11 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE UnliftedFFITypes #-}-{-# LANGUAGE UnliftedNewtypes #-} +#if __GLASGOW_HASKELL__ >= 810+{-# LANGUAGE UnliftedNewtypes #-}+#endif+ module Control.Concurrent.Counter.Unlifted ( Counter @@ -113,10 +116,18 @@ sameCounter (Counter x) (Counter y) = isTrue# (reallyUnsafePtrEquality# x y) -#else+#endif +#if !(defined(USE_CMM) && SIZEOF_HSINT == 8)+ -- | Memory location that supports select few atomic operations.+#if __GLASGOW_HASKELL__ >= 810 newtype Counter s = Counter (MutableByteArray# s)+#endif++#if !(__GLASGOW_HASKELL__ >= 810)+data Counter s = Counter (MutableByteArray# s)+#endif {-# INLINE new #-} -- | Create new counter with initial value.
test/TestMain.hs view
@@ -7,7 +7,6 @@ ---------------------------------------------------------------------------- {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE NamedFieldPuns #-} module TestMain (main) where@@ -18,9 +17,9 @@ import Data.Semigroup import Test.QuickCheck import Test.Tasty-import Test.Tasty.QuickCheck qualified as QC+import qualified Test.Tasty.QuickCheck as QC -import Control.Concurrent.Counter.Lifted.IO qualified as C+import qualified Control.Concurrent.Counter.Lifted.IO as C import TestUtils