[project @ 2005-04-12 12:57:49 by ross]
[ghc-base.git] / GHC / IOBase.lhs
index c25c69e..0a3cfca 100644 (file)
@@ -1,5 +1,5 @@
 \begin{code}
-{-# OPTIONS -fno-implicit-prelude #-}
+{-# OPTIONS_GHC -fno-implicit-prelude #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  GHC.IOBase
 --
 -----------------------------------------------------------------------------
 
-module GHC.IOBase where
-
+-- #hide
+module GHC.IOBase(
+    IO(..), unIO, failIO, liftIO, bindIO, thenIO, returnIO, 
+    unsafePerformIO, unsafeInterleaveIO,
+  
+       -- To and from from ST
+    stToIO, ioToST, unsafeIOToST,
+
+       -- References
+    IORef(..), newIORef, readIORef, writeIORef, 
+    IOArray(..), newIOArray, readIOArray, writeIOArray, unsafeReadIOArray, unsafeWriteIOArray,
+    MVar(..),
+
+       -- Handles, file descriptors,
+    FilePath,  
+    Handle(..), Handle__(..), HandleType(..), IOMode(..), FD, 
+    isReadableHandleType, isWritableHandleType, showHandle,
+  
+       -- Buffers
+    Buffer(..), RawBuffer, BufferState(..), BufferList(..), BufferMode(..),
+    bufferIsWritable, bufferEmpty, bufferFull, 
+
+       -- Exceptions
+    Exception(..), ArithException(..), AsyncException(..), ArrayException(..),
+    stackOverflow, heapOverflow, throw, throwIO, ioException, 
+    IOError, IOException(..), IOErrorType(..), ioError, userError,
+    ExitCode(..) 
+  ) where
+       
 import GHC.ST
 import GHC.Arr -- to derive Ix class
 import GHC.Enum -- to derive Enum class
 import GHC.STRef
 import GHC.Base
-import GHC.Num -- To get fromInteger etc, needed because of -fno-implicit-prelude
+--  import GHC.Num     -- To get fromInteger etc, needed because of -fno-implicit-prelude
 import Data.Maybe  ( Maybe(..) )
 import GHC.Show
 import GHC.List
@@ -112,13 +139,22 @@ returnIO x = IO (\ s -> (# s, x #))
 -- ---------------------------------------------------------------------------
 -- Coercions between IO and ST
 
---stToIO        :: (forall s. ST s a) -> IO a
+-- | A monad transformer embedding strict state transformers in the 'IO'
+-- monad.  The 'RealWorld' parameter indicates that the internal state
+-- used by the 'ST' computation is a special one supplied by the 'IO'
+-- monad, and thus distinct from those used by invocations of 'runST'.
 stToIO       :: ST RealWorld a -> IO a
 stToIO (ST m) = IO m
 
 ioToST       :: IO a -> ST RealWorld a
 ioToST (IO m) = (ST m)
 
+-- This relies on IO and ST having the same representation modulo the
+-- constraint on the type of the state
+--
+unsafeIOToST        :: IO a -> ST s a
+unsafeIOToST (IO io) = ST $ \ s -> (unsafeCoerce# io) s
+
 -- ---------------------------------------------------------------------------
 -- Unsafe IO operations
 
@@ -164,7 +200,7 @@ It is less well known that
 >     
 >     main = do
 >            writeIORef test [42]
->            bang \<- readIORef test
+>            bang <- readIORef test
 >            print (bang :: [Char])
 
 This program will core dump.  This problem with polymorphic references
@@ -178,13 +214,19 @@ help of 'unsafePerformIO'.  So be careful!
 unsafePerformIO        :: IO a -> a
 unsafePerformIO (IO m) = case m realWorld# of (# _, r #)   -> r
 
+-- Why do we NOINLINE unsafePerformIO?  See the comment with
+-- GHC.ST.runST.  Essentially the issue is that the IO computation
+-- inside unsafePerformIO must be atomic: it must either all run, or
+-- not at all.  If we let the compiler see the application of the IO
+-- to realWorld#, it might float out part of the IO.
+
 {-|
 'unsafeInterleaveIO' allows 'IO' computation to be deferred lazily.
 When passed a value of type @IO a@, the 'IO' will only be performed
 when the value of the @a@ is demanded.  This is used to implement lazy
 file reading, see 'System.IO.hGetContents'.
 -}
-{-# NOINLINE unsafeInterleaveIO #-}
+{-# INLINE unsafeInterleaveIO #-}
 unsafeInterleaveIO :: IO a -> IO a
 unsafeInterleaveIO (IO m)
   = IO ( \ s -> let
@@ -192,6 +234,10 @@ unsafeInterleaveIO (IO m)
                in
                (# s, r #))
 
+-- We believe that INLINE on unsafeInterleaveIO is safe, because the
+-- state from this IO thread is passed explicitly to the interleaved
+-- IO, so it cannot be floated out and shared.
+
 -- ---------------------------------------------------------------------------
 -- Handle type
 
@@ -247,6 +293,15 @@ instance Eq (MVar a) where
 -- enough information to identify the handle for debugging.  A handle is
 -- equal according to '==' only to itself; no attempt
 -- is made to compare the internal state of different handles for equality.
+--
+-- GHC note: a 'Handle' will be automatically closed when the garbage
+-- collector detects that it has become unreferenced by the program.
+-- However, relying on this behaviour is not generally recommended:
+-- the garbage collector is unpredictable.  If possible, use explicit
+-- an explicit 'hClose' to close 'Handle's when they are no longer
+-- required.  GHC does not currently attempt to free up file
+-- descriptors when they have run out, it is your responsibility to
+-- ensure that this doesn't happen.
 
 data Handle 
   = FileHandle                         -- A normal handle to a file
@@ -396,7 +451,7 @@ type FilePath = String
 -- but not less frequently, than specified above.
 -- The output buffer is emptied as soon as it has been written out.
 --
--- Similarly, input occurs according to the buffer mode for handle {\em hdl}.
+-- Similarly, input occurs according to the buffer mode for the handle:
 --
 --  * /line-buffering/: when the buffer for the handle is not empty,
 --    the next item is obtained from the buffer; otherwise, when the
@@ -408,8 +463,8 @@ type FilePath = String
 --    the next block of data is read into the buffer.
 --
 --  * /no-buffering/: the next input item is read and returned.
---    The 'hLookAhead' operation implies that even a no-buffered handle
---    may require a one-character buffer.
+--    The 'System.IO.hLookAhead' operation implies that even a no-buffered
+--    handle may require a one-character buffer.
 --
 -- The default buffering mode when a handle is opened is
 -- implementation-dependent and may depend on the file system object
@@ -518,7 +573,8 @@ showHandle file = showString "{handle: " . showString file . showString "}"
 -- |The type of exceptions.  Every kind of system-generated exception
 -- has a constructor in the 'Exception' type, and values of other
 -- types may be injected into 'Exception' by coercing them to
--- 'Dynamic' (see the section on Dynamic Exceptions: "Control.Exception\#DynamicExceptions").
+-- 'Data.Dynamic.Dynamic' (see the section on Dynamic Exceptions:
+-- "Control.Exception\#DynamicExceptions").
 data Exception
   = ArithException     ArithException
        -- ^Exceptions raised by arithmetic
@@ -537,8 +593,12 @@ data Exception
        -- ^Asynchronous exceptions (see section on Asynchronous Exceptions: "Control.Exception\#AsynchronousExceptions").
   | BlockedOnDeadMVar
        -- ^The current thread was executing a call to
-       -- 'takeMVar' that could never return, because there are no other
-       -- references to this 'MVar'.
+       -- 'Control.Concurrent.MVar.takeMVar' that could never return,
+       -- because there are no other references to this 'MVar'.
+  | BlockedIndefinitely
+       -- ^The current thread was waiting to retry an atomic memory transaction
+       -- that could never become possible to complete because there are no other
+       -- threads referring to any of teh TVars involved.
   | Deadlock
        -- ^There are no runnable threads, so the program is
        -- deadlocked.  The 'Deadlock' exception is
@@ -676,6 +736,7 @@ instance Show Exception where
   showsPrec _ (DynException _err)        = showString "unknown exception"
   showsPrec _ (AsyncException e)        = shows e
   showsPrec _ (BlockedOnDeadMVar)       = showString "thread blocked indefinitely"
+  showsPrec _ (BlockedIndefinitely)     = showString "thread blocked indefinitely"
   showsPrec _ (NonTermination)           = showString "<<loop>>"
   showsPrec _ (Deadlock)                 = showString "<<deadlock>>"
 
@@ -701,18 +762,17 @@ instance Eq Exception where
 -- -----------------------------------------------------------------------------
 -- The ExitCode type
 
--- The `ExitCode' type defines the exit codes that a program
--- can return.  `ExitSuccess' indicates successful termination;
--- and `ExitFailure code' indicates program failure
--- with value `code'.  The exact interpretation of `code'
--- is operating-system dependent.  In particular, some values of 
--- `code' may be prohibited (e.g. 0 on a POSIX-compliant system).
-
 -- We need it here because it is used in ExitException in the
 -- Exception datatype (above).
 
-data ExitCode = ExitSuccess | ExitFailure Int 
-                deriving (Eq, Ord, Read, Show)
+data ExitCode
+  = ExitSuccess        -- ^ indicates successful termination;
+  | ExitFailure Int
+               -- ^ indicates program failure with an exit code.
+               -- The exact interpretation of the code is
+               -- operating-system dependent.  In particular, some values
+               -- may be prohibited (e.g. 0 on a POSIX-compliant system).
+  deriving (Eq, Ord, Read, Show)
 
 -- --------------------------------------------------------------------------
 -- Primitive throw