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
29 , IOArray -- instance of: Eq
63 , freeHaskellFunctionPtr
67 , hTell -- :: Handle -> IO HandlePosition
69 , hSetBinaryMode -- :: Handle -> Bool -> IO Bool
83 import PrelHandle ( openFileEx, IOModeEx(..),
84 hSetEcho, hGetEcho, getHandleFd
92 import IO ( hPutStr, hPutChar )
93 import PrelAddr ( Addr )
97 unsafePtrEq :: a -> a -> Bool
100 unsafePtrEq = primReallyUnsafePtrEquality
103 case reallyUnsafePtrEquality# a b of
110 newIORef :: a -> IO (IORef a)
111 readIORef :: IORef a -> IO a
112 writeIORef :: IORef a -> a -> IO ()
115 type IORef a = STRef RealWorld a
117 readIORef = readSTRef
118 writeIORef = writeSTRef
120 newtype IORef a = IORef (MutableVar RealWorld a)
123 newIORef v = stToIO (newVar v) >>= \ var -> return (IORef var)
124 readIORef (IORef var) = stToIO (readVar var)
125 writeIORef (IORef var) v = stToIO (writeVar var v)
128 updateIORef :: IORef a -> (a -> a) -> IO ()
129 updateIORef ref f = do
133 -- or should we return new value ? (or old?)
135 mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a))
136 mkWeakIORef r@(IORef (MutableVar r#)) f = IO $ \s ->
137 case mkWeak# r# r f s of (# s1, w #) -> (# s1, Weak w #)
141 newIOArray :: Ix ix => (ix,ix) -> elt -> IO (IOArray ix elt)
142 boundsIOArray :: Ix ix => IOArray ix elt -> (ix, ix)
143 readIOArray :: Ix ix => IOArray ix elt -> ix -> IO elt
144 writeIOArray :: Ix ix => IOArray ix elt -> ix -> elt -> IO ()
145 freezeIOArray :: Ix ix => IOArray ix elt -> IO (Array ix elt)
146 thawIOArray :: Ix ix => Array ix elt -> IO (IOArray ix elt)
148 unsafeFreezeIOArray :: Ix ix => IOArray ix elt -> IO (Array ix elt)
149 unsafeThawIOArray :: Ix ix => Array ix elt -> IO (IOArray ix elt)
153 type IOArray ix elt = STArray RealWorld ix elt
154 newIOArray = newSTArray
155 boundsIOArray = boundsSTArray
156 readIOArray = readSTArray
157 writeIOArray = writeSTArray
158 freezeIOArray = freezeSTArray
159 thawIOArray = thawSTArray
161 newtype IOArray ix elt = IOArray (MutableArray RealWorld ix elt)
165 stToIO (newArray ixs elt) >>= \arr ->
168 boundsIOArray (IOArray arr) = boundsOfArray arr
170 readIOArray (IOArray arr) ix = stToIO (readArray arr ix)
172 writeIOArray (IOArray arr) ix elt = stToIO (writeArray arr ix elt)
174 freezeIOArray (IOArray arr) = stToIO (freezeArray arr)
177 marr <- stToIO (thawArray arr)
178 return (IOArray marr)
180 unsafeFreezeIOArray (IOArray arr) = stToIO (unsafeFreezeArray arr)
181 unsafeThawIOArray arr = do
182 marr <- stToIO (unsafeThawArray arr)
183 return (IOArray marr)
188 {-# NOINLINE trace #-}
189 trace :: String -> a -> a
191 trace string expr = unsafePerformIO $ do
195 trace string expr = unsafePerformIO $ do
196 fd <- getHandleFd stderr
197 hPutStr stderr string
202 foreign import "PostTraceHook" postTraceHook :: Int -> IO ()
207 Not something you want to call normally, but useful
208 in the cases where you do want to flush stuff out of
209 the heap or make sure you've got room enough
213 foreign import "performGC" performGC :: IO ()
217 When using 'foreign export dynamic' to dress up a Haskell
218 IO action to look like a C function pointer, a little bit
219 of memory is allocated (along with a stable pointer to
220 the Haskell IO action). When done with the C function
221 pointer, you'll need to call @freeHaskellFunctionPtr()@ to
222 let go of these resources - here's the Haskell wrapper for
223 that RTS entry point, should you want to free it from
227 foreign import ccall "freeHaskellFunctionPtr"
228 freeHaskellFunctionPtr :: Addr -> IO ()
234 Support for redirecting I/O on a handle to another for the
235 duration of an IO action. To re-route a handle, it is first
236 flushed, followed by replacing its innards (i.e., FILE_OBJECT)
237 with that of the other. This happens before and after the
240 If the action raises an exception, the handle is replaced back
241 to its old contents, but without flushing it first - as this
242 may provoke exceptions. Notice that the action may perform
243 I/O on either Handle, with the result that the I/O is interleaved.
244 (Why you would want to do this, is a completely different matter.)
246 ToDo: probably want to restrict what kind of handles can be
247 replaced with another - i.e., don't want to be able to replace
248 a writeable handle with a readable one.
251 withHandleFor :: Handle
255 withHandleFor h1 h2 act = do
261 h2_fo <- withHandle h2 $ \ h2_ -> return (h2_{haFO__=h1_fo}, haFO__ h2_)
262 catch (act >>= \ x -> hFlush h2 >> setFO h2 h2_fo >> return x)
263 (\ err -> setFO h2 h2_fo >> ioError err)
266 withHandle h $ \ h_ -> return (h_{haFO__=fo}, ())
269 wantRWHandle "withHandleFor" h $ \ h_ ->
274 Derived @withHandleFor@ combinators and, at the moment, these
275 are exported from @IOExts@ and not @withHandleFor@ itself.
278 withStdin h a = withHandleFor h stdin a
279 withStdout h a = withHandleFor h stdout a
280 withStderr h a = withHandleFor h stderr a
283 @hTell@ is the lower-level version of @hGetPosn@ - return the
284 position, without bundling it together with the handle itself:
287 hTell :: Handle -> IO HandlePosition
289 (HandlePosn _ x) <- hGetPosn h
293 @hSetBinaryMode@ lets you change the translation mode for a handle.
294 On some platforms (e.g., Win32) a distinction is made between being in
295 'text mode' or 'binary mode', with the former terminating lines
296 by \r\n rather than just \n.
298 Debating the Winnitude or otherwise of such a scheme is less than
299 interesting -- it's there, so we have to cope.
301 A side-effect of calling @hSetBinaryMode@ is that the output buffer
302 (if any) is flushed prior to changing the translation mode.
305 hSetBinaryMode :: Handle -> Bool -> IO Bool
306 hSetBinaryMode handle is_binary = do
307 -- is_binary = True => set translation mode to binary.
308 wantRWHandle "hSetBinaryMode" handle $ \ handle_ -> do
309 let fo = haFO__ handle_
310 rc <- setBinaryMode fo flg
314 constructErrorAndFail "hSetBinaryMode"