X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FIOBase.lhs;h=a58ee7973093a8a2228dd0f12f95503b5a5518fe;hb=7316246c1797d46f5757ae156486f09b3db083d9;hp=be727dff1060d3724cbfefccfa9b10996505c40b;hpb=6be5e3277137f11000e7eb145d53009e157e7c90;p=ghc-base.git diff --git a/GHC/IOBase.lhs b/GHC/IOBase.lhs index be727df..a58ee79 100644 --- a/GHC/IOBase.lhs +++ b/GHC/IOBase.lhs @@ -1,5 +1,5 @@ \begin{code} -{-# OPTIONS -fno-implicit-prelude #-} +{-# OPTIONS_GHC -fno-implicit-prelude #-} ----------------------------------------------------------------------------- -- | -- Module : GHC.IOBase @@ -14,14 +14,40 @@ -- ----------------------------------------------------------------------------- -module GHC.IOBase where - +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 +138,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 +199,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 +213,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 +233,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 +292,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 +450,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 @@ -540,6 +594,10 @@ data Exception -- ^The current thread was executing a call to -- '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 @@ -677,6 +735,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 "<>" showsPrec _ (Deadlock) = showString "<>"