global-variables 1.0 → 1.0.1.0
raw patch · 3 files changed
+67/−24 lines, 3 filesdep ~stmPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: stm
API changes (from Hackage documentation)
+ Data.Global: declareEmptyMVar :: Typeable a => String -> MVar a
- Data.Global: declareIORef :: Typeable a => String -> a -> (IORef a)
+ Data.Global: declareIORef :: Typeable a => String -> a -> IORef a
- Data.Global: declareMVar :: Typeable a => String -> a -> (MVar a)
+ Data.Global: declareMVar :: Typeable a => String -> a -> MVar a
- Data.Global: declareTVar :: Typeable a => String -> a -> (TVar a)
+ Data.Global: declareTVar :: Typeable a => String -> a -> TVar a
Files
- global-variables.cabal +9/−2
- src/Data/Global.hs +1/−0
- src/Data/Global/Registry.hs +57/−22
global-variables.cabal view
@@ -1,5 +1,5 @@ Name: global-variables-Version: 1.0+Version: 1.0.1.0 Synopsis: Namespaced, global, and top-level mutable variables without unsafePerformIO.@@ -33,6 +33,12 @@ extends their handling significantly. . Examples are in the documentation of "Data.Global".+ .+ Version History:+ .+ 1.0.1.0: added declareEmptyMVar and widened the stm dependency+ .+ 1.0: First public release License: BSD3 License-file: LICENSE@@ -46,6 +52,7 @@ Build-type: Simple +Tested-With: GHC == 7.0.4, GHC == 7.2.2 -- Extra files to be distributed with the package, such as examples or -- a README. -- Extra-source-files:@@ -58,7 +65,7 @@ Build-depends: base >= 4 && < 5 , containers >= 0.3 && < 0.5- , stm >= 2.1 && < 2.2+ , stm >= 2.1 && < 2.3 Other-modules: Data.Global.Registry
src/Data/Global.hs view
@@ -46,6 +46,7 @@ -- * Reference of Variable Declaration Functions declareIORef , declareMVar+ , declareEmptyMVar , declareTVar ) where
src/Data/Global/Registry.hs view
@@ -13,24 +13,27 @@ ----------------------------------------------------------------------------------------------- module Data.Global.Registry ( -- * Public Interface- declareIORef, declareMVar, declareTVar+ declareIORef, declareMVar, declareEmptyMVar, declareTVar -- * Private Testing Interface , lookupOrInsert , setupRegistry ) where +import Control.Concurrent.MVar ( MVar, newMVar, newEmptyMVar, modifyMVar ) #if __GLASGOW_HASKELL__ < 702+import Control.Concurrent.MVar ( takeMVar, putMVar )+#endif+import Control.Concurrent.STM ( TVar, newTVarIO )+#if __GLASGOW_HASKELL__ < 702 import Control.Exception ( evaluate ) #endif-import Control.Concurrent.MVar-import Control.Concurrent.STM import Data.IORef import Data.Dynamic import Data.Map as M-import GHC.Conc (pseq)+import GHC.Conc ( pseq )+import GHC.IO ( unsafePerformIO, unsafeDupablePerformIO ) -import System.IO.Unsafe #if __GLASGOW_HASKELL__ >= 702@@ -39,6 +42,8 @@ type Registry = Map (Int,Int,String) Dynamic #endif ++ -- | Test helper setupRegistry :: IO (MVar Registry) setupRegistry = m `pseq` newMVar m@@ -64,8 +69,8 @@ -> String -> a -> IO (ref a)-lookupOrInsert registry new name val- | registry `pseq` new `pseq` name `pseq` val `pseq` False = undefined+lookupOrInsert registry new name _+ | registry `pseq` new `pseq` name `pseq` False = undefined lookupOrInsert registry new name val = modifyMVar registry lkup where err ex got = error $ "Data.Global.Registry: Invariant violation\n"@@ -140,6 +145,18 @@ +lookupOrInsertEmptyMVar+ :: forall a. Typeable a+ => String+ -> IO (MVar a)+lookupOrInsertEmptyMVar name = lookupOrInsert globalRegistry newEmptyMVar' name (undefined :: a)+ where+ newEmptyMVar' :: a -> IO (MVar a)+ newEmptyMVar' _ = newEmptyMVar+{-# NOINLINE lookupOrInsertEmptyMVar #-}+++ lookupOrInsertTVar :: Typeable a => String@@ -161,11 +178,11 @@ -- pragma in order to define top-level 'IORef's. declareIORef :: Typeable a- => String -- ^ The identifying name- -> a -- ^ The initial value of the 'IORef', it may or may not be used.- -> (IORef a) -- ^ A unique 'IORef' determined by @(name, typeOf val)@. Whether it refers- -- to the given initial value or not is unspecified.-declareIORef name val = unsafePerformIO $ lookupOrInsertIORef name val+ => String -- ^ The identifying name+ -> a -- ^ The initial value of the 'IORef', it may or may not be used.+ -> IORef a -- ^ A unique 'IORef' determined by @(name, typeOf val)@. Whether it refers to+ -- the given initial value or not is unspecified.+declareIORef name val = unsafeDupablePerformIO $ lookupOrInsertIORef name val {-# NOINLINE declareIORef #-} @@ -182,15 +199,33 @@ -- pragma in order to define top-level 'MVar's. declareMVar :: Typeable a- => String -- ^ The identifying name- -> a -- ^ The initial value of the 'MVar', it may or may not be used.- -> (MVar a) -- ^ A unique 'MVar' determined by @(name, typeOf val)@. Whether it refers to- -- the given initial value or not is unspecified.-declareMVar name val = unsafePerformIO $ lookupOrInsertMVar name val+ => String -- ^ The identifying name+ -> a -- ^ The initial value of the 'MVar', it may or may not be used.+ -> MVar a -- ^ A unique 'MVar' determined by @(name, typeOf val)@. Whether it refers to+ -- the given initial value or not is unspecified.+declareMVar name val = unsafeDupablePerformIO $ lookupOrInsertMVar name val {-# NOINLINE declareMVar #-} +-- | @declareEmptyMVar name@ maps a variable name to an 'MVar'. Calling it multiple times with+-- the same @name@ and type of the expected 'MVar' will always return the same 'MVar'.+--+-- @+-- someVar :: MVar Int+-- someVar = declareEmptyMVar \"my-global-some-var\"+-- @+--+-- Note, there is /no/ need to use 'unsafePerformIO' or to add a @{-\# NOINLINE someVar \#-}@+-- pragma in order to define top-level 'MVar's.+declareEmptyMVar+ :: Typeable a+ => String -- ^ The identifying name+ -> MVar a -- ^ A unique 'MVar' determined by @(name, typeOf val)@. Whether it is still+ -- empty depends on the rest of the program.+declareEmptyMVar name = unsafeDupablePerformIO $ lookupOrInsertEmptyMVar name+{-# NOINLINE declareEmptyMVar #-} + -- | @declareTVar name val@ maps a variable name to an 'TVar'. Calling it multiple times with the same -- @name@ and type of 'val' will always return the same 'TVar'. --@@ -203,9 +238,9 @@ -- pragma in order to define top-level 'TVar's. declareTVar :: Typeable a- => String -- ^ The identifying name- -> a -- ^ The initial value of the 'TVar', it may or may not be used.- -> (TVar a) -- ^ A unique 'TVar' determined by @(name, typeOf val)@. Whether it refers to- -- the given initial value or not is unspecified.-declareTVar name val = unsafePerformIO $ lookupOrInsertTVar name val+ => String -- ^ The identifying name+ -> a -- ^ The initial value of the 'TVar', it may or may not be used.+ -> TVar a -- ^ A unique 'TVar' determined by @(name, typeOf val)@. Whether it refers to+ -- the given initial value or not is unspecified.+declareTVar name val = unsafeDupablePerformIO $ lookupOrInsertTVar name val {-# NOINLINE declareTVar #-}