{-# LANGUAGE Unsafe #-}
{-# LANGUAGE ExistentialQuantification, NoImplicitPrelude #-}
module GHC.Event.Internal
(
Backend
, backend
, delete
, poll
, modifyFd
, modifyFdOnce
, Event
, evtRead
, evtWrite
, evtClose
, eventIs
, Lifetime(..)
, EventLifetime
, eventLifetime
, elLifetime
, elEvent
, Timeout(..)
, throwErrnoIfMinus1NoRetry
) where
import Data.Bits ((.|.), (.&.))
import Data.OldList (foldl', filter, intercalate, null)
import Foreign.C.Error (eINTR, getErrno, throwErrno)
import System.Posix.Types (Fd)
import GHC.Base
import GHC.Word (Word64)
import GHC.Num (Num(..))
import GHC.Show (Show(..))
import Data.Semigroup.Internal (stimesMonoid)
newtype Event = Event Int
deriving Eq
evtNothing :: Event
evtNothing :: Event
evtNothing = Int -> Event
Event 0
{-# INLINE evtNothing #-}
evtRead :: Event
evtRead :: Event
evtRead = Int -> Event
Event 1
{-# INLINE evtRead #-}
evtWrite :: Event
evtWrite :: Event
evtWrite = Int -> Event
Event 2
{-# INLINE evtWrite #-}
evtClose :: Event
evtClose :: Event
evtClose = Int -> Event
Event 4
{-# INLINE evtClose #-}
eventIs :: Event -> Event -> Bool
eventIs :: Event -> Event -> Bool
eventIs (Event a :: Int
a) (Event b :: Int
b) = Int
a Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
instance Show Event where
show :: Event -> String
show e :: Event
e = '[' Char -> ShowS
forall a. a -> [a] -> [a]
: (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate "," ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Bool
forall a. [a] -> Bool
null) ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
[Event
evtRead Event -> ShowS
`so` "evtRead",
Event
evtWrite Event -> ShowS
`so` "evtWrite",
Event
evtClose Event -> ShowS
`so` "evtClose"]) String -> ShowS
forall a. [a] -> [a] -> [a]
++ "]"
where ev :: Event
ev so :: Event -> ShowS
`so` disp :: String
disp | Event
e Event -> Event -> Bool
`eventIs` Event
ev = String
disp
| Bool
otherwise = ""
instance Semigroup Event where
<> :: Event -> Event -> Event
(<>) = Event -> Event -> Event
evtCombine
stimes :: b -> Event -> Event
stimes = b -> Event -> Event
forall b a. (Integral b, Monoid a) => b -> a -> a
stimesMonoid
instance Monoid Event where
mempty :: Event
mempty = Event
evtNothing
mconcat :: [Event] -> Event
mconcat = [Event] -> Event
evtConcat
evtCombine :: Event -> Event -> Event
evtCombine :: Event -> Event -> Event
evtCombine (Event a :: Int
a) (Event b :: Int
b) = Int -> Event
Event (Int
a Int -> Int -> Int
forall a. Bits a => a -> a -> a
.|. Int
b)
{-# INLINE evtCombine #-}
evtConcat :: [Event] -> Event
evtConcat :: [Event] -> Event
evtConcat = (Event -> Event -> Event) -> Event -> [Event] -> Event
forall a b. (b -> a -> b) -> b -> [a] -> b
foldl' Event -> Event -> Event
evtCombine Event
evtNothing
{-# INLINE evtConcat #-}
data Lifetime = OneShot
| MultiShot
deriving ( Show
, Eq
)
elSupremum :: Lifetime -> Lifetime -> Lifetime
elSupremum :: Lifetime -> Lifetime -> Lifetime
elSupremum OneShot OneShot = Lifetime
OneShot
elSupremum _ _ = Lifetime
MultiShot
{-# INLINE elSupremum #-}
instance Semigroup Lifetime where
<> :: Lifetime -> Lifetime -> Lifetime
(<>) = Lifetime -> Lifetime -> Lifetime
elSupremum
stimes :: b -> Lifetime -> Lifetime
stimes = b -> Lifetime -> Lifetime
forall b a. (Integral b, Monoid a) => b -> a -> a
stimesMonoid
instance Monoid Lifetime where
mempty :: Lifetime
mempty = Lifetime
OneShot
newtype EventLifetime = EL Int
deriving ( Show
, Eq
)
instance Semigroup EventLifetime where
EL a :: Int
a <> :: EventLifetime -> EventLifetime -> EventLifetime
<> EL b :: Int
b = Int -> EventLifetime
EL (Int
a Int -> Int -> Int
forall a. Bits a => a -> a -> a
.|. Int
b)
instance Monoid EventLifetime where
mempty :: EventLifetime
mempty = Int -> EventLifetime
EL 0
eventLifetime :: Event -> Lifetime -> EventLifetime
eventLifetime :: Event -> Lifetime -> EventLifetime
eventLifetime (Event e :: Int
e) l :: Lifetime
l = Int -> EventLifetime
EL (Int
e Int -> Int -> Int
forall a. Bits a => a -> a -> a
.|. Lifetime -> Int
forall p. Num p => Lifetime -> p
lifetimeBit Lifetime
l)
where
lifetimeBit :: Lifetime -> p
lifetimeBit OneShot = 0
lifetimeBit MultiShot = 8
{-# INLINE eventLifetime #-}
elLifetime :: EventLifetime -> Lifetime
elLifetime :: EventLifetime -> Lifetime
elLifetime (EL x :: Int
x) = if Int
x Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 0 then Lifetime
OneShot else Lifetime
MultiShot
{-# INLINE elLifetime #-}
elEvent :: EventLifetime -> Event
elEvent :: EventLifetime -> Event
elEvent (EL x :: Int
x) = Int -> Event
Event (Int
x Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 0x7)
{-# INLINE elEvent #-}
data Timeout = Timeout {-# UNPACK #-} !Word64
| Forever
deriving Show
data Backend = forall a. Backend {
()
_beState :: !a
, ()
_bePoll :: a
-> Maybe Timeout
-> (Fd -> Event -> IO ())
-> IO Int
, ()
_beModifyFd :: a
-> Fd
-> Event
-> Event
-> IO Bool
, ()
_beModifyFdOnce :: a
-> Fd
-> Event
-> IO Bool
, ()
_beDelete :: a -> IO ()
}
backend :: (a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int)
-> (a -> Fd -> Event -> Event -> IO Bool)
-> (a -> Fd -> Event -> IO Bool)
-> (a -> IO ())
-> a
-> Backend
backend :: (a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int)
-> (a -> Fd -> Event -> Event -> IO Bool)
-> (a -> Fd -> Event -> IO Bool)
-> (a -> IO ())
-> a
-> Backend
backend bPoll :: a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int
bPoll bModifyFd :: a -> Fd -> Event -> Event -> IO Bool
bModifyFd bModifyFdOnce :: a -> Fd -> Event -> IO Bool
bModifyFdOnce bDelete :: a -> IO ()
bDelete state :: a
state =
a
-> (a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int)
-> (a -> Fd -> Event -> Event -> IO Bool)
-> (a -> Fd -> Event -> IO Bool)
-> (a -> IO ())
-> Backend
forall a.
a
-> (a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int)
-> (a -> Fd -> Event -> Event -> IO Bool)
-> (a -> Fd -> Event -> IO Bool)
-> (a -> IO ())
-> Backend
Backend a
state a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int
bPoll a -> Fd -> Event -> Event -> IO Bool
bModifyFd a -> Fd -> Event -> IO Bool
bModifyFdOnce a -> IO ()
bDelete
{-# INLINE backend #-}
poll :: Backend -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int
poll :: Backend -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int
poll (Backend bState :: a
bState bPoll :: a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int
bPoll _ _ _) = a -> Maybe Timeout -> (Fd -> Event -> IO ()) -> IO Int
bPoll a
bState
{-# INLINE poll #-}
modifyFd :: Backend -> Fd -> Event -> Event -> IO Bool
modifyFd :: Backend -> Fd -> Event -> Event -> IO Bool
modifyFd (Backend bState :: a
bState _ bModifyFd :: a -> Fd -> Event -> Event -> IO Bool
bModifyFd _ _) = a -> Fd -> Event -> Event -> IO Bool
bModifyFd a
bState
{-# INLINE modifyFd #-}
modifyFdOnce :: Backend -> Fd -> Event -> IO Bool
modifyFdOnce :: Backend -> Fd -> Event -> IO Bool
modifyFdOnce (Backend bState :: a
bState _ _ bModifyFdOnce :: a -> Fd -> Event -> IO Bool
bModifyFdOnce _) = a -> Fd -> Event -> IO Bool
bModifyFdOnce a
bState
{-# INLINE modifyFdOnce #-}
delete :: Backend -> IO ()
delete :: Backend -> IO ()
delete (Backend bState :: a
bState _ _ _ bDelete :: a -> IO ()
bDelete) = a -> IO ()
bDelete a
bState
{-# INLINE delete #-}
throwErrnoIfMinus1NoRetry :: (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1NoRetry :: String -> IO a -> IO a
throwErrnoIfMinus1NoRetry loc :: String
loc f :: IO a
f = do
a
res <- IO a
f
if a
res a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== -1
then do
Errno
err <- IO Errno
getErrno
if Errno
err Errno -> Errno -> Bool
forall a. Eq a => a -> a -> Bool
== Errno
eINTR then a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return 0 else String -> IO a
forall a. String -> IO a
throwErrno String
loc
else a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
res