packages feed

regions 0.3 → 0.4

raw patch · 6 files changed

+212/−94 lines, 6 filesdep ~MonadCatchIO-transformers

Dependency ranges changed: MonadCatchIO-transformers

Files

Control/Monad/Trans/Region.hs view
@@ -38,9 +38,9 @@     , ParentOf        -- * Handy functions for writing monadic instances+    , liftCallCC     , mapRegionT     , liftCatch-      -- | /TODO: define and export: /@liftCallCC@     ) where  import Control.Monad.Trans.Region.Internal
Control/Monad/Trans/Region/Internal.hs view
@@ -4,7 +4,6 @@            , RankNTypes            , ScopedTypeVariables            , KindSignatures-           , TypeFamilies            , MultiParamTypeClasses            , FunctionalDependencies            , UndecidableInstances@@ -33,14 +32,8 @@ --------------------------------------------------------------------------------  module Control.Monad.Trans.Region.Internal-    ( -- * Scarce resources-      Resource-    , Handle-    , openResource-    , closeResource--      -- * Regions-    , RegionT+    ( -- * Regions+      RegionT        -- * Running regions     , runRegionT@@ -54,7 +47,6 @@     , RegionalHandle      , internalHandle-    , mapInternalHandle      , open     , with@@ -64,9 +56,9 @@     , dup        -- * Handy functions for writing monadic instances+    , liftCallCC     , mapRegionT     , liftCatch-      -- | /TODO: define and export: /@liftCallCC@        -- * Parent/child relationship between regions.     , ParentOf@@ -99,33 +91,21 @@ -- from transformers: import Control.Monad.Trans   ( MonadTrans, lift, MonadIO, liftIO ) -import qualified Control.Monad.Trans.Reader as Reader ( liftCatch )-import           Control.Monad.Trans.Reader ( ReaderT-                                            , ask-                                            , runReaderT, mapReaderT-                                            )+import qualified Control.Monad.Trans.Reader as R ( liftCallCC, liftCatch )+import           Control.Monad.Trans.Reader      ( ReaderT+                                                 , ask+                                                 , runReaderT, mapReaderT+                                                 ) -- from base-unicode-symbols: import Data.Eq.Unicode       ( (≡) ) import Data.Function.Unicode ( (∘) ) ------------------------------------------------------------------------------------- * Scarce resources-----------------------------------------------------------------------------------{-| Class of /scarce/ resources. A scarce resource is a resource that only one-user can use at a time. (like a file, memory pointer or USB device for-example).--Because of the scarcity, these resources need to be /opened/ to grant temporary-sole access to the resource. When the resource is no longer needed it should be-/closed/ a.s.a.p to grant others access to the resource.--}-class Resource resource where-    data Handle resource ∷ *--    openResource  ∷ resource → IO (Handle resource)-    closeResource ∷ Handle resource → IO ()+-- from ourselves:+import Control.Resource ( Resource+                        , Handle+                        , openResource+                        , closeResource+                        )   --------------------------------------------------------------------------------@@ -186,14 +166,24 @@        {-| Get the reference count from the given regional handle. -      Handles are reference counted because they may be /duplicated/-      to a parent region using 'dup'.+      Normally a handle should be closed when its originating region+      terminates. There are two exceptions to this rule: +      * When a handle is /duplicated/ to a parent region using 'dup'+        it should only be closed when the parent region terminates.++      * When a region is executed in a new thread using 'forkTopRegion' all+        handles that can be referenced in the originating region should also be+        referenceable in the new forked region. Therefore those handles should only be+        closed when the originating region or the new forked region terminates,+        whichever comes /last/.++      To implement this behaviour, handles are reference counted.       The reference count is:         * Initialized at 1 in 'open'. -       * Incremented in 'dup'.+       * Incremented in 'dup' and 'forkTopRegion'.         * Decremented on termination of 'runRegionWith'          (which is called by 'runRegionT' and 'forkTopRegion').@@ -204,11 +194,6 @@     , refCntIORef ∷ IORef Int     } --- | Modify the internal handle from the given regional handle.-mapInternalHandle ∷ (Handle resource1 → Handle resource2)-                  → (RegionalHandle resource1 r → RegionalHandle resource2 r)-mapInternalHandle f rh = rh { internalHandle = f $ internalHandle rh }- {-| Internally used function that atomically decrements the reference count that is stored in the given @IORef@. The function returns the decremented reference count.@@ -478,12 +463,10 @@ -- * Handy functions for writing monadic instances -------------------------------------------------------------------------------- --- TODO:--- -- | Lift a @callCC@ operation to the new monad.--- liftCallCC ∷ (((α → pr β) → pr α) → pr α)        -- ^ @callCC@ on the argument monad.---            → ((α → RegionT s pr β) → RegionT s pr α)---            → RegionT s pr α--- liftCallCC callCC f = RegionT $ ???+-- | Lift a @callCC@ operation to the new monad.+liftCallCC ∷ (((α → pr β) → pr α) → pr α)+           → (((α → RegionT s pr β) → RegionT s pr α) → RegionT s pr α)+liftCallCC callCC f = RegionT $ R.liftCallCC callCC $ unRegionT ∘ f ∘ (RegionT ∘)  -- | Transform the computation inside a region. mapRegionT ∷ (m α → n β) → RegionT s m α → RegionT s n β@@ -494,7 +477,7 @@           → RegionT s pr α             -- ^ Computation to attempt.           → (e → RegionT s pr α)       -- ^ Exception handler.           → RegionT s pr α-liftCatch f m h = RegionT $ Reader.liftCatch f (unRegionT m) (unRegionT ∘ h)+liftCatch f m h = RegionT $ R.liftCatch f (unRegionT m) (unRegionT ∘ h)   --------------------------------------------------------------------------------
Control/Monad/Trans/Region/Unsafe.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE UnicodeSyntax #-}+ ------------------------------------------------------------------------------- -- | -- Module      :  Control.Monad.Trans.Region.Unsafe@@ -10,29 +12,17 @@ -- close the resource manually, which will defeat the safety-guarantees that -- this package provides! ----- This module should /only/ be used by library authors wishing to allow their--- end-users to open their resources in a region.------ To create a module or library that allows your users to open your resources--- in a region, the only thing you have to do is to define an instance for--- 'Resource' for your type of resource.------ Make sure not to re-export anything from this module. Either re-export things--- from @Control.Monad.Trans.Region@ or tell your users to import that module--- directly.--- --------------------------------------------------------------------------------  module Control.Monad.Trans.Region.Unsafe-    ( -- * Scarce resources-      Resource-    , Handle--    , openResource-    , closeResource--    , internalHandle+    ( internalHandle     , mapInternalHandle     ) where -import Control.Monad.Trans.Region.Internal+import Control.Monad.Trans.Region.Internal ( RegionalHandle, internalHandle )+import Control.Resource ( Handle )++-- | Modify the internal handle from the given regional handle.+mapInternalHandle ∷ (Handle resource1 → Handle resource2)+                  → (RegionalHandle resource1 r → RegionalHandle resource2 r)+mapInternalHandle f rh = rh { internalHandle = f $ internalHandle rh }
+ Control/Resource.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude, TypeFamilies #-}++-------------------------------------------------------------------------------+-- |+-- Module      :  Control.Resource+-- Copyright   :  (c) 2009 Bas van Dijk+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>+--+-- Unsafely opening and closing of scarce resources.+--+--------------------------------------------------------------------------------++module Control.Resource+    ( Resource+    , Handle+    , openResource+    , closeResource+    ) where++import System.IO ( IO )++{-| Class of /scarce/ resources. A scarce resource is a resource that only one+user can use at a time. (like a file, memory pointer or USB device for+example).++Because of the scarcity, these resources need to be /opened/ to grant temporary+sole access to the resource. When the resource is no longer needed it should be+/closed/ a.s.a.p to grant others access to the resource.+-}+class Resource resource where+    data Handle resource ∷ *++    -- | Yield an @IO@ computation that opens the given resource and returns a+    -- @Handle@ on it.+    --+    -- Think of a handle as your private session with the resource. As long as+    -- you have it, other users can't use the resource. So don't forget to close+    -- this session with the resource as soon as you're done with it.+    openResource  ∷ resource → IO (Handle resource)++    -- | Yield an @IO@ computation that closes the resource identified by the+    -- given @Handle@.+    --+    -- /Warning/: Using the @Handle@ after the resource has been closed will+    -- usually throw an exception or result in a program crash!+    closeResource ∷ Handle resource → IO ()
+ Data/RegionRef.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE UnicodeSyntax, NoImplicitPrelude, KindSignatures #-}++-------------------------------------------------------------------------------+-- |+-- Module      :  Data.RegionRef+-- Copyright   :  (c) 2009 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.Trans ( 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 ---------------------------------------------------------------------
regions.cabal view
@@ -1,10 +1,10 @@ name:          regions-version:       0.3+version:       0.4 cabal-version: >=1.6 build-type:    Simple license:       BSD3 license-file:  LICENSE-copyright:     2009 Bas van Dijk+copyright:     2010 Bas van Dijk author:        Bas van Dijk maintainer:    Bas van Dijk <v.dijk.bas@gmail.com> stability:     experimental@@ -31,28 +31,19 @@    . -  This package provides two modules:--  .--  * @Control.Monad.Trans.Region.Unsafe@ should only be used by library authors-    wishing to allow their users to open their type of resources in a region. It-    should /not/ be used by end-users directly!--  .--  * @Control.Monad.Trans.Region@ provides the public and safe interface to-    regions which can be used by end-users.+  Also see the @regions-monadsfd@ and @regions-monadstf@ packages which provide+  instances for the classes in the respected monads packages.    . -  Also see the @regions-monadsfd@ and @regions-monadstf@ packages which provide-  instances for the classes in the respected monads packages.+  For an example on how to use this library see the @safer-file-handles@,+  @usb-safe@ or @regional-pointers@ packages.    . -  For an example of how to use this library see the @safer-file-handles@ or-  @usb-safe@ packages.+  Note that if you want to open /your/ type of scarce resource in a region, the+  only thing you have to do is define an instance for the @Resource@ class+  (which you can find in: @Control.Resource@).  source-repository head   Type:     darcs@@ -60,10 +51,12 @@  Library   GHC-Options: -Wall-  build-depends: base                      >= 4 && < 4.3-               , base-unicode-symbols      >= 0.1.1 && < 0.2-               , transformers              >= 0.1.4 && < 0.2-               , MonadCatchIO-transformers == 0.0.2.*-  exposed-modules: Control.Monad.Trans.Region-                 , Control.Monad.Trans.Region.Unsafe+  build-depends: base                      >= 4       && < 4.3+               , base-unicode-symbols      >= 0.1.1   && < 0.2+               , transformers              >= 0.1.4   && < 0.2+               , MonadCatchIO-transformers >= 0.0.2.0 && < 0.1+  exposed-modules: Control.Resource+                   Control.Monad.Trans.Region+                   Control.Monad.Trans.Region.Unsafe+                   Data.RegionRef   other-modules:   Control.Monad.Trans.Region.Internal