2 % (c) The AQUA Project, Glasgow University, 1994-1996
4 \section[IOExts]{Module @IOExts@}
6 @IOExts@ provides useful functionality that fall outside the
7 standard Haskell IO interface. Expect the contents of IOExts
8 to be the same for Hugs and GHC (same goes for any other
9 Hugs/GHC extension libraries, unless a function/type is
10 explicitly flagged as being implementation specific
14 {-# OPTIONS -fno-implicit-prelude #-}
21 , IORef -- instance of: Eq
28 , IOArray -- instance of: Eq
62 , freeHaskellFunctionPtr
66 , hTell -- :: Handle -> IO HandlePosition
68 , hSetBinaryMode -- :: Handle -> Bool -> IO Bool
82 import PrelHandle ( openFileEx, IOModeEx(..),
83 hSetEcho, hGetEcho, getHandleFd
91 import IO ( hPutStr, hPutChar )
92 import PrelAddr ( Addr )
96 unsafePtrEq :: a -> a -> Bool
99 unsafePtrEq = primReallyUnsafePtrEquality
102 case reallyUnsafePtrEquality# a b of
109 newIORef :: a -> IO (IORef a)
110 readIORef :: IORef a -> IO a
111 writeIORef :: IORef a -> a -> IO ()
114 type IORef a = STRef RealWorld a
116 readIORef = readSTRef
117 writeIORef = writeSTRef
119 newtype IORef a = IORef (MutableVar RealWorld a)
122 newIORef v = stToIO (newVar v) >>= \ var -> return (IORef var)
123 readIORef (IORef var) = stToIO (readVar var)
124 writeIORef (IORef var) v = stToIO (writeVar var v)
127 mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a))
128 mkWeakIORef r@(IORef (MutableVar r#)) f = IO $ \s ->
129 case mkWeak# r# r f s of (# s1, w #) -> (# s1, Weak w #)
133 newIOArray :: Ix ix => (ix,ix) -> elt -> IO (IOArray ix elt)
134 boundsIOArray :: Ix ix => IOArray ix elt -> (ix, ix)
135 readIOArray :: Ix ix => IOArray ix elt -> ix -> IO elt
136 writeIOArray :: Ix ix => IOArray ix elt -> ix -> elt -> IO ()
137 freezeIOArray :: Ix ix => IOArray ix elt -> IO (Array ix elt)
138 thawIOArray :: Ix ix => Array ix elt -> IO (IOArray ix elt)
140 unsafeFreezeIOArray :: Ix ix => IOArray ix elt -> IO (Array ix elt)
141 unsafeThawIOArray :: Ix ix => Array ix elt -> IO (IOArray ix elt)
145 type IOArray ix elt = STArray RealWorld ix elt
146 newIOArray = newSTArray
147 boundsIOArray = boundsSTArray
148 readIOArray = readSTArray
149 writeIOArray = writeSTArray
150 freezeIOArray = freezeSTArray
151 thawIOArray = thawSTArray
153 newtype IOArray ix elt = IOArray (MutableArray RealWorld ix elt)
157 stToIO (newArray ixs elt) >>= \arr ->
160 boundsIOArray (IOArray arr) = boundsOfArray arr
162 readIOArray (IOArray arr) ix = stToIO (readArray arr ix)
164 writeIOArray (IOArray arr) ix elt = stToIO (writeArray arr ix elt)
166 freezeIOArray (IOArray arr) = stToIO (freezeArray arr)
169 marr <- stToIO (thawArray arr)
170 return (IOArray marr)
172 unsafeFreezeIOArray (IOArray arr) = stToIO (unsafeFreezeArray arr)
173 unsafeThawIOArray arr = do
174 marr <- stToIO (unsafeThawArray arr)
175 return (IOArray marr)
180 {-# NOINLINE trace #-}
181 trace :: String -> a -> a
183 trace string expr = unsafePerformIO $ do
187 trace string expr = unsafePerformIO $ do
188 fd <- getHandleFd stderr
189 hPutStr stderr string
194 foreign import "PostTraceHook" postTraceHook :: Int -> IO ()
199 Not something you want to call normally, but useful
200 in the cases where you do want to flush stuff out of
201 the heap or make sure you've got room enough
205 foreign import "performGC" performGC :: IO ()
209 When using 'foreign export dynamic' to dress up a Haskell
210 IO action to look like a C function pointer, a little bit
211 of memory is allocated (along with a stable pointer to
212 the Haskell IO action). When done with the C function
213 pointer, you'll need to call @freeHaskellFunctionPtr()@ to
214 let go of these resources - here's the Haskell wrapper for
215 that RTS entry point, should you want to free it from
219 foreign import ccall "freeHaskellFunctionPtr"
220 freeHaskellFunctionPtr :: Addr -> IO ()
226 Support for redirecting I/O on a handle to another for the
227 duration of an IO action. To re-route a handle, it is first
228 flushed, followed by replacing its innards (i.e., FILE_OBJECT)
229 with that of the other. This happens before and after the
232 If the action raises an exception, the handle is replaced back
233 to its old contents, but without flushing it first - as this
234 may provoke exceptions. Notice that the action may perform
235 I/O on either Handle, with the result that the I/O is interleaved.
236 (Why you would want to do this, is a completely different matter.)
238 ToDo: probably want to restrict what kind of handles can be
239 replaced with another - i.e., don't want to be able to replace
240 a writeable handle with a readable one.
243 withHandleFor :: Handle
247 withHandleFor h1 h2 act = do
253 h2_fo <- withHandle h2 $ \ h2_ -> return (h2_{haFO__=h1_fo}, haFO__ h2_)
254 catch (act >>= \ x -> hFlush h2 >> setFO h2 h2_fo >> return x)
255 (\ err -> setFO h2 h2_fo >> ioError err)
258 withHandle h $ \ h_ -> return (h_{haFO__=fo}, ())
261 wantRWHandle "withHandleFor" h $ \ h_ ->
266 Derived @withHandleFor@ combinators and, at the moment, these
267 are exported from @IOExts@ and not @withHandleFor@ itself.
270 withStdin h a = withHandleFor h stdin a
271 withStdout h a = withHandleFor h stdout a
272 withStderr h a = withHandleFor h stderr a
275 @hTell@ is the lower-level version of @hGetPosn@ - return the
276 position, without bundling it together with the handle itself:
279 hTell :: Handle -> IO HandlePosition
281 (HandlePosn _ x) <- hGetPosn h
285 @hSetBinaryMode@ lets you change the translation mode for a handle.
286 On some platforms (e.g., Win32) a distinction is made between being in
287 'text mode' or 'binary mode', with the former terminating lines
288 by \r\n rather than just \n.
290 Debating the Winnitude or otherwise of such a scheme is less than
291 interesting -- it's there, so we have to cope.
293 A side-effect of calling @hSetBinaryMode@ is that the output buffer
294 (if any) is flushed prior to changing the translation mode.
297 hSetBinaryMode :: Handle -> Bool -> IO Bool
298 hSetBinaryMode handle is_binary = do
299 -- is_binary = True => set translation mode to binary.
300 wantRWHandle "hSetBinaryMode" handle $ \ handle_ -> do
301 let fo = haFO__ handle_
302 rc <- setBinaryMode fo flg
306 constructErrorAndFail "hSetBinaryMode"