eprocess (empty) → 1.0.0
raw patch · 5 files changed
+189/−0 lines, 5 filesdep +MonadCatchIO-mtldep +basedep +mtlsetup-changed
Dependencies added: MonadCatchIO-mtl, base, mtl
Files
- LICENSE +31/−0
- README +2/−0
- Setup.hs +2/−0
- eprocess.cabal +32/−0
- src/Control/Concurrent/Process.hs +122/−0
+ LICENSE view
@@ -0,0 +1,31 @@+Copyright Fernando Brujo Benavides 2009++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Fernando Brujo Benavides nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ README view
@@ -0,0 +1,2 @@+This library provides a *very* basic support for processes with message queues. It was built using channels and MVars.+See http://hackage.haskell.org/package/eprocess
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ eprocess.cabal view
@@ -0,0 +1,32 @@+name: eprocess+version: 1.0.0+cabal-version: >=1.6+build-type: Simple+license: BSD3+license-file: LICENSE+copyright: 2009 Fernando "Brujo" Benavides+maintainer: greenmellon@gmail.com+stability: stable+package-url: http://code.haskell.org/eprocess+bug-reports: http://github.com/elbrujohalcon/eprocess/issues+synopsis: *Very* basic erlang-like process support for Haskel+description: This library provides a *very* basic support for processes with message queues. It was built using channels and MVars.+category: Concurrency+author: Fernando "Brujo" Benavides+tested-with: GHC ==6.10.3, GHC ==6.10.4+data-files: LICENSE README+data-dir: ""+extra-source-files: Setup.hs+extra-tmp-files:++source-repository head+ type: git+ location: git://github.com/elbrujohalcon/eprocess.git++Library+ build-depends: base >= 4, base < 5,+ mtl >=1.1.0, mtl < 1.2,+ MonadCatchIO-mtl >= 0.1.0, MonadCatchIO-mtl < 0.3+ exposed-modules: Control.Concurrent.Process+ hs-source-dirs: src+
+ src/Control/Concurrent/Process.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE GeneralizedNewtypeDeriving,+ MultiParamTypeClasses,+ FlexibleInstances,+ FunctionalDependencies,+ UndecidableInstances #-} ++-- | This module provides a *very* basic support for processes with message queues. It was built using channels and MVars.+module Control.Concurrent.Process (+-- * Types+ ReceiverT, Handle, Process, +-- * Functions+-- ** Process creation + makeProcess, runHere, spawn,+-- ** Message passing+ self, sendTo, recv, sendRecv+ ) where++import Control.Monad.Reader+import Control.Monad.State.Class+import Control.Monad.Writer.Class+import Control.Monad.Error.Class+import Control.Monad.CatchIO+import Data.Monoid+import Control.Concurrent+import Control.Concurrent.Chan++-- | A Process handle. It's returned on process creation and should be used+-- | afterwards to send messages to it+newtype Handle r = PH {chan :: Chan r}++-- | The /ReceiverT/ generic type.+-- +-- [@r@] the type of things the process will receive+-- +-- [@m@] the monad in which it will run+-- +-- [@a@] the classic monad parameter+newtype ReceiverT r m a = RT { internalReader :: ReaderT (Handle r) m a }+ deriving (Monad, MonadIO, MonadTrans, MonadCatchIO)++-- | /Process/ are receivers that run in the IO Monad+type Process r = ReceiverT r IO++-- | /sendTo/ lets you send a message to a running process. Usage:+-- @+-- sendTo processHandle message+-- @+sendTo :: MonadIO m => Handle a -- ^ The receiver process handle + -> a -- ^ The message to send+ -> m ()+sendTo ph = liftIO . writeChan (chan ph)++-- | /recv/ lets you receive a message in a running process (it's a blocking receive). Usage:+-- @+-- message <- recv+-- @+recv :: MonadIO m => ReceiverT r m r+recv = RT $ ask >>= liftIO . readChan . chan++-- | /sendRecv/ is just a syntactic sugar for:+-- @+-- sendTo h a >> recv+-- @ +sendRecv :: MonadIO m => Handle a -- ^ The receiver process handle+ -> a -- ^ The message to send+ -> ReceiverT r m r -- ^ The process where this action is run will wait until it receives something+sendRecv h a = sendTo h a >> recv ++-- | /spawn/ starts a process and returns its handle. Usage:+-- @+-- handle <- spawn process+-- @+spawn :: MonadIO m => Process r k -- ^ The process to be run+ -> m (Handle r) -- ^ The handle for that process+spawn p = liftIO $ do+ pChan <- newChan+ let handle = PH { chan = pChan }+ let action = runReaderT (internalReader p) handle+ forkIO $ action >> return ()+ return handle++-- | /runHere/ executes process code in the current environment. Usage:+-- @+-- result <- runHere process+-- @+runHere :: MonadIO m => Process r t -- ^ The process to be run+ -> m t -- ^ It's returned as an action+runHere p = liftIO (runReaderT (internalReader p) . PH =<< newChan)++-- | /self/ returns the handle of the current process. Usage:+-- @+-- handle <- self+-- @+self :: Monad m => ReceiverT r m (Handle r)+self = RT ask++-- | /makeProcess/ builds a process from a code that generates an IO action. Usage:+-- @+-- process <- makeProcess evalFunction receiver+-- @ +makeProcess :: (m t -> IO s) -> ReceiverT r m t -> Process r s +makeProcess f (RT a) = RT (mapReaderT f a)++instance MonadState s m => MonadState s (ReceiverT r m) where+ get = lift get+ put = lift . put++instance MonadReader r m => MonadReader r (ReceiverT r m) where+ ask = lift ask+ local = onInner . local ++instance (Monoid w, MonadWriter w m) => MonadWriter w (ReceiverT w m) where+ tell = lift . tell+ listen = onInner listen+ pass = onInner pass++instance MonadError e m => MonadError e (ReceiverT r m) where+ throwError = lift . throwError+ catchError (RT a) h = RT $ a `catchError` (\e -> internalReader $ h e)++onInner :: (m a -> m b) -> ReceiverT r m a -> ReceiverT r m b+onInner f (RT m) = RT $ mapReaderT f m