documentation only: tag some things as "GHC only".
-- * Basic concurrency operations
-#ifndef __HUGS__
ThreadId,
+#ifdef __GLASGOW_HASKELL__
myThreadId,
#endif
forkIO,
-#ifndef __HUGS__
+#ifdef __GLASGOW_HASKELL__
killThread,
throwTo,
#endif
import Control.Concurrent.QSemN
import Control.Concurrent.SampleVar
+#ifdef __HUGS__
+type ThreadId = ()
+#endif
+
{- $conc_intro
The concurrency extension for Haskell is described in the paper
Haskell threads can communicate via 'MVar's, a kind of synchronised
mutable variable (see "Control.Concurrent.MVar"). Several common
concurrency abstractions can be built from 'MVar's, and these are
-provided by the "Control.Concurrent" library. Threads may also
-communicate via exceptions.
+provided by the "Control.Concurrent" library.
+In GHC, threads may also communicate via exceptions.
-}
{- $conc_scheduling
#ifdef __GLASGOW_HASKELL__
-- | A variant of 'throwDyn' that throws the dynamic exception to an
--- arbitrary thread (c.f. 'throwTo').
+-- arbitrary thread (GHC only: c.f. 'throwTo').
throwDynTo :: Typeable exception => ThreadId -> exception -> IO ()
throwDynTo t exception = throwTo t (DynException (toDyn exception))
#endif /* __GLASGOW_HASKELL__ */
-- Stability : experimental
-- Portability : non-portable
--
--- Data types for generic definitions.
+-- Data types for generic definitions (GHC only).
--
-----------------------------------------------------------------------------
-- Stability : experimental
-- Portability : non-portable (uses Control.Exception, Control.Concurrent)
--
--- This is a batch driver for runing QuickCheck.
+-- This is a batch driver for running QuickCheck (GHC only).
--
-----------------------------------------------------------------------------
useful when debugging or diagnosing the behaviour of a concurrent
program.
-NOTE: in GHC, if you have a 'ThreadId', you essentially have
+/Note/: in GHC, if you have a 'ThreadId', you essentially have
a pointer to the thread itself. This means the thread itself can\'t be
garbage collected until you drop the 'ThreadId'.
This misfeature will hopefully be corrected at a later date.
+
+/Note/: Hugs does not provide any operations on other threads;
+it defines 'ThreadId' as a synonym for ().
-}
--forkIO has now been hoisted out into the Concurrent library.
-{- | 'killThread' terminates the given thread (Note: 'killThread' is
-not implemented in Hugs). Any work already done by the thread isn\'t
+{- | 'killThread' terminates the given thread (GHC only).
+Any work already done by the thread isn\'t
lost: the computation is suspended until required by another thread.
The memory used by the thread will be garbage collected if it isn\'t
referenced from anywhere. The 'killThread' function is defined in
killThread :: ThreadId -> IO ()
killThread tid = throwTo tid (AsyncException ThreadKilled)
-{- | 'throwTo' raises an arbitrary exception in the target thread.
+{- | 'throwTo' raises an arbitrary exception in the target thread (GHC only).
'throwTo' does not return until the exception has been raised in the
target thread. The calling thread can thus be certain that the target
throwTo (ThreadId id) ex = IO $ \ s ->
case (killThread# id ex s) of s1 -> (# s1, () #)
--- | Returns the 'ThreadId' of the calling thread.
+-- | Returns the 'ThreadId' of the calling thread (GHC only).
myThreadId :: IO ThreadId
myThreadId = IO $ \s ->
case (myThreadId# s) of (# s1, id #) -> (# s1, ThreadId id #)
case isEmptyMVar# mv# s# of
(# s2#, flg #) -> (# s2#, not (flg ==# 0#) #)
--- |Add a finalizer to an 'MVar'. See "Foreign.ForeignPtr" and
+-- |Add a finalizer to an 'MVar' (GHC only). See "Foreign.ForeignPtr" and
-- "System.Mem.Weak" for more about finalizers.
addMVarFinalizer :: MVar a -> IO () -> IO ()
addMVarFinalizer (MVar m) finalizer =
\begin{code}
-- |The 'threadDelay' operation will cause the current thread to
--- suspend for a given number of microseconds. Note that the resolution
+-- suspend for a given number of microseconds (GHC only).
+--
+-- Note that the resolution
-- used by the Haskell runtime system\'s internal timer together with the
-- fact that the thread may take some time to be rescheduled after the
-- time has expired, means that the accuracy is more like 1\/50 second.
threadDelay :: Int -> IO ()
-- | Block the current thread until data is available to read on the
--- given file descriptor.
+-- given file descriptor (GHC only).
threadWaitRead :: Int -> IO ()
-- | Block the current thread until data can be written to the
--- given file descriptor.
+-- given file descriptor (GHC only).
threadWaitWrite :: Int -> IO ()
threadDelay (I# ms) = IO $ \s -> case delay# ms s of s -> (# s, () #)
|| tEXT_MODE_SEEK_ALLOWED))
-- -----------------------------------------------------------------------------
--- Changing echo status
+-- Changing echo status (Non-standard GHC extensions)
--- Non-standard GHC extension is to allow the echoing status
--- of a handles connected to terminals to be reconfigured:
+-- | Set the echoing status of a handle connected to a terminal (GHC only).
hSetEcho :: Handle -> Bool -> IO ()
hSetEcho handle on = do
ClosedHandle -> ioe_closedHandle
_ -> setEcho (haFD handle_) on
+-- | Get the echoing status of a handle connected to a terminal (GHC only).
+
hGetEcho :: Handle -> IO Bool
hGetEcho handle = do
isT <- hIsTerminalDevice handle
ClosedHandle -> ioe_closedHandle
_ -> getEcho (haFD handle_)
+-- | Is the handle connected to a terminal? (GHC only)
+
hIsTerminalDevice :: Handle -> IO Bool
hIsTerminalDevice handle = do
withHandle_ "hIsTerminalDevice" handle $ \ handle_ -> do
class Read a where
readsPrec :: Int -> ReadS a
readList :: ReadS [a]
+ -- | Proposed replacement for 'readsPrec' using new-style parsers (GHC only).
readPrec :: ReadPrec a
+ -- | Proposed replacement for 'readList' using new-style parsers (GHC only).
readListPrec :: ReadPrec [a]
-- default definitions
readListPrec = readS_to_Prec (\_ -> readList)
readListDefault :: Read a => ReadS [a]
--- ^ Use this to define the 'readList' method, if you
--- don't want a special case
+-- ^ Use this to define the 'readList' method, if you don't want a special
+-- case (GHC only; for other systems the default suffices).
readListDefault = readPrec_to_S readListPrec 0
readListPrecDefault :: Read a => ReadPrec [a]
-- ^ Use this to define the 'readListPrec' method, if you
--- don't want a special case
+-- don't want a special case (GHC only).
readListPrecDefault = list readPrec
------------------------------------------------------------------------
foreign import ccall unsafe "systemCmd" primSystem :: CString -> IO Int
{- |
-The same as 'system', but bypasses the shell. Will behave more portably between
-systems, because there is no interpretation of shell metasyntax.
+The same as 'system', but bypasses the shell (GHC only).
+Will behave more portably between systems,
+because there is no interpretation of shell metasyntax.
-}
rawSystem :: String -> IO ExitCode
{-|
@withArgs args act@ - while executing action @act@, have 'System.getArgs'
-return @args@.
+return @args@ (GHC only).
-}
withArgs xs act = do
p <- System.Environment.getProgName
withArgv (p:xs) act
{-|
-@withProgName name act@ - while executing action @act@, have 'System.getProgName'return @name@.
+@withProgName name act@ - while executing action @act@,
+have 'System.getProgName' return @name@ (GHC only).
-}
withProgName nm act = do
xs <- System.Environment.getArgs