unix-bytestring-0.3.5: src/Foreign/C/Error/Safe.hs
{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
----------------------------------------------------------------
-- 2011.06.29
-- |
-- Module : Foreign.C.Error.Safe
-- Copyright : Copyright (c) 2010--2011 wren ng thornton
-- License : BSD
-- Maintainer : wren@community.haskell.org
-- Stability : provisional
-- Portability : portable (H98+FFI)
--
-- Provides a variant of the "Foreign.C.Error" API which returns
-- errors explicitly, instead of throwing exceptions.
--
-- /Since: 0.3.5/
----------------------------------------------------------------
module Foreign.C.Error.Safe
(
-- * Primitive handlers
eitherErrnoIf
, eitherErrnoIfRetry
, eitherErrnoIfRetryMayBlock
-- * Derived handlers
-- ** With predicate @(-1 ==)@
, eitherErrnoIfMinus1
, eitherErrnoIfMinus1Retry
, eitherErrnoIfMinus1RetryMayBlock
-- ** With predicate @(nullPtr ==)@
, eitherErrnoIfNull
, eitherErrnoIfNullRetry
, eitherErrnoIfNullRetryMayBlock
) where
import qualified Foreign.C.Error as C
import qualified Foreign.Ptr as FFI
----------------------------------------------------------------
----------------------------------------------------------------
-- | A variant of 'C.throwErrnoIf' which returns @Either@ instead
-- of throwing an errno error.
eitherErrnoIf
:: (a -> Bool) -- ^ Predicate to apply to the result value of
-- the @IO@ operation.
-> IO a -- ^ The @IO@ operation to be executed.
-> IO (Either C.Errno a)
eitherErrnoIf p io = do
a <- io
if p a
then do
errno <- C.getErrno
return (Left errno)
else return (Right a)
-- | A variant of 'C.throwErrnoIfRetry' which returns @Either@
-- instead of throwing an errno error.
eitherErrnoIfRetry
:: (a -> Bool) -- ^ Predicate to apply to the result value of
-- the @IO@ operation.
-> IO a -- ^ The @IO@ operation to be executed.
-> IO (Either C.Errno a)
eitherErrnoIfRetry p io = loop
where
loop = do
a <- io
if p a
then do
errno <- C.getErrno
if errno == C.eINTR
then loop
else return (Left errno)
else return (Right a)
-- | A variant of 'C.throwErrnoIfRetryMayBlock' which returns
-- @Either@ instead of throwing an errno error.
eitherErrnoIfRetryMayBlock
:: (a -> Bool) -- ^ Predicate to apply to the result value of
-- the @IO@ operation.
-> IO a -- ^ The @IO@ operation to be executed.
-> IO b -- ^ Action to execute before retrying if an
-- immediate retry would block.
-> IO (Either C.Errno a)
eitherErrnoIfRetryMayBlock p f on_block = loop
where
loop = do
a <- f
if p a
then do
errno <- C.getErrno
if errno == C.eINTR
then loop
else if errno == C.eWOULDBLOCK || errno == C.eAGAIN
then on_block >> loop
else return (Left errno)
else return (Right a)
----------------------------------------------------------------
eitherErrnoIfMinus1 :: (Num a) => IO a -> IO (Either C.Errno a)
eitherErrnoIfMinus1 = eitherErrnoIf (-1 ==)
eitherErrnoIfMinus1Retry :: (Num a) => IO a -> IO (Either C.Errno a)
eitherErrnoIfMinus1Retry = eitherErrnoIfRetry (-1 ==)
eitherErrnoIfMinus1RetryMayBlock
:: (Num a) => IO a -> IO b -> IO (Either C.Errno a)
eitherErrnoIfMinus1RetryMayBlock =
eitherErrnoIfRetryMayBlock (-1 ==)
eitherErrnoIfNull :: IO (FFI.Ptr a) -> IO (Either C.Errno (FFI.Ptr a))
eitherErrnoIfNull = eitherErrnoIf (== FFI.nullPtr)
eitherErrnoIfNullRetry :: IO (FFI.Ptr a) -> IO (Either C.Errno (FFI.Ptr a))
eitherErrnoIfNullRetry = eitherErrnoIfRetry (== FFI.nullPtr)
eitherErrnoIfNullRetryMayBlock
:: IO (FFI.Ptr a) -> IO b -> IO (Either C.Errno (FFI.Ptr a))
eitherErrnoIfNullRetryMayBlock =
eitherErrnoIfRetryMayBlock (== FFI.nullPtr)
----------------------------------------------------------------
----------------------------------------------------------- fin.