packages feed

atomic-primops-foreign (empty) → 0.6

raw patch · 5 files changed

+171/−0 lines, 5 filesdep +HUnitdep +basedep +bits-atomicsetup-changed

Dependencies added: HUnit, base, bits-atomic, test-framework, test-framework-hunit, time

Files

+ Data/Atomics/Counter/Foreign.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE BangPatterns #-}++-- | This implementation stores an unboxed counter and uses FFI operations to modify+-- its contents.  It has the advantage that it can use true fetch-and-add operations.+-- It has the disadvantage of extra overhead due to FFI calls.+--+-- For more documentation, see the module "Data.Atomics.Counter", which exports+-- the same interface as this module.++module Data.Atomics.Counter.Foreign+       (AtomicCounter, CTicket,+        newCounter, readCounterForCAS, readCounter, peekCTicket,+        writeCounter, casCounter, incrCounter, incrCounter_)+   where+import Control.Monad (void)+import Data.Bits.Atomic+import Foreign.ForeignPtr+import Foreign.Storable++-- | The type of mutable atomic counters.+type AtomicCounter = ForeignPtr Int++-- | You should not depend on this type.  It varies between different implementations+-- of atomic counters.+type CTicket = Int++{-# INLINE newCounter #-}+-- | Create a new counter initialized to the given value.+newCounter :: Int -> IO AtomicCounter+newCounter n = do x <- mallocForeignPtr+                  writeCounter x n+                  -- Do we need a write barrier here?+                  return x++{-# INLINE incrCounter #-}+-- | Increment the counter by a given amount.+--   Returns the original value before the increment.+--                 +--   Note that UNLIKE with boxed implementations of counters, where increment is+--   based on CAS, this increment is /O(1)/.  Fetch-and-add does not require a retry+--   loop like CAS.+incrCounter :: Int -> AtomicCounter -> IO Int+incrCounter bump r = withForeignPtr r$ \r' -> addAndFetch r' bump++{-# INLINE incrCounter_ #-}+-- | An alternate version for when you don't care about the old value.+incrCounter_ :: Int -> AtomicCounter -> IO ()+incrCounter_ bump r = withForeignPtr r$ \r' -> void (addAndFetch r' bump)++{-# INLINE readCounterForCAS #-}+-- | Just like the "Data.Atomics" CAS interface, this routine returns an opaque+-- ticket that can be used in CAS operations.+readCounterForCAS :: AtomicCounter -> IO CTicket+readCounterForCAS = readCounter++{-# INLINE peekCTicket #-}+-- | Opaque tickets cannot be constructed, but they can be destructed into values.+peekCTicket :: CTicket -> Int+peekCTicket x = x++{-# INLINE readCounter #-}+-- | Equivalent to `readCounterForCAS` followed by `peekCTicket`.+readCounter :: AtomicCounter -> IO Int+readCounter r = withForeignPtr r peek ++{-# INLINE writeCounter #-}+-- | Make a non-atomic write to the counter.  No memory-barrier.+writeCounter :: AtomicCounter -> Int -> IO ()+writeCounter r !new = withForeignPtr r $ \r' -> poke r' new++{-# INLINE casCounter #-}+-- | Compare and swap for the counter ADT.+casCounter :: AtomicCounter -> CTicket -> Int -> IO (Bool, CTicket)+casCounter r !tick !new = withForeignPtr r $ \r' -> do+   cur <- compareAndSwap r' tick new+   if cur==tick +     then return (True,new)+     else return (False,cur)+--   return (b==tick, b)
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2012-2013, Ryan R. Newton++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Ryan R. Newton nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ atomic-primops-foreign.cabal view
@@ -0,0 +1,42 @@+Name:                atomic-primops-foreign+Version:             0.6+License:             BSD3+License-file:        LICENSE+Author:              Ryan Newton+Maintainer:          rrnewton@gmail.com+Category:            Data+Build-type:          Simple+Cabal-version:       >=1.8+HomePage: https://github.com/rrnewton/haskell-lockfree/wiki+Bug-Reports: https://github.com/rrnewton/haskell-lockfree/issues++-- 0.6 -- Factored out of parent module to separate dependencies.++Synopsis: An atomic counter implemented using the FFI.+Description:++Library+  exposed-modules: Data.Atomics.Counter.Foreign+  ghc-options: -O2 -funbox-strict-fields+  build-depends: bits-atomic >= 0.1.3++  -- This can go back further than the atomic-primops package in supporting old GHC's:+  -- For now let's say GHC 7.0 through 7.8:+  build-depends: base >= 4.3.0.0 && <= 4.7.0.0+  CC-Options:       -Wall ++Test-Suite test-atomic-primops-foreign+    type:       exitcode-stdio-1.0+    main-is: testing/Main.hs+    hs-source-dirs: testing/ ./++    ghc-options: -threaded -rtsopts -with-rtsopts=-N4+    build-depends: bits-atomic+    build-depends: base >= 4.3.0.0 && <= 4.7.0.0, +                   -- For Testing:+                   time, HUnit, test-framework, test-framework-hunit++Source-Repository head+    Type:         git+    Location:     git://github.com/rrnewton/haskell-lockfree.git+    Subdir:       atomic-primops-foreign/
+ testing/Main.hs view
@@ -0,0 +1,18 @@++module Main where++import GHC.Conc+import Test.Framework  (Test, defaultMain, testGroup)+import qualified CounterForeign+import Control.Monad (when)++----------------------------------------++main :: IO ()+main = do+       -- TEMP: Fixing this at four processors because it takes a REALLY long time at larger numbers:+       -- It does 248 test cases and takes 55s at -N16...+       -- numcap <- getNumProcessors+       let numcap = 4+       when (numCapabilities /= numcap) $ setNumCapabilities numcap+       defaultMain CounterForeign.tests