SafeHaskell: Added SafeHaskell to base
[ghc.git] / libraries / base / Data / Unique.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE CPP #-}
3
4 #ifdef __GLASGOW_HASKELL__
5 {-# LANGUAGE MagicHash, DeriveDataTypeable #-}
6 #endif
7
8 -----------------------------------------------------------------------------
9 -- |
10 -- Module : Data.Unique
11 -- Copyright : (c) The University of Glasgow 2001
12 -- License : BSD-style (see the file libraries/base/LICENSE)
13 --
14 -- Maintainer : libraries@haskell.org
15 -- Stability : experimental
16 -- Portability : non-portable
17 --
18 -- An abstract interface to a unique symbol generator.
19 --
20 -----------------------------------------------------------------------------
21
22 module Data.Unique (
23 -- * Unique objects
24 Unique, -- instance (Eq, Ord)
25 newUnique, -- :: IO Unique
26 hashUnique -- :: Unique -> Int
27 ) where
28
29 import Prelude
30
31 import System.IO.Unsafe (unsafePerformIO)
32
33 #ifdef __GLASGOW_HASKELL__
34 import GHC.Base
35 import GHC.Num
36 import GHC.Conc
37 import Data.Typeable
38 #endif
39
40 -- | An abstract unique object. Objects of type 'Unique' may be
41 -- compared for equality and ordering and hashed into 'Int'.
42 newtype Unique = Unique Integer deriving (Eq,Ord
43 #ifdef __GLASGOW_HASKELL__
44 ,Typeable
45 #endif
46 )
47
48 uniqSource :: TVar Integer
49 uniqSource = unsafePerformIO (newTVarIO 0)
50 {-# NOINLINE uniqSource #-}
51
52 -- | Creates a new object of type 'Unique'. The value returned will
53 -- not compare equal to any other value of type 'Unique' returned by
54 -- previous calls to 'newUnique'. There is no limit on the number of
55 -- times 'newUnique' may be called.
56 newUnique :: IO Unique
57 newUnique = atomically $ do
58 val <- readTVar uniqSource
59 let next = val+1
60 writeTVar uniqSource $! next
61 return (Unique next)
62
63 -- SDM (18/3/2010): changed from MVar to STM. This fixes
64 -- 1. there was no async exception protection
65 -- 2. there was a space leak (now new value is strict)
66 -- 3. using atomicModifyIORef would be slightly quicker, but can
67 -- suffer from adverse scheduling issues (see #3838)
68 -- 4. also, the STM version is faster.
69
70 -- | Hashes a 'Unique' into an 'Int'. Two 'Unique's may hash to the
71 -- same value, although in practice this is unlikely. The 'Int'
72 -- returned makes a good hash key.
73 hashUnique :: Unique -> Int
74 #if defined(__GLASGOW_HASKELL__)
75 hashUnique (Unique i) = I# (hashInteger i)
76 #else
77 hashUnique (Unique u) = fromInteger (u `mod` (toInteger (maxBound :: Int) + 1))
78 #endif