{-# LANGUAGE ExistentialQuantification, FlexibleContexts, TypeOperators #-} -- | A pure specification of 'forkIO'. module Test.IOSpec.Fork ( ForkS , forkIO ) where import Test.IOSpec.VirtualMachine import Test.IOSpec.Types -- The 'ForkS' data type and its instances. -- -- | An expression of type @IOSpec ForkS a@ corresponds to an 'IO' -- computation that uses 'forkIO' and returns a value of -- type 'a'. -- -- By itself, 'ForkS' is not terribly useful. You will probably want -- to use @IOSpec (ForkS :+: MVarS)@ or @IOSpec (ForkS :+: STMS)@. data ForkS a = forall f b . Executable f => Fork (IOSpec f b) (ThreadId -> a) instance Functor ForkS where fmap f (Fork l io) = Fork l (f . io) -- | The 'forkIO' function forks off a new thread. forkIO :: (Executable f, ForkS :<: g) => IOSpec f a -> IOSpec g ThreadId forkIO p = inject (Fork p return) instance Executable ForkS where step (Fork t p) = do tid <- freshThreadId updateSoup tid t return (Step (p tid))