From fcf1a95395777c7335f3313795d3495abf29b921 Mon Sep 17 00:00:00 2001 From: Ross Paterson <ross@soi.city.ac.uk> Date: Tue, 13 Jun 2006 14:27:51 +0000 Subject: [PATCH] offer a subset of the interface to sequential implementations --- Control/Concurrent/STM.hs | 21 +++++++++++- Control/Concurrent/STM/TArray.hs | 4 +++ Control/Concurrent/STM/TVar.hs | 5 ++- Control/Sequential/STM.hs | 59 ++++++++++++++++++++++++++++++++ LICENSE | 31 +++++++++++++++++ Makefile | 2 +- stm.cabal | 16 +++++++++ 7 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 Control/Sequential/STM.hs create mode 100644 LICENSE create mode 100644 stm.cabal diff --git a/Control/Concurrent/STM.hs b/Control/Concurrent/STM.hs index 1c9d623..31281b3 100644 --- a/Control/Concurrent/STM.hs +++ b/Control/Concurrent/STM.hs @@ -9,7 +9,12 @@ -- Portability : non-portable (requires STM) -- -- Software Transactional Memory: a modular composable concurrency --- abstraction. +-- abstraction. See +-- +-- * /Composable memory transactions/, by Tim Harris, Simon Marlow, Simon +-- Peyton Jones, and Maurice Herlihy, in /ACM Conference on Principles +-- and Practice of Parallel Programming/ 2005. +-- <http://research.microsoft.com/Users/simonpj/papers/stm/index.htm> -- ----------------------------------------------------------------------------- @@ -17,35 +22,49 @@ module Control.Concurrent.STM ( -- * The STM monad and basic operations STM, atomically, +#ifdef __GLASGOW_HASKELL__ retry, orElse, check, +#endif catchSTM, +#ifdef __GLASGOW_HASKELL__ registerDelay, +#endif -- * TVars module Control.Concurrent.STM.TVar, +#ifdef __GLASGOW_HASKELL__ -- * TMVars module Control.Concurrent.STM.TMVar, -- * TChan module Control.Concurrent.STM.TChan, +#endif -- * TArray module Control.Concurrent.STM.TArray ) where +#ifdef __GLASGOW_HASKELL__ import GHC.Conc import Control.Monad ( MonadPlus(..) ) +#else +import Control.Sequential.STM +#endif import Control.Concurrent.STM.TVar +#ifdef __GLASGOW_HASKELL__ import Control.Concurrent.STM.TMVar import Control.Concurrent.STM.TChan +#endif import Control.Concurrent.STM.TArray +#ifdef __GLASGOW_HASKELL__ instance MonadPlus STM where mzero = retry mplus = orElse check :: Bool -> STM a check b = if b then return undefined else retry +#endif diff --git a/Control/Concurrent/STM/TArray.hs b/Control/Concurrent/STM/TArray.hs index f4f6538..709806a 100644 --- a/Control/Concurrent/STM/TArray.hs +++ b/Control/Concurrent/STM/TArray.hs @@ -22,7 +22,11 @@ import Data.Array (Array) import Data.Array.Base (listArray, arrEleBottom, unsafeAt, MArray(..), HasBounds(..)) import Data.Ix (rangeSize) import Control.Concurrent.STM.TVar (TVar, newTVar, readTVar, writeTVar) +#ifdef __GLASGOW_HASKELL__ import GHC.Conc (STM) +#else +import Control.Sequential.STM (STM) +#endif -- |TArray is a transactional array, supporting the usual 'MArray' -- interface for mutable arrays. diff --git a/Control/Concurrent/STM/TVar.hs b/Control/Concurrent/STM/TVar.hs index b8b7ad9..ee9734e 100644 --- a/Control/Concurrent/STM/TVar.hs +++ b/Control/Concurrent/STM/TVar.hs @@ -21,5 +21,8 @@ module Control.Concurrent.STM.TVar ( newTVarIO ) where +#ifdef __GLASGOW_HASKELL__ import GHC.Conc - +#else +import Control.Sequential.STM +#endif diff --git a/Control/Sequential/STM.hs b/Control/Sequential/STM.hs new file mode 100644 index 0000000..9ce7fa0 --- /dev/null +++ b/Control/Sequential/STM.hs @@ -0,0 +1,59 @@ +-- Transactional memory for sequential implementations. +-- Transactions do not run concurrently, but are atomic in the face +-- of exceptions. + +-- #hide +module Control.Sequential.STM ( + STM, atomically, catchSTM, + TVar, newTVar, newTVarIO, readTVar, writeTVar + ) where + +import Prelude hiding (catch) +import Control.Exception +import Data.IORef + +-- The reference contains a rollback action to be executed on exceptions +newtype STM a = STM (IORef (IO ()) -> IO a) + +unSTM :: STM a -> IORef (IO ()) -> IO a +unSTM (STM f) = f + +instance Functor STM where + fmap f (STM m) = STM (fmap f . m) + +instance Monad STM where + return x = STM (const (return x)) + STM m >>= k = STM $ \ r -> do + x <- m r + unSTM (k x) r + +atomically :: STM a -> IO a +atomically (STM m) = do + r <- newIORef (return ()) + m r `catch` \ ex -> do + rollback <- readIORef r + rollback + throw ex + +catchSTM :: STM a -> (Exception -> STM a) -> STM a +catchSTM (STM m) h = STM $ \ r -> m r `catch` \ ex -> unSTM (h ex) r + +newtype TVar a = TVar (IORef a) + deriving (Eq) + +newTVar :: a -> STM (TVar a) +newTVar a = STM (const (newTVarIO a)) + +newTVarIO :: a -> IO (TVar a) +newTVarIO a = do + ref <- newIORef a + return (TVar ref) + +readTVar :: TVar a -> STM a +readTVar (TVar ref) = STM (const (readIORef ref)) + +writeTVar :: TVar a -> a -> STM () +writeTVar (TVar ref) a = STM $ \ r -> do + oldval <- readIORef ref + modifyIORef r (writeIORef ref oldval >>) + writeIORef ref a diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4ec14bf --- /dev/null +++ b/LICENSE @@ -0,0 +1,31 @@ +The Glasgow Haskell Compiler License + +Copyright 2004, The University Court of the University of Glasgow. +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 name of the University nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF +GLASGOW AND THE 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 +UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE 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. diff --git a/Makefile b/Makefile index 79423e4..121d3de 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ PACKAGE = stm VERSION = 1.0 PACKAGE_DEPS = base -SRC_HC_OPTS += -fglasgow-exts +SRC_HC_OPTS += -fglasgow-exts -cpp SRC_HADDOCK_OPTS += -t "Haskell Hierarchical Libraries (stm package)" diff --git a/stm.cabal b/stm.cabal new file mode 100644 index 0000000..dde2a78 --- /dev/null +++ b/stm.cabal @@ -0,0 +1,16 @@ +name: stm +version: 1.0 +license: BSD3 +license-file: LICENSE +maintainer: libraries@haskell.org +synopsis: Software Transactional Memory +description: A modular composable concurrency abstraction. +-- these are the modules exposed by the cut-down non-GHC interface. +exposed-modules: + Control.Concurrent.STM + Control.Concurrent.STM.TArray + Control.Concurrent.STM.TVar +other-modules: + Control.Sequential.STM +build-depends: base +extensions: CPP -- GitLab