X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FConc%2FSync.lhs;h=f16ee3fd7a3b097caf4e90c5a767b64e9a7fd9f7;hb=d8c8a1a857709334949d680d6afa274b7c6c7809;hp=370bfd91352bba9e88a65c177fbe93a2eb659be9;hpb=6685444335fe57d5d86b61965989e45f34fddf0e;p=ghc-base.git diff --git a/GHC/Conc/Sync.lhs b/GHC/Conc/Sync.lhs index 370bfd9..f16ee3f 100644 --- a/GHC/Conc/Sync.lhs +++ b/GHC/Conc/Sync.lhs @@ -7,6 +7,8 @@ , UnliftedFFITypes , ForeignFunctionInterface , DeriveDataTypeable + , StandaloneDeriving + , RankNTypes #-} {-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# OPTIONS_HADDOCK not-home #-} @@ -39,8 +41,11 @@ module GHC.Conc.Sync -- * Forking and suchlike , forkIO -- :: IO a -> IO ThreadId , forkIOUnmasked - , forkOnIO -- :: Int -> IO a -> IO ThreadId + , forkIOWithUnmask + , forkOn -- :: Int -> IO a -> IO ThreadId + , forkOnIO -- DEPRECATED , forkOnIOUnmasked + , forkOnWithUnmask , numCapabilities -- :: Int , getNumCapabilities -- :: IO Int , numSparks -- :: IO Int @@ -195,36 +200,74 @@ forkIO action = IO $ \ s -> where action_plus = catchException action childHandler --- | Like 'forkIO', but the child thread is created with asynchronous exceptions --- unmasked (see 'Control.Exception.mask'). +{-# DEPRECATED forkIOUnmasked "use forkIOWithUnmask instead" #-} +-- | This function is deprecated; use 'forkIOWIthUnmask' instead forkIOUnmasked :: IO () -> IO ThreadId forkIOUnmasked io = forkIO (unsafeUnmask io) +-- | Like 'forkIO', but the child thread is passed a function that can +-- be used to unmask asynchronous exceptions. This function is +-- typically used in the following way +-- +-- > ... mask_ $ forkIOWithUnmask $ \unmask -> +-- > catch (unmask ...) handler +-- +-- so that the exception handler in the child thread is established +-- with asynchronous exceptions masked, meanwhile the main body of +-- the child thread is executed in the unmasked state. +-- +-- Note that the unmask function passed to the child thread should +-- only be used in that thread; the behaviour is undefined if it is +-- invoked in a different thread. +-- +forkIOWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ThreadId +forkIOWithUnmask io = forkIO (io unsafeUnmask) + {- | -Like 'forkIO', but lets you specify on which CPU the thread is -created. Unlike a `forkIO` thread, a thread created by `forkOnIO` -will stay on the same CPU for its entire lifetime (`forkIO` threads -can migrate between CPUs according to the scheduling policy). -`forkOnIO` is useful for overriding the scheduling policy when you -know in advance how best to distribute the threads. - -The `Int` argument specifies the CPU number; it is interpreted modulo -the value returned by 'getNumCapabilities'. +Like 'forkIO', but lets you specify on which processor the thread +should run. Unlike a `forkIO` thread, a thread created by `forkOn` +will stay on the same processor for its entire lifetime (`forkIO` +threads can migrate between processors according to the scheduling +policy). `forkOn` is useful for overriding the scheduling policy when +you know in advance how best to distribute the threads. + +The `Int` argument specifies a /capability number/ (see +'getNumCapabilities'). Typically capabilities correspond to physical +processors, but the exact behaviour is implementation-dependent. The +value passed to 'forkOn' is interpreted modulo the total number of +capabilities as returned by 'getNumCapabilities'. + +GHC note: the number of capabilities is specified by the @+RTS -N@ +option when the program is started. Capabilities can be fixed to +actual processor cores with @+RTS -qa@ if the underlying operating +system supports that, although in practice this is usually unnecessary +(and may actually degrade perforamnce in some cases - experimentation +is recommended). -} -forkOnIO :: Int -> IO () -> IO ThreadId -forkOnIO (I# cpu) action = IO $ \ s -> +forkOn :: Int -> IO () -> IO ThreadId +forkOn (I# cpu) action = IO $ \ s -> case (forkOn# cpu action_plus s) of (# s1, tid #) -> (# s1, ThreadId tid #) where action_plus = catchException action childHandler --- | Like 'forkOnIO', but the child thread is created with --- asynchronous exceptions unmasked (see 'Control.Exception.mask'). +{-# DEPRECATED forkOnIO "renamed to forkOn" #-} +-- | This function is deprecated; use 'forkOn' instead +forkOnIO :: Int -> IO () -> IO ThreadId +forkOnIO = forkOn + +{-# DEPRECATED forkOnIOUnmasked "use forkOnWithUnmask instead" #-} +-- | This function is deprecated; use 'forkOnWIthUnmask' instead forkOnIOUnmasked :: Int -> IO () -> IO ThreadId -forkOnIOUnmasked cpu io = forkOnIO cpu (unsafeUnmask io) +forkOnIOUnmasked cpu io = forkOn cpu (unsafeUnmask io) + +-- | Like 'forkIOWithUnmask', but the child thread is pinned to the +-- given CPU, as with 'forkOn'. +forkOnWithUnmask :: Int -> ((forall a . IO a -> IO a) -> IO ()) -> IO ThreadId +forkOnWithUnmask cpu io = forkOn cpu (io unsafeUnmask) -- | the value passed to the @+RTS -N@ flag. This is the number of -- Haskell threads that can run truly simultaneously at any given --- time, and is typically set to the number of physical CPU cores on +-- time, and is typically set to the number of physical processor cores on -- the machine. -- -- Strictly speaking it is better to use 'getNumCapabilities', because @@ -236,12 +279,12 @@ numCapabilities = unsafePerformIO $ getNumCapabilities {- | Returns the number of Haskell threads that can run truly simultaneously (on separate physical processors) at any given time. -The CPU number passed to `forkOnIO` is interpreted modulo this +The number passed to `forkOn` is interpreted modulo this value. An implementation in which Haskell threads are mapped directly to OS threads might return the number of physical processor cores in -the machine, and 'forkOnIO' would be implemented using the OS's +the machine, and 'forkOn' would be implemented using the OS's affinity facilities. An implementation that schedules Haskell threads onto a smaller number of OS threads (like GHC) would return the number of such OS threads that can be running simultaneously. @@ -330,9 +373,17 @@ thread reaches a /safe point/, where a safe point is where memory allocation occurs. Some loops do not perform any memory allocation inside the loop and therefore cannot be interrupted by a 'throwTo'. -Blocked 'throwTo' is fair: if multiple threads are trying to throw an -exception to the same target thread, they will succeed in FIFO order. - +If the target of 'throwTo' is the calling thread, then the behaviour +is the same as 'Control.Exception.throwIO', except that the exception +is thrown as an asynchronous exception. This means that if there is +an enclosing pure computation, which would be the case if the current +IO operation is inside 'unsafePerformIO' or 'unsafeInterleaveIO', that +computation is not permanently replaced by the exception, but is +suspended as if it had received an asynchronous exception. + +Note that if 'throwTo' is called with the current thread as the +target, the exception will be thrown even if the thread is currently +inside 'mask' or 'uninterruptibleMask'. -} throwTo :: Exception e => ThreadId -> e -> IO () throwTo (ThreadId tid) ex = IO $ \ s -> @@ -444,7 +495,7 @@ threadStatus (ThreadId t) = IO $ \s -> -- | returns the number of the capability on which the thread is currently -- running, and a boolean indicating whether the thread is locked to -- that capability or not. A thread is locked to a capability if it --- was created with @forkOnIO@. +-- was created with @forkOn@. threadCapability :: ThreadId -> IO (Int, Bool) threadCapability (ThreadId t) = IO $ \s -> case threadStatus# t s of