import PrelByteArr ( ByteArray )
import PrelPack ( unpackNBytesAccST )
import PrelException ( ioError, catch )
+import PrelConc
#ifndef __PARALLEL_HASKELL__
import PrelForeign ( ForeignObj )
\begin{code}
hGetChar :: Handle -> IO Char
-hGetChar handle =
- wantReadableHandle "hGetChar" handle $ \ handle_ -> do
- let fo = haFO__ handle_
- intc <- mayBlock fo (fileGetc fo) -- ConcHask: UNSAFE, may block
- if intc /= ((-1)::Int)
- then return (chr intc)
- else constructErrorAndFail "hGetChar"
+hGetChar handle = do
+ c <- mayBlockRead "hGetChar" handle fileGetc
+ return (chr c)
{-
If EOF is reached before EOL is encountered, ignore the
\begin{code}
hLookAhead :: Handle -> IO Char
-hLookAhead handle =
- wantReadableHandle "hLookAhead" handle $ \ handle_ -> do
- let fo = haFO__ handle_
- intc <- mayBlock fo (fileLookAhead fo) -- ConcHask: UNSAFE, may block
- if intc /= (-1)
- then return (chr intc)
- else constructErrorAndFail "hLookAhead"
-
+hLookAhead handle = do
+ rc <- mayBlockRead "hLookAhead" handle fileLookAhead
+ return (chr rc)
\end{code}
\begin{code}
hIsEOF :: Handle -> IO Bool
-hIsEOF handle =
- wantReadableHandle "hIsEOF" handle $ \ handle_ -> do
- let fo = haFO__ handle_
- rc <- mayBlock fo (fileEOF fo) -- ConcHask: UNSAFE, may block
+hIsEOF handle = do
+ rc <- mayBlockRead "hIsEOF" handle fileEOF
case rc of
0 -> return False
1 -> return True
"hFillBufBA"
("illegal buffer size " ++ showsPrec 9 sz [])) -- 9 => should be parens'ified.
| otherwise =
- wantReadableHandle "hFillBufBA" handle $ \ handle_ -> do
- let fo = haFO__ handle_
- rc <- mayBlock fo (readChunkBA fo buf sz) -- ConcHask: UNSAFE, may block.
- if rc >= (0::Int)
- then return rc
- else constructErrorAndFail "hFillBufBA"
+ mayBlockRead "hFillBufBA" handle (\fo -> readChunkBA fo buf sz)
#endif
hFillBuf :: Handle -> Addr -> Int -> IO Int
"hFillBuf"
("illegal buffer size " ++ showsPrec 9 sz [])) -- 9 => should be parens'ified.
| otherwise =
- wantReadableHandle "hFillBuf" handle $ \ handle_ -> do
- let fo = haFO__ handle_
- rc <- mayBlock fo (readChunk fo buf sz) -- ConcHask: UNSAFE, may block.
- if rc >= 0
- then return rc
- else constructErrorAndFail "hFillBuf"
-
+ mayBlockRead "hFillBuf" handle (\fo -> readChunk fo buf sz)
\end{code}
The @hPutBuf hdl buf len@ action writes an already packed sequence of
mayBlock fo act -- output possible
_ -> do
return rc
+
+data MayBlock
+ = BlockRead Int
+ | BlockWrite Int
+ | NoBlock Int
+
+mayBlockRead :: String -> Handle -> (ForeignObj -> IO Int) -> IO Int
+mayBlockRead fname handle fn = do
+ r <- wantReadableHandle fname handle $ \ handle_ -> do
+ let fo = haFO__ handle_
+ rc <- fn fo
+ case rc of
+ -5 -> do -- (possibly blocking) read
+ fd <- getFileFd fo
+ return (BlockRead fd)
+ -6 -> do -- (possibly blocking) write
+ fd <- getFileFd fo
+ return (BlockWrite fd)
+ -7 -> do -- (possibly blocking) write on connected handle
+ fd <- getConnFileFd fo
+ return (BlockWrite fd)
+ _ ->
+ if rc >= 0
+ then return (NoBlock rc)
+ else constructErrorAndFail fname
+ case r of
+ BlockRead fd -> do
+ threadWaitRead fd
+ mayBlockRead fname handle fn
+ BlockWrite fd -> do
+ threadWaitWrite fd
+ mayBlockRead fname handle fn
+ NoBlock c -> return c
\end{code}
Foreign import declarations of helper functions: