packages feed

regions 0.7.0.1 → 0.11

raw patch · 11 files changed

Files

+ CONTRIBUTORS view
@@ -0,0 +1,6 @@+* Oleg Kiselyov and Chung-chieh Shan+  For coming up with the original idea of "lightweight monadic regions".++* Ben Franksen+  For rewriting the overly complicated ParentOf class and related instances+  to something really clean and simple exploiting TypeFamilies.
Control/Monad/Trans/Region.hs view
@@ -1,9 +1,7 @@-{-# LANGUAGE CPP #-}- ------------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.Trans.Region--- Copyright   :  (c) 2009-2010 Bas van Dijk+-- Copyright   :  (c) 2009-2011 Bas van Dijk -- License     :  BSD3 (see the file LICENSE) -- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com> --@@ -21,25 +19,26 @@       -- * Running regions     , runRegionT -    , TopRegion-    , runTopRegion+    , RegionControlIO -      -- ** Forking /top-level/ regions-    , forkIOTopRegion-    , forkOSTopRegion-#ifdef __GLASGOW_HASKELL__-    , forkOnIOTopRegion-#endif       -- * Duplication     , Dup(dup) -    , module Control.Monad.Trans.Region.ParentOf+      -- * Ancestor relation between regions+    , AncestorRegion -      -- * Handy functions for writing monadic instances+      -- * Special regions+      -- ** The root region+    , RootRegion++      -- ** Local regions+    , LocalRegion, Local++      -- * Utilities for writing monadic instances     , liftCallCC     , mapRegionT     , liftCatch     ) where  import Control.Monad.Trans.Region.Internal-import Control.Monad.Trans.Region.ParentOf+
Control/Monad/Trans/Region/Internal.hs view
@@ -1,15 +1,21 @@-{-# LANGUAGE CPP-           , UnicodeSyntax-           , NoImplicitPrelude-           , GeneralizedNewtypeDeriving-           , RankNTypes-           , KindSignatures+{-# LANGUAGE CPP                        -- For portability.+           , UnicodeSyntax              -- Makes it look so nice.+           , NoImplicitPrelude          -- I like to be fully explicit.+           , GeneralizedNewtypeDeriving -- I'm lazy.+           , RankNTypes                 -- Provides the essential type-safety.+           , KindSignatures             -- To help the type-checker.+           , EmptyDataDecls             -- For the RootRegion type.+           , MultiParamTypeClasses      -- For the AncestorRegion class.+           , UndecidableInstances       -- For the AncestorRegion instances.+           , FlexibleInstances          -- ,,          ,,          ,,+           , OverlappingInstances       -- ,,          ,,          ,,+           , FlexibleContexts           -- For unsafeLiftControl   #-}  ------------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.Trans.Region.Internal--- Copyright   :  (c) 2009-2010 Bas van Dijk+-- Copyright   :  (c) 2009-2011 Bas van Dijk -- License     :  BSD3 (see the file LICENSE) -- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com> --@@ -27,28 +33,35 @@     ( -- * Regions       RegionT -      -- * Close handles-    , CloseAction-    , CloseHandle+      -- * Registering finalizers+    , Finalizer+    , FinalizerHandle     , onExit        -- * Running regions     , runRegionT -    , TopRegion-    , runTopRegion--      -- ** Forking /top-level/ regions-    , forkIOTopRegion-    , forkOSTopRegion-#ifdef __GLASGOW_HASKELL__-    , forkOnIOTopRegion-#endif-       -- * Duplication     , Dup(dup) -      -- * Handy functions for writing monadic instances+      -- * Ancestor relation between regions+    , AncestorRegion++      -- * Special regions+      -- ** The root region+    , RootRegion++      -- ** Local regions+    , LocalRegion, Local, unsafeStripLocal++      -- * MonadTransControl & MonadControlIO+    , RegionControlIO, unsafeLiftControlIO+    , unsafeLiftControl+    , unsafeControlIO+    , unsafeLiftIOOp+    , unsafeLiftIOOp_++      -- * Utilities for writing monadic instances     , liftCallCC     , mapRegionT     , liftCatch@@ -60,13 +73,11 @@ --------------------------------------------------------------------------------  -- from base:-import Prelude             ( (+), (-), seq, fromInteger )+import Prelude             ( (+), (-), seq ) import Control.Applicative ( Applicative, Alternative )-import Control.Monad       ( Monad, return, (>>=), fail-                           , (>>), when, forM_-                           , MonadPlus-                           )+import Control.Monad       ( Monad, return, when, forM_, join, liftM, MonadPlus,  ) import Control.Monad.Fix   ( MonadFix )+import Control.Exception   ( bracket ) import System.IO           ( IO ) import Data.Function       ( ($) ) import Data.Functor        ( Functor )@@ -74,41 +85,46 @@ import Data.IORef          ( IORef, newIORef                            , readIORef, modifyIORef, atomicModifyIORef                            )-import Control.Concurrent  ( forkIO, forkOS, ThreadId )-#ifdef __GLASGOW_HASKELL__-import GHC.Conc            ( forkOnIO )+#if __GLASGOW_HASKELL__ < 700+import Prelude             ( fromInteger )+import Control.Monad       ( (>>=), (>>), fail ) #endif --- from MonadCatchIO-transformers:-import Control.Monad.CatchIO ( MonadCatchIO, block, bracket )+-- from monad-control:+import Control.Monad.Trans.Control ( Run, RunInBase, liftControl )+import Control.Monad.IO.Control    ( MonadControlIO, liftControlIO )  -- from transformers: import Control.Monad.Trans.Class ( MonadTrans, lift ) import Control.Monad.IO.Class    ( MonadIO, liftIO )  import qualified Control.Monad.Trans.Reader as R ( liftCallCC, liftCatch )-import           Control.Monad.Trans.Reader      ( ReaderT(ReaderT)-                                                 , runReaderT, mapReaderT-                                                 )+import Control.Monad.Trans.Reader ( ReaderT(ReaderT), runReaderT, mapReaderT )+ -- from base-unicode-symbols: import Data.Eq.Unicode       ( (≡) ) import Data.Function.Unicode ( (∘) ) +-- Handling the new asynchronous exceptions API in base-4.3:+#if MIN_VERSION_base(4,3,0)+import Control.Exception ( mask_ )+#else+import Control.Exception ( block )+mask_ ∷ IO α → IO α+mask_ = block+#endif + -------------------------------------------------------------------------------- -- * Regions -------------------------------------------------------------------------------- -{-| A monad transformer in which scarce resources can be opened-which are automatically closed when the region terminates.--Note that regions can be nested. @pr@ (for parent region) is a monad which is-usually the region which is running this region. However when you are running a-'TopRegion' the parent region will be 'IO'.+{-| A monad transformer in which scarce resources can be opened. When the region+terminates, all opened resources will be closed automatically. It's a type error+to return an opened resource from the region. The latter ensures no I/O with+closed resources is possible. -}-newtype RegionT s (pr ∷ * → *) α = RegionT-    { unRegionT ∷ ReaderT (IORef [Handle]) pr α }-+newtype RegionT s pr α = RegionT (ReaderT (IORef [RefCountedFinalizer]) pr α)     deriving ( Functor              , Applicative              , Alternative@@ -117,37 +133,62 @@              , MonadFix              , MonadTrans              , MonadIO-             , MonadCatchIO              ) -data Handle = Handle !CloseAction !(IORef RefCnt)+unRegionT ∷ RegionT s pr α → ReaderT (IORef [RefCountedFinalizer]) pr α+unRegionT (RegionT r) = r +-- | A 'Finalizer' paired with its reference count which defines how many times+-- it has been registered in some region.+data RefCountedFinalizer = RefCountedFinalizer !Finalizer !(IORef RefCnt)+ -- | An 'IO' computation that closes or finalizes a resource. For example--- @hClose@ or @free@.-type CloseAction = IO ()+-- \"@hClose someHandle@\" or \"@free somePtr@\".+type Finalizer = IO ()  type RefCnt = Int   ----------------------------------------------------------------------------------- * Close handles+-- * Registering finalizers -------------------------------------------------------------------------------- --- | A handle to a 'CloseAction' that allows you to duplicate the action to a--- parent region using 'dup'.-newtype CloseHandle (r ∷ * → *) = CloseHandle Handle+{-| A handle to a 'Finalizer' that allows you to duplicate it to a parent region+using 'dup'. --- | Register the 'CloseAction' in the region. When the region terminates all--- registered close actions will be perfomed if they're not duplicated to a--- parent region.-onExit ∷ MonadIO pr ⇒ CloseAction → RegionT s pr (CloseHandle (RegionT s pr))-onExit closeAction = RegionT $ ReaderT $ \hsIORef → liftIO $ do-                       refCntIORef ← newIORef 1-                       let h = Handle closeAction refCntIORef-                       modifyIORef hsIORef (h:)-                       return $ CloseHandle h+Duplicating a finalizer means that instead of it being performed when the+current region terminates it is performed when the parent region terminates.+-}+newtype FinalizerHandle (r ∷ * → *) = FinalizerHandle RefCountedFinalizer +{-| Register the 'Finalizer' in the region. When the region terminates all+registered finalizers will be perfomed if they're not duplicated to a parent+region. +Note that finalizers are run in LIFO order (Last In First Out). So executing the following:++@+runRegionT $ do+  _ <- onExit $ putStrLn \"finalizer 1\"+  _ <- onExit $ putStrLn \"finalizer 2\"+  return ()+@++yields:++@+finalizer 2+finalizer 1+@+-}+onExit ∷ MonadIO pr ⇒ Finalizer → RegionT s pr (FinalizerHandle (RegionT s pr))+onExit finalizer = RegionT $ ReaderT $ \hsIORef → liftIO $ do+                     refCntIORef ← newIORef 1+                     let h = RefCountedFinalizer finalizer refCntIORef+                     modifyIORef hsIORef (h:)+                     return $ FinalizerHandle h++ -------------------------------------------------------------------------------- -- * Running regions --------------------------------------------------------------------------------@@ -167,111 +208,29 @@  Note that it is possible to run a region inside another region. -}-runRegionT ∷ MonadCatchIO pr ⇒ (∀ s. RegionT s pr α) → pr α-runRegionT m = runRegionWith [] m--{-| A region which has 'IO' as its parent region which enables it to be:-- * directly executed in 'IO' by 'runTopRegion',-- * concurrently executed in a new thread by 'forkIOTopRegion'.--}-type TopRegion s = RegionT s IO--{-| Convenience funtion for running a /top-level/ region in 'IO'.--Note that: @runTopRegion = 'runRegionT'@--}-runTopRegion ∷ (∀ s. TopRegion s α) → IO α-runTopRegion = runRegionT-------------------------------------------------------------------------------------- ** Forking /top-level/ regions-----------------------------------------------------------------------------------{-| Return a region which executes the given /top-level/ region in a new thread.--Note that the forked region has the same type variable @s@ as the resulting-region. This means that all values which can be referenced in the resulting-region can also be referenced in the forked region.--For example the following is allowed:--@-'runRegionT' $ do-  regionalHndl <- open resource-  threadId <- 'forkIOTopRegion' $ doSomethingWith regionalHndl-  doSomethingElseWith regionalHndl-@--Note that the @regionalHndl@ and all other resources opened in the current-thread are closed only when the current thread or the forked thread terminates-whichever comes /last/.--}-forkIOTopRegion ∷ MonadIO pr ⇒ TopRegion s () → RegionT s pr ThreadId-forkIOTopRegion = forkTopRegion forkIO---- | Like 'forkIOTopRegion' but internally uses 'forkOS'.-forkOSTopRegion ∷ MonadIO pr ⇒ TopRegion s () → RegionT s pr ThreadId-forkOSTopRegion = forkTopRegion forkOS--#ifdef __GLASGOW_HASKELL__--- | Like 'forkIOTopRegion' but internally uses 'forkOnIO'.-forkOnIOTopRegion ∷ MonadIO pr ⇒ Int → TopRegion s () → RegionT s pr ThreadId-forkOnIOTopRegion = forkTopRegion ∘ forkOnIO-#endif--forkTopRegion ∷ MonadIO pr-              ⇒ (IO () → IO ThreadId)-              → (TopRegion s () → RegionT s pr ThreadId)-forkTopRegion doFork = \m →-    RegionT $ ReaderT $ \hsIORef → liftIO $ do-      hs ← readIORef hsIORef-      block $ do-        forM_ hs $ \(Handle _ refCntIORef) → increment refCntIORef-        doFork $ runRegionWith hs m-------------------------------------------------------------------------------------- | Internally used function that actually runs the region on the given list of--- opened resources.-runRegionWith ∷ ∀ s pr α. MonadCatchIO pr-              ⇒ [Handle] → RegionT s pr α → pr α-runRegionWith hs r = bracket (liftIO before)-                             (liftIO ∘ after)-                             (runReaderT $ unRegionT r)+runRegionT ∷ RegionControlIO pr ⇒ (∀ s. RegionT s pr α) → pr α+runRegionT r = unsafeLiftIOOp (bracket before after) thing     where-      before = newIORef hs+      before = newIORef []+      thing hsIORef = runReaderT (unRegionT r) hsIORef       after hsIORef = do         hs' ← readIORef hsIORef-        forM_ hs' $ \(Handle closeAction refCntIORef) → do+        forM_ hs' $ \(RefCountedFinalizer finalizer refCntIORef) → do           refCnt ← decrement refCntIORef-          when (refCnt ≡ 0) closeAction---- | Internally used function that atomically decrements the reference count--- that is stored in the given @IORef@. The function returns the decremented--- reference count.-decrement ∷ IORef RefCnt → IO RefCnt-decrement ioRef = do atomicModifyIORef ioRef $ \refCnt →-                       let refCnt' = refCnt - 1-                       in (refCnt', refCnt')---- | Internally used function that atomically increments the reference count that--- is stored in the given @IORef@.-increment ∷ IORef RefCnt → IO ()-increment ioRef = do refCnt' ← atomicModifyIORef ioRef $ \refCnt →-                                 let refCnt' = refCnt + 1-                                 in (refCnt', refCnt')-                     refCnt' `seq` return ()+          when (refCnt ≡ 0) finalizer+          where+            decrement ∷ IORef RefCnt → IO RefCnt+            decrement ioRef = atomicModifyIORef ioRef $ \refCnt →+                                let refCnt' = refCnt - 1+                                in (refCnt', refCnt')   -------------------------------------------------------------------------------- -- * Duplication -------------------------------------------------------------------------------- -{-| Duplicate an @&#945;@ in the parent region. This @&#945;@ will usually be-some type of regional handle.+{-| Duplicate an @h@ in the parent region. This @h@ will usually be some type of+regional handle.  For example, suppose you run the following region: @@ -313,22 +272,188 @@  Back in the parent region you can safely operate on @r1hDup@. -}-class Dup α where-    dup ∷ MonadCatchIO ppr-        ⇒ α (RegionT cs (RegionT ps ppr))-        → RegionT cs (RegionT ps ppr)-              (α (RegionT ps ppr))+class Dup h where+    dup ∷ MonadIO ppr+        ⇒ h (RegionT cs (RegionT ps ppr))+        →    RegionT cs (RegionT ps ppr)+                     (h (RegionT ps ppr)) -instance Dup CloseHandle where-    dup (CloseHandle h@(Handle _ refCntIORef)) =-      lift $ RegionT $ ReaderT $ \hsIORef → liftIO $ block $ do-        increment refCntIORef-        modifyIORef hsIORef (h:)-        return $ CloseHandle h+instance Dup FinalizerHandle where+    dup = lift ∘ copy +copy ∷ MonadIO pr+     ⇒ FinalizerHandle r+     → RegionT s pr (FinalizerHandle (RegionT s pr))+copy (FinalizerHandle h@(RefCountedFinalizer _ refCntIORef)) =+  RegionT $ ReaderT $ \hsIORef → liftIO $ mask_ $ do+    increment refCntIORef+    modifyIORef hsIORef (h:)+    return $ FinalizerHandle h +increment ∷ IORef RefCnt → IO ()+increment ioRef = do refCnt' ← atomicModifyIORef ioRef $ \refCnt →+                                 let refCnt' = refCnt + 1+                                 in (refCnt', refCnt')+                     refCnt' `seq` return ()++ ----------------------------------------------------------------------------------- * Handy functions for writing monadic instances+-- * Ancestor relation between regions+--------------------------------------------------------------------------------++{-| The @AncestorRegion@ class is used to relate the region in which a resource+was opened to the region in which it is used. Take the following operation from+the @safer-file-handles@ package as an example:++@hFileSize :: (pr \`AncestorRegion\` cr, MonadIO cr) => RegionalFileHandle ioMode pr -> cr Integer@++The @AncestorRegion@ class defines the parent / child relationship between regions.+The constraint++@+    pr \`AncestorRegion\` cr+@++is satisfied if and only if @cr@ is a sequence of zero or more \"@'RegionT' s@\"+(with varying @s@) applied to @pr@, in other words, if @cr@ is an (improper)+nested subregion of @pr@.++The class constraint @InternalAncestorRegion pr cr@ serves two purposes. First, the+instances of @InternalAncestorRegion@ do the type-level recursion that implements+the relation specified above. Second, since it is not exported, user code cannot+add new instances of 'AncestorRegion' (as these would have to be made instances of+@InternalAncestorRegion@, too), effectively turning it into a /closed class/.+-}++-- The implementation uses type-level recursion, so it is no surprise we need+-- UndecidableInstances.++class (InternalAncestorRegion pr cr) ⇒ AncestorRegion pr cr++instance (InternalAncestorRegion pr cr) ⇒ AncestorRegion pr cr++class InternalAncestorRegion (pr ∷ * → *) (cr ∷ * → *)++instance InternalAncestorRegion (RegionT s m) (RegionT s m)+instance (InternalAncestorRegion pr cr) ⇒ InternalAncestorRegion pr (RegionT s cr)+++--------------------------------------------------------------------------------+-- * The root region+--------------------------------------------------------------------------------++{-| The @RootRegion@ is the ancestor of any region.++It's primary purpose is to tag regional handles which don't have an associated+finalizer. For example the standard file handles @stdin@, @stdout@ and @stderr@+which are opened on program startup and which shouldn't be closed when a region+terminates. Another example is the @nullPtr@ which is a memory pointer which+doesn't point to any allocated memory so doesn't need to be freed.+-}+data RootRegion α++instance InternalAncestorRegion RootRegion (RegionT s m)+++--------------------------------------------------------------------------------+-- * Local regions+--------------------------------------------------------------------------------++{-|+A @LocalRegion@ is used to tag regional handles which are created locally.++An example is the @LocalPtr@ in the @alloca@ function from the+@regional-pointers@ package:++@+alloca :: (Storable a, MonadControlIO pr)+       => (forall sl. LocalPtr a ('LocalRegion' sl s) -> RegionT ('Local' s) pr b)+       -> RegionT s pr b+@++The finalisation of the @LocalPtr@ is not performed by the @regions@ library but+is handled locally by @alloca@ instead.++The type variable @sl@, which is only quantified over the continuation, ensures+that locally opened resources don't escape.+-}+data LocalRegion sl s α++{-|+A type used to tag regions in which locally created handles (handles tagged with+'LocalRegion') can be used.++Note than any handle which is created in a @RegionT (Local s)@ can be used+outside that region (@RegionT s@) and visa versa+(except for 'LocalRegion'-tagged handles).+-}+data Local s++instance InternalAncestorRegion (LocalRegion sf s) (RegionT (Local s) m)++instance InternalAncestorRegion (RegionT        s  m) (RegionT (Local s) m)+instance InternalAncestorRegion (RegionT (Local s) m) (RegionT        s  m)++{-|+Convert a 'Local' region to a regular region.++This function is unsafe because it allows you to use a 'LocalRegion'-tagged+handle outside its 'Local' region.+-}+unsafeStripLocal ∷ RegionT (Local s) pr α → RegionT s pr α+unsafeStripLocal = RegionT ∘ unRegionT+++--------------------------------------------------------------------------------+-- * MonadTransControl & MonadControlIO+--------------------------------------------------------------------------------++{-|+Regions do not have an instance for 'MonadControlIO' since that would break the+safety guarantees. (Think about lifting 'forkIO' into a region!)++However 'runRegionT' and other operations on regions do need the ability to lift+control operations. This is where the 'RegionControlIO' class comes in. This+class is identical to `MonadControlIO` but its 'unsafeLiftControlIO' method is+not exported by this module. So user can't accidentally break the safety.++Note that a 'RegionT' is an instance of this class. For the rest there is a+catch-all @instance 'MonadControlIO' m => 'RegionControlIO' m@.+-}+class MonadIO m ⇒ RegionControlIO m where+    unsafeLiftControlIO ∷ (RunInBase m IO → IO α) → m α++instance RegionControlIO pr ⇒ RegionControlIO (RegionT s pr) where+    unsafeLiftControlIO f =+        unsafeLiftControl $ \runInPr →+          unsafeLiftControlIO $ \runInBase →+            let run = liftM (join ∘ lift) ∘ runInBase ∘ runInPr+            in f run++instance MonadControlIO m ⇒ RegionControlIO m where+    unsafeLiftControlIO = liftControlIO++--------------------------------------------------------------------------------++unsafeLiftControl ∷ Monad pr ⇒ (Run (RegionT s) → pr α) → RegionT s pr α+unsafeLiftControl f = RegionT $ liftControl $ \runReader →+                        f $ liftM RegionT ∘ runReader ∘ unRegionT++unsafeControlIO ∷ RegionControlIO m ⇒ (RunInBase m IO → IO (m α)) → m α+unsafeControlIO = join ∘ unsafeLiftControlIO++unsafeLiftIOOp ∷ RegionControlIO m+               ⇒ ((α → IO (m β)) → IO (m γ))+               → ((α →     m β)  →     m γ)+unsafeLiftIOOp f = \g → unsafeControlIO $ \runInIO → f $ runInIO ∘ g++unsafeLiftIOOp_ ∷ RegionControlIO m+                ⇒ (IO (m α) → IO (m β))+                → (    m α →      m β)+unsafeLiftIOOp_ f = \m → unsafeControlIO $ \runInIO → f $ runInIO m++--------------------------------------------------------------------------------+-- * Utilities for writing monadic instances --------------------------------------------------------------------------------  -- | Lift a @callCC@ operation to the new monad.
Control/Monad/Trans/Region/OnExit.hs view
@@ -1,9 +1,7 @@-{-# LANGUAGE UnicodeSyntax #-}- ------------------------------------------------------------------------------- -- |--- Module      :  Control.Monad.Trans.Region.Unsafe--- Copyright   :  (c) 2009-2010 Bas van Dijk+-- Module      :  Control.Monad.Trans.Region.OnExit+-- Copyright   :  (c) 2009-2011 Bas van Dijk -- License     :  BSD3 (see the file LICENSE) -- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com> --@@ -12,12 +10,12 @@ -- -------------------------------------------------------------------------------- -module Control.Monad.Trans.Region.OnExit ( CloseAction-                                         , CloseHandle+module Control.Monad.Trans.Region.OnExit ( Finalizer+                                         , FinalizerHandle                                          , onExit                                          ) where -import Control.Monad.Trans.Region.Internal ( CloseAction-                                           , CloseHandle+import Control.Monad.Trans.Region.Internal ( Finalizer+                                           , FinalizerHandle                                            , onExit                                            )
− Control/Monad/Trans/Region/ParentOf.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE UnicodeSyntax-           , NoImplicitPrelude-           , KindSignatures-           , MultiParamTypeClasses-           , FunctionalDependencies-           , UndecidableInstances-           , FlexibleInstances-           , OverlappingInstances-  #-}------------------------------------------------------------------------------------ |--- Module      :  Control.Monad.Trans.Region.ParentOf--- Copyright   :  (c) 2009-2010 Bas van Dijk--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>--------------------------------------------------------------------------------------module Control.Monad.Trans.Region.ParentOf ( ParentOf ) where---- from base:-import Control.Monad ( Monad )---- from regions:-import Control.Monad.Trans.Region.Internal ( RegionT )---{-| The @ParentOf@ class declares the parent/child relationship between regions.--A region is the parent of another region if they're either equivalent like:--@-RegionT ps pr  \`ParentOf\`  RegionT ps pr-@--or if it is the parent of the parent of the child like:--@-RegionT ps ppr \`ParentOf\` RegionT cs-                              (RegionT pcs-                                (RegionT ppcs-                                  (RegionT ps ppr)))-@--}-class (Monad pr, Monad cr) ⇒ pr `ParentOf` cr--instance Monad r ⇒ ParentOf r r--instance ( Monad cr-         , cr `TypeCast2` RegionT s pcr-         , pr `ParentOf` pcr-         )-         ⇒ ParentOf pr cr-------------------------------------------------------------------------------------- Type casting-----------------------------------------------------------------------------------class TypeCast2     (a ∷ * → *) (b ∷ * → *) |   a → b,   b → a-class TypeCast2'  t (a ∷ * → *) (b ∷ * → *) | t a → b, t b → a-class TypeCast2'' t (a ∷ * → *) (b ∷ * → *) | t a → b, t b → a--instance TypeCast2'  () a b ⇒ TypeCast2    a b-instance TypeCast2'' t  a b ⇒ TypeCast2' t a b-instance TypeCast2'' () a a----- The End ---------------------------------------------------------------------
+ Control/Monad/Trans/Region/Unsafe.hs view
@@ -0,0 +1,23 @@+-------------------------------------------------------------------------------+-- |+-- Module      :  Control.Monad.Trans.Region.Unsafe+-- Copyright   :  (c) 2009-2011 Bas van Dijk+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>+--+--+--------------------------------------------------------------------------------++module Control.Monad.Trans.Region.Unsafe+    ( -- * Local regions+      unsafeStripLocal++      -- * MonadTransControl & MonadControlIO+    , unsafeLiftControlIO+    , unsafeLiftControl+    , unsafeControlIO+    , unsafeLiftIOOp+    , unsafeLiftIOOp_+    ) where++import Control.Monad.Trans.Region.Internal
− Data/RegionRef.hs
@@ -1,105 +0,0 @@-{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude, KindSignatures #-}------------------------------------------------------------------------------------ |--- Module      :  Data.RegionRef--- Copyright   :  (c) 2009-2010 Bas van Dijk--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>------ A mutable variable in the region monad that should provide a safer--- replacement for an 'IORef' because you can't use it outside the region in--- which it was created (unless you explicitly duplicate it).--------------------------------------------------------------------------------------module Data.RegionRef-    ( RegionRef-    , pureDup-    , newRegionRef-    , readRegionRef-    , writeRegionRef-    , modifyRegionRef-    , atomicModifyRegionRef-    ) where------------------------------------------------------------------------------------- Imports------------------------------------------------------------------------------------- from base:-import Data.Function ( ($) )-import Control.Monad ( liftM )-import Data.Eq       ( Eq )-import Data.IORef    ( IORef-                     , newIORef-                     , readIORef, writeIORef-                     , modifyIORef, atomicModifyIORef-                     )---- from base-unicode-symbols:-import Data.Function.Unicode ( (∘) )---- from transformers:-import Control.Monad.IO.Class ( MonadIO, liftIO )---- from ourselves:-import Control.Monad.Trans.Region ( RegionT, ParentOf )-------------------------------------------------------------------------------------- Mutable references in the region monad------------------------------------------------------------------------------------- | A mutable variable storing a value of type @&#945;@ which can only be used--- in region @r@, @r@'s children or @r@'s parent when you duplicate it using--- 'pureDup'.-newtype RegionRef (r ∷ * → *) α = RegionRef { unRegionRef ∷ IORef α }-    deriving ( Eq )---- | Transform the region type @r@ of the regional reference to @r@'s parent so--- that it can be used in that region.-pureDup ∷ RegionRef (RegionT cs (RegionT ps ppr)) α-        → RegionRef             (RegionT ps ppr)  α-pureDup = RegionRef ∘ unRegionRef--{-| Yield a regional computation that returns a new regional reference that-stores the given value.--Note that the reference is parameterized by the same region in which it was-created. This ensures you can never use this reference outside that region and-it allows you to use this reference in a child region of that region--}-newRegionRef ∷ MonadIO pr-             ⇒ α → RegionT s pr (RegionRef (RegionT s pr) α)-newRegionRef = liftM RegionRef ∘ liftIO ∘ newIORef---- | Read the value of the given regional reference.-readRegionRef ∷ (pr `ParentOf` cr, MonadIO cr)-              ⇒ RegionRef pr α → cr α-readRegionRef = liftIO ∘ readIORef ∘ unRegionRef---- | Write a new value into the given regional reference.-writeRegionRef ∷ (pr `ParentOf` cr, MonadIO cr)-               ⇒ RegionRef pr α → α → cr ()-writeRegionRef ref x = liftIO $ writeIORef (unRegionRef ref) x---- | Mutate the contents of the given regional reference using the given--- function.-modifyRegionRef ∷ (pr `ParentOf` cr, MonadIO cr)-                ⇒ RegionRef pr α → (α → α) → cr ()-modifyRegionRef ref f = liftIO $ modifyIORef (unRegionRef ref) f--{-| Atomically modifies the contents of the given regional reference using the-given function.--This function is useful for using a regional reference in a safe way in a-multithreaded program. If you only have one regional reference, then using-@atomicModifyRegionRef@ to access and modify it will prevent race conditions.--}-atomicModifyRegionRef ∷ (pr `ParentOf` cr, MonadIO cr)-                      ⇒ RegionRef pr α → (α → (α, β)) → cr β-atomicModifyRegionRef ref f = liftIO $ atomicModifyIORef (unRegionRef ref) f----- The End ---------------------------------------------------------------------
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2009-2010 Bas van Dijk+Copyright (c) 2009-2011 Bas van Dijk  All rights reserved. 
+ NEWS view
@@ -0,0 +1,154 @@+0.9++(Relased on: Wed Mar 9 12:20:05 UTC 2011)++* Removed Control.Monad.Trans.Region.Concurrent+  The fork functions contained bugs which could not be fixed.++* Removed Data.RegionRef+  I always considered this module a bit of a wart.++* Switch from monad-peel to monad-control.++* Added support for local regions+  Primarily needed for the alloca functions from the regional-pointers package.+++0.8.1++(Released on: Mon Jan 17 22:04:15 UTC 2011)++* Fixed bug: Forked threads should have the same masked state has their parents.++* Added forkIOUnmasked.++* Derived MonadTransPeel instance for RegionT.+++0.8++(Released on: Sat Nov 6 15:56:27 UTC 2010)++* Released during BelHac 2010!++* Replaced ParentOf class with the more understandable,+  easier to implement and safer AncestorRegion class.+  (Contributed by Ben Franksen)++  Also moved the class from its own module to the main:+  Control.Monad.Trans.Region module.++* Exported fork*TopRegion functions from their own dedicated module:+  Control.Monad.Trans.Region.Concurrent.++* Use MonadPeelIO instead of MonadCatchIO.++* Removed TopRegion and runTopRegion and+  renamed the fork functions accordingly.++* Renamed CloseAction to Finalizer and+  CloseHandle to FinalizerHandle.++* Added the RootRegion (empty) datatype which is defined as the+  ancestor of any region.+++0.7.0.1++(Released on: Sat Sep 11 14:17:48 UTC 2010)++* Added strictness flags to the arguments of the Handle data constructor.++* Fix haddock link.+++0.7++(Released on: Wed Sep 1 20:11:41 UTC 2010)++* Renamed forkTopRegion to forkIOTopRegion+  Also added forkOSTopRegion and forkOnIOTopRegion.+++0.6.0.1++(Released on: Wed Jun 16 13:45:27 UTC 2010)++* Removed outdated documentation.+++0.6++(Released on: Wed Jun 16 09:11:23 UTC 2010)++* Major change: removed the Resource class in favor of the much+  simpler 'onExit' function.++* Renamed Control.Monad.Trans.Region.Close to+  Control.Monad.Trans.Region.OnExit.+++0.5++(Released on: Sun May 2 20:24:19 UTC 2010)++* Renamed openResource and closeResource to open and close+  respectively The intention is that Control.Resource should be+  imported qualified.++* Updated dependencies+  transformers              >= 0.2   && < 0.3+  MonadCatchIO-transformers >= 0.2   && < 0.3+  base-unicode-symbols      >= 0.1.1 && < 0.3+++0.4++(Released on: Thu Feb 4 10:17:47 UTC 2010)++* Added Data.RegionRef.++* Moved the Resource class to its own module Control.Resource.++* Depend on more compatible versions of MonadCatchIO-transformers.++* Defined and exported liftCallCC.+++0.3++(Released on: Sat Jan 23 14:25:08 UTC 2010)++* Add 'mapInternalHandle'.++* Export the 'Dup' and 'ParentOf' classes from+  'Control.Monad.Trans.Region'.+++0.2++(Released on: Thu Jan 7 14:14:15 UTC 2010)++* Renamed module Control.Monad.Trans.Region.Internal to+  Control.Monad.Trans.Region.Unsafe.++* Export only the unsafe things from Control.Monad.Trans.Region.Unsafe.++* Removed resource type from RegionT which prevented opening different+  types of resources in the same region.+++0.1.0.1++(Released on: Wed Dec 23 13:42:48 UTC 2009)++* Depend on base-unicode-symbols instead of unicode-symbols.++* Tested with base 4.2.+++0.1++(Released on: Mon Dec 21 09:46:51 UTC 2009)++* Initial release.
+ README.markdown view
@@ -0,0 +1,25 @@+This package provides the region monad transformer. Scarce resources+like files, memory pointers or USB devices for example can be opened+in a region. When the region terminates, all opened resources will be+automatically closed. The main advantage of regions is that the opened+resources can not be returned from the region which ensures no I/O+with closed resources is possible.++The primary technique used in this package is called "Lightweight+monadic regions" which was [invented][1] by Oleg Kiselyov and+Chung-chieh Shan.++Also see the [regions-mtl] and [regions-monadstf] packages which+provide instances for the classes in the respected monad transformers+packages.++For an example on how to use this library see the+[safer-file-handles], [usb-safe] or [regional-pointers] packages.++[1]: http://okmij.org/ftp/Haskell/regions.html#light-weight++[regions-mtl]:        http://hackage.haskell.org/package/regions-mtl+[regions-monadstf]:   http://hackage.haskell.org/package/regions-monadstf+[safer-file-handles]: http://hackage.haskell.org/package/safer-file-handles+[usb-safe]:           http://hackage.haskell.org/package/usb-safe+[regional-pointers]:  http://hackage.haskell.org/package/regional-pointers
regions.cabal view
@@ -1,12 +1,14 @@ name:          regions-version:       0.7.0.1+version:       0.11 cabal-version: >=1.6 build-type:    Simple license:       BSD3 license-file:  LICENSE-copyright:     2009-2010 Bas van Dijk+copyright:     2009-2011 Bas van Dijk author:        Bas van Dijk maintainer:    Bas van Dijk <v.dijk.bas@gmail.com>+homepage:      https://github.com/basvandijk/regions/+bug-reports:   https://github.com/basvandijk/regions/issues stability:     experimental category:      Control, Monadic Regions synopsis:      Provides the region monad for safely opening and working with@@ -24,24 +26,25 @@   .   <http://okmij.org/ftp/Haskell/regions.html#light-weight>   .-  Also see the @regions-monadsfd@ and @regions-monadstf@ packages which provide-  instances for the classes in the respected monads packages.+  Also see the @regions-mtl@ and @regions-monadstf@ packages which provide+  instances for the classes in the respected monad transformers packages.   .   For an example on how to use this library see the @safer-file-handles@,   @usb-safe@ or @regional-pointers@ packages. +extra-source-files: README.markdown, NEWS, CONTRIBUTORS+ source-repository head-  Type:     darcs-  Location: http://code.haskell.org/~basvandijk/code/regions+  Type:     git+  Location: git://github.com/basvandijk/regions.git  Library   GHC-Options: -Wall-  build-depends: base                      >= 4       && < 4.3-               , base-unicode-symbols      >= 0.1.1   && < 0.3-               , transformers              >= 0.2     && < 0.3-               , MonadCatchIO-transformers >= 0.2     && < 0.3+  build-depends: base                      >= 4     && < 4.5+               , base-unicode-symbols      >= 0.1.1 && < 0.3+               , transformers              >= 0.2   && < 0.3+               , monad-control             >= 0.2   && < 0.3   exposed-modules: Control.Monad.Trans.Region-                   Control.Monad.Trans.Region.ParentOf                    Control.Monad.Trans.Region.OnExit-                   Data.RegionRef+                   Control.Monad.Trans.Region.Unsafe   other-modules:   Control.Monad.Trans.Region.Internal