1 {-# LANGUAGE BangPatterns, ForeignFunctionInterface, NoImplicitPrelude #-}
3 module System.Event.Thread
5 ensureIOManagerIsRunning
12 import Data.IORef (IORef, newIORef, readIORef, writeIORef)
13 import Data.Maybe (Maybe(..))
14 import Foreign.Ptr (Ptr)
16 import GHC.Conc.Sync (TVar, ThreadId, ThreadStatus(..), atomically, forkIO,
17 labelThread, modifyMVar_, newTVar, sharedCAF,
18 threadStatus, writeTVar)
19 import GHC.MVar (MVar, newEmptyMVar, newMVar, putMVar, takeMVar)
20 import System.Event.Manager (Event, EventManager, evtRead, evtWrite, loop,
21 new, registerFd, unregisterFd_, registerTimeout)
22 import System.IO.Unsafe (unsafePerformIO)
23 import System.Posix.Types (Fd)
25 -- | Suspends the current thread for a given number of microseconds
28 -- There is no guarantee that the thread will be rescheduled promptly
29 -- when the delay has expired, but the thread will never continue to
30 -- run /earlier/ than specified.
31 threadDelay :: Int -> IO ()
32 threadDelay usecs = do
33 Just mgr <- readIORef eventManager
35 _ <- registerTimeout mgr usecs (putMVar m ())
38 -- | Set the value of returned TVar to True after a given number of
39 -- microseconds. The caveats associated with threadDelay also apply.
41 registerDelay :: Int -> IO (TVar Bool)
42 registerDelay usecs = do
43 t <- atomically $ newTVar False
44 Just mgr <- readIORef eventManager
45 _ <- registerTimeout mgr usecs . atomically $ writeTVar t True
48 -- | Block the current thread until data is available to read from the
49 -- given file descriptor.
50 threadWaitRead :: Fd -> IO ()
51 threadWaitRead = threadWait evtRead
52 {-# INLINE threadWaitRead #-}
54 -- | Block the current thread until the given file descriptor can
55 -- accept data to write.
56 threadWaitWrite :: Fd -> IO ()
57 threadWaitWrite = threadWait evtWrite
58 {-# INLINE threadWaitWrite #-}
60 threadWait :: Event -> Fd -> IO ()
61 threadWait evt fd = do
63 Just mgr <- readIORef eventManager
64 _ <- registerFd mgr (\reg _ -> unregisterFd_ mgr reg >> putMVar m ()) fd evt
67 foreign import ccall unsafe "getOrSetSystemEventThreadEventManagerStore"
68 getOrSetSystemEventThreadEventManagerStore :: Ptr a -> IO (Ptr a)
70 eventManager :: IORef (Maybe EventManager)
71 eventManager = unsafePerformIO $ do
72 em <- newIORef Nothing
73 sharedCAF em getOrSetSystemEventThreadEventManagerStore
74 {-# NOINLINE eventManager #-}
76 foreign import ccall unsafe "getOrSetSystemEventThreadIOManagerThreadStore"
77 getOrSetSystemEventThreadIOManagerThreadStore :: Ptr a -> IO (Ptr a)
79 {-# NOINLINE ioManager #-}
80 ioManager :: MVar (Maybe ThreadId)
81 ioManager = unsafePerformIO $ do
83 sharedCAF m getOrSetSystemEventThreadIOManagerThreadStore
85 ensureIOManagerIsRunning :: IO ()
86 ensureIOManagerIsRunning
87 | not threaded = return ()
88 | otherwise = modifyMVar_ ioManager $ \old -> do
91 writeIORef eventManager $ Just mgr
92 !t <- forkIO $ loop mgr
93 labelThread t "IOManager"
100 ThreadFinished -> create
104 foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool