chp-spec-1.0.0: Control/Concurrent/CHPSpec/CSP.hs
-- Communicating Haskell Processes.
-- Copyright (c) 2008, University of Kent.
-- 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 the University of Kent nor the names of its
-- 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.
-- | A module containing a few miscellaneous items that can't go in Control.Concurrent.CHP.Base
-- because they would form a cyclic module link. Not publicly visible.
-- TODO rename this module.
module Control.Concurrent.CHPSpec.CSP where
import qualified Control.Exception as C
import Control.Monad.Reader
import Control.Monad.State
import qualified Data.List as L
import qualified Data.Map as Map
import Data.Typeable
import Control.Concurrent.CHPSpec.Base
import Control.Concurrent.CHPSpec.Enroll
import Control.Concurrent.CHPSpec.Spec
{-
-- | Synchronises on the given barrier. You must be enrolled on a barrier in order
-- to synchronise on it. Returns the new phase, following the synchronisation.
syncBarrierWith :: (Unique -> (Unique -> Integer) -> String -> [RecordedIndivEvent Unique])
-> (Int -> STM ()) -> Enrolled PhasedBarrier phase -> CHP phase
syncBarrierWith recE storeN (Enrolled (Barrier (e,tv, fph)))
= buildOnEventPoison (wrapIndiv recE) e (EventActions incPhase (return ()))
(NoPoison <$> (atomically $ readTVar tv))
where
incPhase :: Map.Map Unique Int -> STM ()
incPhase m = do readTVar tv >>= writeTVar tv . fph
maybe (return ()) storeN $ Map.lookup (Event.getEventUnique e) m
-}
data PhasedBarrier phase = Barrier EventId
deriving (Eq, Typeable)
instance Enrollable PhasedBarrier phase where
enroll b f
= f $ Enrolled b
resign _ m = m
bottomPrefix :: String
bottomPrefix = "__CHP.bottom__"
fakeCommIn :: Integer -> CHP a
fakeCommIn n = addSpecT1 $ do
st <- get
put $ st { chpNextBottom = succ $ chpNextBottom st }
return (error $ bottomPrefix ++ show (chpNextBottom st)
,Sync $ Right (n, DirInput, chpNextBottom st)
)
fakeCommOut :: Integer -> a -> CHP ()
fakeCommOut n x = addSpecT1 $ do
possErr <- lift $ C.try $ C.evaluate x
case possErr of
Left (C.ErrorCall s) | bottomPrefix `L.isPrefixOf` s
-> return ((), Sync $ Right
(n, DirOutput, read $ L.drop (L.length bottomPrefix) s))
-- Wasn't one of our bottoms, we can't know anything about it, hope this will work in FDR:
_ -> return ((), Sync $ Left n)
fakeCommBarr :: Integer -> CHP a
fakeCommBarr n = addSpecT1 $ return (undefined, Sync $ Left n)
-- TODO this method will give a different channel each time, but at the moment
-- we treat it as if it will always act the same, so for example with recursive
-- processes (such as the sieve), it won't reflect the behaviour correctly
newEvent :: StateT CHPState IO EventId
newEvent = do st <- get
let n = toInteger $ Map.size $ chpEventMap st
put $ st { chpEventMap = Map.insert n "" $ chpEventMap st }
return n
labelEvent :: EventId -> String -> StateT CHPState IO ()
labelEvent n s = modify $ \st -> st { chpEventMap = Map.insert n s $ chpEventMap st }
newtype Shared c a = Shared (c a)