diff -rN -u old-base/base.cabal new-base/base.cabal
|
old
|
new
|
|
| 1 | 1 | name: base |
| 2 | | version: 4.3.0.0 |
| | 2 | version: 4.3.1.0 |
| 3 | 3 | license: BSD3 |
| 4 | 4 | license-file: LICENSE |
| 5 | 5 | maintainer: libraries@haskell.org |
diff -rN -u old-base/Control/Concurrent.hs new-base/Control/Concurrent.hs
|
old
|
new
|
|
| 47 | 47 | threadDelay, -- :: Int -> IO () |
| 48 | 48 | threadWaitRead, -- :: Int -> IO () |
| 49 | 49 | threadWaitWrite, -- :: Int -> IO () |
| | 50 | closeFd, -- :: (Int -> IO ()) -> Int -> IO () |
| 50 | 51 | #endif |
| 51 | 52 | |
| 52 | 53 | -- * Communication abstractions |
| … |
… |
|
| 450 | 451 | |
| 451 | 452 | -- | Block the current thread until data is available to read on the |
| 452 | 453 | -- given file descriptor (GHC only). |
| | 454 | -- |
| | 455 | -- This will throw an 'IOError' if the file descriptor was closed |
| | 456 | -- while this thread was blocked. |
| 453 | 457 | threadWaitRead :: Fd -> IO () |
| 454 | 458 | threadWaitRead fd |
| 455 | 459 | #ifdef mingw32_HOST_OS |
| … |
… |
|
| 470 | 474 | |
| 471 | 475 | -- | Block the current thread until data can be written to the |
| 472 | 476 | -- given file descriptor (GHC only). |
| | 477 | -- |
| | 478 | -- This will throw an 'IOError' if the file descriptor was closed |
| | 479 | -- while this thread was blocked. |
| 473 | 480 | threadWaitWrite :: Fd -> IO () |
| 474 | 481 | threadWaitWrite fd |
| 475 | 482 | #ifdef mingw32_HOST_OS |
| … |
… |
|
| 479 | 486 | = GHC.Conc.threadWaitWrite fd |
| 480 | 487 | #endif |
| 481 | 488 | |
| | 489 | -- | Close a file descriptor in a concurrency-safe way (GHC only). If |
| | 490 | -- you are using 'threadWaitRead' or 'threadWaitWrite' to perform |
| | 491 | -- blocking I\/O, you /must/ use this function to close file |
| | 492 | -- descriptors, or blocked threads may not be woken. |
| | 493 | -- |
| | 494 | -- Any threads that are blocked on the file descriptor via |
| | 495 | -- 'threadWaitRead' or 'threadWaitWrite' will be unblocked by having |
| | 496 | -- IO exceptions thrown. |
| | 497 | closeFd :: (Fd -> IO ()) -- ^ Low-level action that performs the real close. |
| | 498 | -> Fd -- ^ File descriptor to close. |
| | 499 | -> IO () |
| | 500 | closeFd close fd |
| | 501 | #ifdef mingw32_HOST_OS |
| | 502 | = close fd |
| | 503 | #else |
| | 504 | = GHC.Conc.closeFd close fd |
| | 505 | #endif |
| | 506 | |
| 482 | 507 | #ifdef mingw32_HOST_OS |
| 483 | 508 | foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool |
| 484 | 509 | |
diff -rN -u old-base/GHC/Conc/IO.hs new-base/GHC/Conc/IO.hs
|
old
|
new
|
|
| 31 | 31 | , registerDelay -- :: Int -> IO (TVar Bool) |
| 32 | 32 | , threadWaitRead -- :: Int -> IO () |
| 33 | 33 | , threadWaitWrite -- :: Int -> IO () |
| | 34 | , closeFd -- :: (Int -> IO ()) -> Int -> IO () |
| 34 | 35 | |
| 35 | 36 | #ifdef mingw32_HOST_OS |
| 36 | 37 | , asyncRead -- :: Int -> Int -> Int -> Ptr a -> IO (Int, Int) |
| … |
… |
|
| 82 | 83 | |
| 83 | 84 | -- | Block the current thread until data can be written to the |
| 84 | 85 | -- given file descriptor (GHC only). |
| | 86 | -- |
| | 87 | -- This will throw an 'IOError' if the file descriptor was closed |
| | 88 | -- while this thread was blocked. |
| 85 | 89 | threadWaitWrite :: Fd -> IO () |
| 86 | 90 | threadWaitWrite fd |
| 87 | 91 | #ifndef mingw32_HOST_OS |
| … |
… |
|
| 92 | 96 | case waitWrite# fd# s of { s' -> (# s', () #) |
| 93 | 97 | }} |
| 94 | 98 | |
| | 99 | -- | Close a file descriptor in a concurrency-safe way (GHC only). If |
| | 100 | -- you are using 'threadWaitRead' or 'threadWaitWrite' to perform |
| | 101 | -- blocking I\/O, you /must/ use this function to close file |
| | 102 | -- descriptors, or blocked threads may not be woken. |
| | 103 | -- |
| | 104 | -- Any threads that are blocked on the file descriptor via |
| | 105 | -- 'threadWaitRead' or 'threadWaitWrite' will be unblocked by having |
| | 106 | -- IO exceptions thrown. |
| | 107 | closeFd :: (Fd -> IO ()) -- ^ Low-level action that performs the real close. |
| | 108 | -> Fd -- ^ File descriptor to close. |
| | 109 | -> IO () |
| | 110 | closeFd close fd |
| | 111 | #ifndef mingw32_HOST_OS |
| | 112 | | threaded = Event.closeFd close fd |
| | 113 | #endif |
| | 114 | | otherwise = close fd |
| | 115 | |
| 95 | 116 | -- | Suspends the current thread for a given number of microseconds |
| 96 | 117 | -- (GHC only). |
| 97 | 118 | -- |
diff -rN -u old-base/GHC/Conc.lhs new-base/GHC/Conc.lhs
|
old
|
new
|
|
| 52 | 52 | , registerDelay -- :: Int -> IO (TVar Bool) |
| 53 | 53 | , threadWaitRead -- :: Int -> IO () |
| 54 | 54 | , threadWaitWrite -- :: Int -> IO () |
| | 55 | , closeFd -- :: (Int -> IO ()) -> Int -> IO () |
| 55 | 56 | |
| 56 | 57 | -- * TVars |
| 57 | 58 | , STM(..) |
diff -rN -u old-base/GHC/IO/FD.hs new-base/GHC/IO/FD.hs
|
old
|
new
|
|
| 280 | 280 | #ifndef mingw32_HOST_OS |
| 281 | 281 | (flip finally) (release fd) $ do |
| 282 | 282 | #endif |
| 283 | | throwErrnoIfMinus1Retry_ "GHC.IO.FD.close" $ |
| | 283 | let closer realFd = |
| | 284 | throwErrnoIfMinus1Retry_ "GHC.IO.FD.close" $ |
| 284 | 285 | #ifdef mingw32_HOST_OS |
| 285 | | if fdIsSocket fd then |
| 286 | | c_closesocket (fdFD fd) |
| 287 | | else |
| | 286 | if fdIsSocket fd then |
| | 287 | c_closesocket (fromIntegral realFd) |
| | 288 | else |
| 288 | 289 | #endif |
| 289 | | c_close (fdFD fd) |
| | 290 | c_close (fromIntegral realFd) |
| | 291 | closeFd closer (fromIntegral (fdFD fd)) |
| 290 | 292 | |
| 291 | 293 | release :: FD -> IO () |
| 292 | 294 | #ifdef mingw32_HOST_OS |
diff -rN -u old-base/System/Event/Internal.hs new-base/System/Event/Internal.hs
|
old
|
new
|
|
| 12 | 12 | , Event |
| 13 | 13 | , evtRead |
| 14 | 14 | , evtWrite |
| | 15 | , evtClose |
| 15 | 16 | , eventIs |
| 16 | 17 | -- * Timeout type |
| 17 | 18 | , Timeout(..) |
| … |
… |
|
| 29 | 30 | import GHC.Show (Show(..)) |
| 30 | 31 | import GHC.List (filter, null) |
| 31 | 32 | |
| 32 | | -- | An I/O event. |
| | 33 | -- | An I\/O event. |
| 33 | 34 | newtype Event = Event Int |
| 34 | 35 | deriving (Eq) |
| 35 | 36 | |
| … |
… |
|
| 37 | 38 | evtNothing = Event 0 |
| 38 | 39 | {-# INLINE evtNothing #-} |
| 39 | 40 | |
| | 41 | -- | Data is available to be read. |
| 40 | 42 | evtRead :: Event |
| 41 | 43 | evtRead = Event 1 |
| 42 | 44 | {-# INLINE evtRead #-} |
| 43 | 45 | |
| | 46 | -- | The file descriptor is ready to accept a write. |
| 44 | 47 | evtWrite :: Event |
| 45 | 48 | evtWrite = Event 2 |
| 46 | 49 | {-# INLINE evtWrite #-} |
| 47 | 50 | |
| | 51 | -- | Another thread closed the file descriptor. |
| | 52 | evtClose :: Event |
| | 53 | evtClose = Event 4 |
| | 54 | {-# INLINE evtClose #-} |
| | 55 | |
| 48 | 56 | eventIs :: Event -> Event -> Bool |
| 49 | 57 | eventIs (Event a) (Event b) = a .&. b /= 0 |
| 50 | 58 | |
| 51 | 59 | instance Show Event where |
| 52 | 60 | show e = '[' : (intercalate "," . filter (not . null) $ |
| 53 | | [evtRead `so` "evtRead", evtWrite `so` "evtWrite"]) ++ "]" |
| | 61 | [evtRead `so` "evtRead", |
| | 62 | evtWrite `so` "evtWrite", |
| | 63 | evtClose `so` "evtClose"]) ++ "]" |
| 54 | 64 | where ev `so` disp | e `eventIs` ev = disp |
| 55 | 65 | | otherwise = "" |
| 56 | 66 | |
diff -rN -u old-base/System/Event/Manager.hs new-base/System/Event/Manager.hs
|
old
|
new
|
|
| 26 | 26 | , registerFd |
| 27 | 27 | , unregisterFd_ |
| 28 | 28 | , unregisterFd |
| 29 | | , fdWasClosed |
| | 29 | , closeFd |
| 30 | 30 | |
| 31 | 31 | -- * Registering interest in timeout events |
| 32 | 32 | , TimeoutCallback |
| … |
… |
|
| 48 | 48 | import Data.IORef (IORef, atomicModifyIORef, mkWeakIORef, newIORef, readIORef, |
| 49 | 49 | writeIORef) |
| 50 | 50 | import Data.Maybe (Maybe(..)) |
| 51 | | import Data.Monoid (mconcat, mempty) |
| | 51 | import Data.Monoid (mappend, mconcat, mempty) |
| 52 | 52 | import GHC.Base |
| 53 | 53 | import GHC.Conc.Signal (runHandlers) |
| 54 | 54 | import GHC.List (filter) |
| … |
… |
|
| 57 | 57 | import GHC.Show (Show(..)) |
| 58 | 58 | import System.Event.Clock (getCurrentTime) |
| 59 | 59 | import System.Event.Control |
| 60 | | import System.Event.Internal (Backend, Event, evtRead, evtWrite, Timeout(..)) |
| | 60 | import System.Event.Internal (Backend, Event, evtClose, evtRead, evtWrite, |
| | 61 | Timeout(..)) |
| 61 | 62 | import System.Event.Unique (Unique, UniqueSource, newSource, newUnique) |
| 62 | 63 | import System.Posix.Types (Fd) |
| 63 | 64 | |
| … |
… |
|
| 331 | 332 | wake <- unregisterFd_ mgr reg |
| 332 | 333 | when wake $ wakeManager mgr |
| 333 | 334 | |
| 334 | | -- | Notify the event manager that a file descriptor has been closed. |
| 335 | | fdWasClosed :: EventManager -> Fd -> IO () |
| 336 | | fdWasClosed mgr fd = |
| 337 | | modifyMVar_ (emFds mgr) $ \oldMap -> |
| | 335 | -- | Close a file descriptor in a race-safe way. |
| | 336 | closeFd :: EventManager -> (Fd -> IO ()) -> Fd -> IO () |
| | 337 | closeFd mgr close fd = do |
| | 338 | fds <- modifyMVar (emFds mgr) $ \oldMap -> do |
| | 339 | close fd |
| 338 | 340 | case IM.delete (fromIntegral fd) oldMap of |
| 339 | | (Nothing, _) -> return oldMap |
| | 341 | (Nothing, _) -> return (oldMap, []) |
| 340 | 342 | (Just fds, !newMap) -> do |
| 341 | 343 | when (eventsOf fds /= mempty) $ wakeManager mgr |
| 342 | | return newMap |
| | 344 | return (newMap, fds) |
| | 345 | forM_ fds $ \(FdData reg ev cb) -> cb reg (ev `mappend` evtClose) |
| 343 | 346 | |
| 344 | 347 | ------------------------------------------------------------------------ |
| 345 | 348 | -- Registering interest in timeout events |
diff -rN -u old-base/System/Event/Thread.hs new-base/System/Event/Thread.hs
|
old
|
new
|
|
| 5 | 5 | ensureIOManagerIsRunning |
| 6 | 6 | , threadWaitRead |
| 7 | 7 | , threadWaitWrite |
| | 8 | , closeFd |
| 8 | 9 | , threadDelay |
| 9 | 10 | , registerDelay |
| 10 | 11 | ) where |
| 11 | 12 | |
| 12 | 13 | import Data.IORef (IORef, newIORef, readIORef, writeIORef) |
| 13 | 14 | import Data.Maybe (Maybe(..)) |
| | 15 | import Foreign.C.Error (eBADF, errnoToIOError) |
| 14 | 16 | import Foreign.Ptr (Ptr) |
| 15 | 17 | import GHC.Base |
| 16 | 18 | import GHC.Conc.Sync (TVar, ThreadId, ThreadStatus(..), atomically, forkIO, |
| 17 | 19 | labelThread, modifyMVar_, newTVar, sharedCAF, |
| 18 | 20 | threadStatus, writeTVar) |
| | 21 | import GHC.IO.Exception (ioError) |
| 19 | 22 | import GHC.MVar (MVar, newEmptyMVar, newMVar, putMVar, takeMVar) |
| | 23 | import GHC.Real (fromIntegral) |
| | 24 | import System.Event.Internal (eventIs, evtClose) |
| 20 | 25 | import System.Event.Manager (Event, EventManager, evtRead, evtWrite, loop, |
| 21 | 26 | new, registerFd, unregisterFd_, registerTimeout) |
| | 27 | import qualified System.Event.Manager as M |
| 22 | 28 | import System.IO.Unsafe (unsafePerformIO) |
| 23 | 29 | import System.Posix.Types (Fd) |
| 24 | 30 | |
| … |
… |
|
| 47 | 53 | |
| 48 | 54 | -- | Block the current thread until data is available to read from the |
| 49 | 55 | -- given file descriptor. |
| | 56 | -- |
| | 57 | -- This will throw an 'IOError' if the file descriptor was closed |
| | 58 | -- while this thread is blocked. |
| 50 | 59 | threadWaitRead :: Fd -> IO () |
| 51 | 60 | threadWaitRead = threadWait evtRead |
| 52 | 61 | {-# INLINE threadWaitRead #-} |
| 53 | 62 | |
| 54 | 63 | -- | Block the current thread until the given file descriptor can |
| 55 | 64 | -- accept data to write. |
| | 65 | -- |
| | 66 | -- This will throw an 'IOError' if the file descriptor was closed |
| | 67 | -- while this thread is blocked. |
| 56 | 68 | threadWaitWrite :: Fd -> IO () |
| 57 | 69 | threadWaitWrite = threadWait evtWrite |
| 58 | 70 | {-# INLINE threadWaitWrite #-} |
| 59 | 71 | |
| | 72 | -- | Close a file descriptor in a concurrency-safe way. |
| | 73 | -- |
| | 74 | -- Any threads that are blocked on the file descriptor via |
| | 75 | -- 'threadWaitRead' or 'threadWaitWrite' will be unblocked by having |
| | 76 | -- IO exceptions thrown. |
| | 77 | closeFd :: (Fd -> IO ()) -- ^ Action that performs the close. |
| | 78 | -> Fd -- ^ File descriptor to close. |
| | 79 | -> IO () |
| | 80 | closeFd close fd = do |
| | 81 | Just mgr <- readIORef eventManager |
| | 82 | M.closeFd mgr close fd |
| | 83 | |
| 60 | 84 | threadWait :: Event -> Fd -> IO () |
| 61 | 85 | threadWait evt fd = do |
| 62 | 86 | m <- newEmptyMVar |
| 63 | 87 | Just mgr <- readIORef eventManager |
| 64 | | _ <- registerFd mgr (\reg _ -> unregisterFd_ mgr reg >> putMVar m ()) fd evt |
| 65 | | takeMVar m |
| | 88 | _ <- registerFd mgr (\reg e -> unregisterFd_ mgr reg >> putMVar m e) fd evt |
| | 89 | evt' <- takeMVar m |
| | 90 | if evt' `eventIs` evtClose |
| | 91 | then ioError $ errnoToIOError "threadWait" eBADF Nothing Nothing |
| | 92 | else return () |
| 66 | 93 | |
| 67 | 94 | foreign import ccall unsafe "getOrSetSystemEventThreadEventManagerStore" |
| 68 | 95 | getOrSetSystemEventThreadEventManagerStore :: Ptr a -> IO (Ptr a) |
diff -rN -u old-base/System/Event.hs new-base/System/Event.hs
|
old
|
new
|
|
| 22 | 22 | , registerFd_ |
| 23 | 23 | , unregisterFd |
| 24 | 24 | , unregisterFd_ |
| 25 | | , fdWasClosed |
| | 25 | , closeFd |
| 26 | 26 | |
| 27 | 27 | -- * Registering interest in timeout events |
| 28 | 28 | , TimeoutCallback |