\begin{code}
{-# OPTIONS -fno-implicit-prelude #-}
-module PrelConc (
+module PrelConc
+ ( ThreadId(..)
+
+ -- Forking and suchlike
+ , myThreadId -- :: IO ThreadId
+ , killThread -- :: ThreadId -> IO ()
+ , raiseInThread -- :: ThreadId -> Exception -> IO ()
+ , par -- :: a -> b -> b
+ , seq -- :: a -> b -> b
+ , yield -- :: IO ()
+
+ -- Waiting
+ , threadDelay -- :: Int -> IO ()
+ , threadWaitRead -- :: Int -> IO ()
+ , threadWaitWrite -- :: Int -> IO ()
+
+ -- MVars
+ , MVar -- abstract
+ , newMVar -- :: a -> IO (MVar a)
+ , newEmptyMVar -- :: IO (MVar a)
+ , takeMVar -- :: MVar a -> IO a
+ , putMVar -- :: MVar a -> a -> IO ()
+ , readMVar -- :: MVar a -> IO a
+ , swapMVar -- :: MVar a -> a -> IO a
+ , isEmptyMVar -- :: MVar a -> IO Bool
- -- Thread Ids
- ThreadId,
-
- -- Forking and suchlike
- forkIO,
- killThread,
- seq, par, fork,
- {-threadDelay, threadWaitRead, threadWaitWrite, -}
-
- -- MVars
- MVar, newMVar, newEmptyMVar, takeMVar, putMVar, readMVar, swapMVar
) where
import PrelBase
-import {-# SOURCE #-} PrelErr ( parError )
-import PrelST ( ST(..), STret(..), liftST )
-import PrelIOBase ( IO(..), MVar(..), liftIO, unsafePerformIO )
-import PrelErr ( parError )
+import PrelErr ( parError, seqError )
+import PrelST ( liftST )
+import PrelIOBase ( IO(..), MVar(..), unsafePerformIO )
import PrelBase ( Int(..) )
-import PrelErr ( seqError )
+import PrelException ( Exception(..), AsyncException(..) )
-infixr 0 `par`, `fork`
+infixr 0 `par`, `seq`
\end{code}
%************************************************************************
\begin{code}
data ThreadId = ThreadId ThreadId#
--- ToDo: data ThreadId = ThreadId (WeakPair ThreadId# ())
--- But since ThreadId# is unlifted, the WeakPair type must use open
+-- ToDo: data ThreadId = ThreadId (Weak ThreadId#)
+-- But since ThreadId# is unlifted, the Weak type must use open
-- type variables.
-forkIO :: IO () -> IO ThreadId
-forkIO action = IO $ \ s ->
- case (fork# action s) of (# s, id #) -> (# s, ThreadId id #)
+--forkIO has now been hoisted out into the Concurrent library.
killThread :: ThreadId -> IO ()
killThread (ThreadId id) = IO $ \ s ->
- case (killThread# id s) of s -> (# s, () #)
+ case (killThread# id (AsyncException ThreadKilled) s) of s1 -> (# s1, () #)
+
+raiseInThread :: ThreadId -> Exception -> IO ()
+raiseInThread (ThreadId id) ex = IO $ \ s ->
+ case (killThread# id ex s) of s1 -> (# s1, () #)
+
+myThreadId :: IO ThreadId
+myThreadId = IO $ \s ->
+ case (myThreadId# s) of (# s1, id #) -> (# s1, ThreadId id #)
+
+yield :: IO ()
+yield = IO $ \s ->
+ case (yield# s) of s1 -> (# s1, () #)
-- "seq" is defined a bit wierdly (see below)
--
seq :: a -> b -> b
seq x y = case (seq# x) of { 0# -> seqError; _ -> y }
-par, fork :: a -> b -> b
-
{-# INLINE par #-}
-{-# INLINE fork #-}
-#if defined(__PARALLEL_HASKELL__) || defined (__GRANSIM__)
+par :: a -> b -> b
par x y = case (par# x) of { 0# -> parError; _ -> y }
-#else
-par x y = y
-#endif
-
-fork x y = unsafePerformIO (forkIO (x `seq` return ())) `seq` y
-
\end{code}
%************************************************************************
\begin{code}
--Defined in IOBase to avoid cycle: data MVar a = MVar (SynchVar# RealWorld a)
-instance Eq (MVar a) where
- (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#
-
newEmptyMVar :: IO (MVar a)
newEmptyMVar = IO $ \ s# ->
takeMVar mvar >>= \ old ->
putMVar mvar new >>
return old
+
+{-
+ Low-level op. for checking whether an MVar is filled-in or not.
+ Notice that the boolean value returned is just a snapshot of
+ the state of the MVar. By the time you get to react on its result,
+ the MVar may have been filled (or emptied) - so be extremely
+ careful when using this operation.
+
+ If you can re-work your abstractions to avoid having to
+ depend on isEmptyMVar, then you're encouraged to do so,
+ i.e., consider yourself warned about the imprecision in
+ general of isEmptyMVar :-)
+-}
+isEmptyMVar :: MVar a -> IO Bool
+isEmptyMVar (MVar mv#) = IO $ \ s# ->
+ case isEmptyMVar# mv# s# of
+ (# s2#, flg #) -> (# s2#, not (flg ==# 0#) #)
\end{code}
@threadWaitWrite@ is similar, but for writing on a file descriptor.
\begin{code}
-{- Not yet -- SDM
threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
-threadDelay (I# x#) = IO $ \ s# ->
- case delay# x# s# of
- s2# -> (# s2#, () #)
-
-threadWaitRead (I# x#) = IO $ \ s# ->
- case waitRead# x# s# of
- s2# -> (# s2#, () #)
-
-threadWaitWrite (I# x#) = IO $ \ s# ->
- case waitWrite# x# s# of
- s2# -> (# s2#, () #)
--}
+threadDelay (I# ms) = IO $ \s -> case delay# ms s of s -> (# s, () #)
+threadWaitRead (I# fd) = IO $ \s -> case waitRead# fd s of s -> (# s, () #)
+threadWaitWrite (I# fd) = IO $ \s -> case waitWrite# fd s of s -> (# s, () #)
\end{code}