Skip to content

Instantly share code, notes, and snippets.

@nh2
Created September 28, 2017 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nh2/6f571ce00667bc49d845ab4c8fdf9769 to your computer and use it in GitHub Desktop.
Save nh2/6f571ce00667bc49d845ab4c8fdf9769 to your computer and use it in GitHub Desktop.
Shows how hWaitForInput eventually calls sycalls in GHC Haskell
-- Call chain of hWaitForInput:
--
-- hWaitForInput
-- ready from the IODevice typeclass for type FD (from haDevice of a Handle__)
-- ready from base/GHC.IO.FD
-- fdReady foreign import from base/GHC.IO.FD
-- Exact locations and code:
-- http://hackage.haskell.org/package/base-4.10.0.0/docs/src/GHC.IO.Handle.Text.html#local-6989586621679305954
hWaitForInput :: Handle -> Int -> IO Bool
hWaitForInput h msecs = do
wantReadableHandle_ "hWaitForInput" h $ \ handle_@Handle__{..} -> do
cbuf <- readIORef haCharBuffer
if not (isEmptyBuffer cbuf) then return True else do
if msecs < 0
then do cbuf' <- readTextDevice handle_ cbuf
writeIORef haCharBuffer cbuf'
return True
else do
-- there might be bytes in the byte buffer waiting to be decoded
cbuf' <- decodeByteBuf handle_ cbuf
writeIORef haCharBuffer cbuf'
if not (isEmptyBuffer cbuf') then return True else do
r <- IODevice.ready haDevice False{-read-} msecs -------ready call HERE
if r then do -- Call hLookAhead' to throw an EOF
-- exception if appropriate
_ <- hLookAhead_ handle_
return True
else return False
-- http://hackage.haskell.org/package/base-4.10.0.0/docs/GHC-IO-Device.html#t:IODevice
class IODevice a where
-- | @ready dev write msecs@ returns 'True' if the device has data
-- to read (if @write@ is 'False') or space to write new data (if
-- @write@ is 'True'). @msecs@ specifies how long to wait, in
-- milliseconds.
--
ready :: a -> Bool -> Int -> IO Bool
-- https://github.com/ghc/ghc/blob/ghc-8.2.1-release/libraries/base/GHC/IO/FD.hs#L103
instance GHC.IO.Device.IODevice FD where
ready = ready
-- https://github.com/ghc/ghc/blob/ghc-8.2.1-release/libraries/base/GHC/IO/FD.hs#L395
ready :: FD -> Bool -> Int -> IO Bool
ready fd write msecs = do
r <- throwErrnoIfMinus1Retry "GHC.IO.FD.ready" $
fdReady (fdFD fd) (fromIntegral $ fromEnum $ write)
(fromIntegral msecs)
#if defined(mingw32_HOST_OS)
(fromIntegral $ fromEnum $ fdIsSocket fd)
#else
0
#endif
return (toEnum (fromIntegral r))
-- https://github.com/ghc/ghc/blob/ghc-8.2.1-release/libraries/base/GHC/IO/FD.hs#L407
foreign import ccall safe "fdReady"
fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment