Typo
[packages/base.git] / Data / Unique.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE MagicHash, DeriveDataTypeable #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module : Data.Unique
7 -- Copyright : (c) The University of Glasgow 2001
8 -- License : BSD-style (see the file libraries/base/LICENSE)
9 --
10 -- Maintainer : libraries@haskell.org
11 -- Stability : experimental
12 -- Portability : non-portable
13 --
14 -- An abstract interface to a unique symbol generator.
15 --
16 -----------------------------------------------------------------------------
17
18 module Data.Unique (
19 -- * Unique objects
20 Unique,
21 newUnique,
22 hashUnique
23 ) where
24
25 import Prelude
26
27 import System.IO.Unsafe (unsafePerformIO)
28
29 import GHC.Base
30 import GHC.Num
31 import Data.Typeable
32 import Data.IORef
33
34 -- | An abstract unique object. Objects of type 'Unique' may be
35 -- compared for equality and ordering and hashed into 'Int'.
36 newtype Unique = Unique Integer deriving (Eq,Ord,Typeable)
37
38 uniqSource :: IORef Integer
39 uniqSource = unsafePerformIO (newIORef 0)
40 {-# NOINLINE uniqSource #-}
41
42 -- | Creates a new object of type 'Unique'. The value returned will
43 -- not compare equal to any other value of type 'Unique' returned by
44 -- previous calls to 'newUnique'. There is no limit on the number of
45 -- times 'newUnique' may be called.
46 newUnique :: IO Unique
47 newUnique = do
48 r <- atomicModifyIORef' uniqSource $ \x -> let z = x+1 in (z,z)
49 return (Unique r)
50
51 -- SDM (18/3/2010): changed from MVar to STM. This fixes
52 -- 1. there was no async exception protection
53 -- 2. there was a space leak (now new value is strict)
54 -- 3. using atomicModifyIORef would be slightly quicker, but can
55 -- suffer from adverse scheduling issues (see #3838)
56 -- 4. also, the STM version is faster.
57
58 -- SDM (30/4/2012): changed to IORef using atomicModifyIORef. Reasons:
59 -- 1. STM version could not be used inside unsafePerformIO, if it
60 -- happened to be poked inside an STM transaction.
61 -- 2. IORef version can be used with unsafeIOToSTM inside STM,
62 -- because if the transaction retries then we just get a new
63 -- Unique.
64 -- 3. IORef version is very slightly faster.
65
66 -- IGL (08/06/2013): changed to using atomicModifyIORef' instead.
67 -- This feels a little safer, from the point of view of not leaking
68 -- memory, but the resulting core is identical.
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 hashUnique (Unique i) = I# (hashInteger i)