X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Data%2FUnique.hs;h=c4c882743301bd1cd43acd74db055010fdafe978;hb=HEAD;hp=1c1ceb88eef52e2943acb87279adf79525d09ba6;hpb=8cfaaa32cdd732188a101cd813c389c601ca2e6b;p=ghc-base.git diff --git a/Data/Unique.hs b/Data/Unique.hs index 1c1ceb8..c4c8827 100644 --- a/Data/Unique.hs +++ b/Data/Unique.hs @@ -1,3 +1,9 @@ +{-# LANGUAGE CPP #-} + +#ifdef __GLASGOW_HASKELL__ +{-# LANGUAGE MagicHash, DeriveDataTypeable #-} +#endif + ----------------------------------------------------------------------------- -- | -- Module : Data.Unique @@ -14,27 +20,32 @@ module Data.Unique ( -- * Unique objects - Unique, -- instance (Eq, Ord) - newUnique, -- :: IO Unique - hashUnique -- :: Unique -> Int + Unique, -- instance (Eq, Ord) + newUnique, -- :: IO Unique + hashUnique -- :: Unique -> Int ) where import Prelude -import Control.Concurrent.MVar import System.IO.Unsafe (unsafePerformIO) #ifdef __GLASGOW_HASKELL__ import GHC.Base -import GHC.Num ( Integer(..) ) +import GHC.Num +import GHC.Conc +import Data.Typeable #endif -- | An abstract unique object. Objects of type 'Unique' may be -- compared for equality and ordering and hashed into 'Int'. -newtype Unique = Unique Integer deriving (Eq,Ord) +newtype Unique = Unique Integer deriving (Eq,Ord +#ifdef __GLASGOW_HASKELL__ + ,Typeable +#endif + ) -uniqSource :: MVar Integer -uniqSource = unsafePerformIO (newMVar 0) +uniqSource :: TVar Integer +uniqSource = unsafePerformIO (newTVarIO 0) {-# NOINLINE uniqSource #-} -- | Creates a new object of type 'Unique'. The value returned will @@ -42,20 +53,25 @@ uniqSource = unsafePerformIO (newMVar 0) -- previous calls to 'newUnique'. There is no limit on the number of -- times 'newUnique' may be called. newUnique :: IO Unique -newUnique = do - val <- takeMVar uniqSource - let next = val+1 - putMVar uniqSource next - return (Unique next) +newUnique = atomically $ do + val <- readTVar uniqSource + let next = val+1 + writeTVar uniqSource $! next + return (Unique next) + +-- SDM (18/3/2010): changed from MVar to STM. This fixes +-- 1. there was no async exception protection +-- 2. there was a space leak (now new value is strict) +-- 3. using atomicModifyIORef would be slightly quicker, but can +-- suffer from adverse scheduling issues (see #3838) +-- 4. also, the STM version is faster. -- | Hashes a 'Unique' into an 'Int'. Two 'Unique's may hash to the -- same value, although in practice this is unlikely. The 'Int' -- returned makes a good hash key. hashUnique :: Unique -> Int -#ifdef __GLASGOW_HASKELL__ -hashUnique (Unique (S# i)) = I# i -hashUnique (Unique (J# s d)) | s ==# 0# = 0 - | otherwise = I# (indexIntArray# d 0#) +#if defined(__GLASGOW_HASKELL__) +hashUnique (Unique i) = I# (hashInteger i) #else hashUnique (Unique u) = fromInteger (u `mod` (toInteger (maxBound :: Int) + 1)) #endif