{-# language BangPatterns #-}
{-# language MagicHash #-}
{-# language UnliftedFFITypes #-}
{-# language ScopedTypeVariables #-}

module Posix.Poll
  ( uninterruptiblePoll
  , uninterruptiblePollMutablePrimArray
  , PollFd(..)
  , Exchange(..)
  , PT.input
  , PT.output
  , PT.error
  , PT.hangup
  , PT.invalid
  , PT.isSubeventOf
  ) where

import Posix.Types (CNfds(..))
import Foreign.C.Error (Errno,getErrno)
import Foreign.C.Types (CInt(..))
import GHC.Ptr (Ptr)
import GHC.Exts (RealWorld,MutableByteArray#)
import Posix.Poll.Types (PollFd(..),Exchange(..))
import Data.Primitive (MutablePrimArray(..))

import qualified Posix.Poll.Types as PT

foreign import ccall unsafe "poll.h poll"
  c_poll_ptr :: Ptr PollFd -> CNfds -> CInt -> IO CInt

foreign import ccall unsafe "poll.h poll"
  c_poll_prim_array :: MutableByteArray# RealWorld -> CNfds -> CInt -> IO CInt

-- | The @timeout@ argument is omitted since it is nonsense to choose
--   anything other than 0 when using the unsafe FFI.
uninterruptiblePoll ::
     Ptr PollFd
  -> CNfds
  -> IO (Either Errno CInt)
uninterruptiblePoll :: Ptr PollFd -> CNfds -> IO (Either Errno CInt)
uninterruptiblePoll Ptr PollFd
pfds CNfds
n =
  Ptr PollFd -> CNfds -> CInt -> IO CInt
c_poll_ptr Ptr PollFd
pfds CNfds
n CInt
0 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= CInt -> IO (Either Errno CInt)
errorsFromInt

uninterruptiblePollMutablePrimArray ::
     MutablePrimArray RealWorld PollFd
  -> CNfds
  -> IO (Either Errno CInt)
uninterruptiblePollMutablePrimArray :: MutablePrimArray RealWorld PollFd
-> CNfds -> IO (Either Errno CInt)
uninterruptiblePollMutablePrimArray (MutablePrimArray MutableByteArray# RealWorld
pfds) CNfds
n =
  MutableByteArray# RealWorld -> CNfds -> CInt -> IO CInt
c_poll_prim_array MutableByteArray# RealWorld
pfds CNfds
n CInt
0 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= CInt -> IO (Either Errno CInt)
errorsFromInt

errorsFromInt :: CInt -> IO (Either Errno CInt)
errorsFromInt :: CInt -> IO (Either Errno CInt)
errorsFromInt CInt
r = if CInt
r forall a. Ord a => a -> a -> Bool
>= CInt
0
  then forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. b -> Either a b
Right CInt
r)
  else forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. a -> Either a b
Left IO Errno
getErrno