Hoogle Search
Within LTS Haskell 24.52 (ghc-9.10.3)
Note that Stackage only displays results for the latest LTS and Nightly snapshot. Learn more.
forkThread :: Program τ α -> Program τ (Thread α)core-program Core.Program.Threads Fork a thread. The child thread will run in the same Context as the calling Program, including sharing the user-defined application state value. If you want to find out what the result of a thread was use waitThread on the Thread object returned from this function. For example:
t1 <- forkThread $ do info "Doing interesting stuff concurrently" pure True ... result <- waitThread t1 if result then -- expected else -- not good
If you don't need the result, you can use forkThread_ instead. Threads that are launched off as children are on their own! If the code in the child thread throws an exception that is not caught within that thread, the exception will kill the thread. Threads dying without telling anyone is a bit of an anti-pattern, so this library logs a warning-level log message if this happens. (this function wraps base's forkIO) Concerning telemetry Note that threads inherit the telemetry state from their parent. If you are using the tracing features from core-telemetry any telemetry registered in that side task will be included in the enclosing span active in the parent thread that spawned the thread:t2 <- forkThread $ do info "Performing quick side task" telemetry [ 'metric "counter" 42 ] ...
In this case the "counter" field in the parent thread's current span will get the value 42. This is appropriate for the common case where you are doing small side tasks concurrently to accelerate a larger computation. But at other times you are launching off a fully independent control flow and want it to have its own telemetry. In those cases, you'll want to start a new span (or even a new trace) immediately after forking the thread:forkThread_ $ do encloseSpan "subTask" $ do ...
any telemetry from this worker thread will be appropriately nested in a new child span called "subTask".forkThread_ :: Program τ α -> Program τ ()core-program Core.Program.Threads Fork a thread with forkThread but do not wait for a result. This is on the assumption that the sub program will either be a side-effect and over quickly, or long-running daemon thread (presumably containing a forever loop in it), never returning.
raceThreads :: Program τ α -> Program τ β -> Program τ (Either α β)core-program Core.Program.Threads Fork two threads and race them against each other. This blocks until one or the other of the threads finishes. The return value will be Left α if the first program (one) completes first, and Right β if it is the second program (two) which finishes first. The sub program which is still running will be cancelled with an exception.
result <- raceThreads one two case result of Left a -> do -- one finished first Right b -> do -- two finished first
For a variant that ingores the return value and just races the threads see raceThreads_ below.raceThreads_ :: Program τ α -> Program τ β -> Program τ ()core-program Core.Program.Threads Fork two threads and race them against each other. When one action completes the other will be cancelled with an exception. This is useful for enforcing timeouts:
raceThreads_ (sleepThread 300) (do -- We expect this to complete within 5 minutes. performAction )
timeoutThread :: Rational -> Program τ α -> Program τ αcore-program Core.Program.Threads Run a program that needs to complete before the given number of seconds have elapsed. This will return the result of the sub program or throw the Timeout exception if the limit is exceeded.
waitThread :: Thread α -> Program τ αcore-program Core.Program.Threads Wait for the completion of a thread, returning the result. This is a blocking operation. If the thread you are waiting on throws an exception it will be rethrown by waitThread. If the current thread making this call is cancelled (as a result of being on the losing side of concurrentThreads or raceThreads for example, or due to the current scope exiting), then the thread you are waiting on will be cancelled too. This is necessary to ensure that child threads are not leaked if you nest forkThreads.
waitThread' :: Thread α -> Program τ (Either SomeException α)core-program Core.Program.Threads Wait for a thread to complete, returning the result if the computation was successful or the exception if one was thrown by the child thread. This basically is convenience for calling waitThread and putting catch around it, but as with all the other wait* functions this ensures that if the thread waiting is killed the cancellation is propagated to the thread being watched as well.
waitThread_ :: Thread α -> Program τ ()core-program Core.Program.Threads Wait for the completion of a thread, discarding its result. This is particularly useful at the end of a do-block if you're waiting on a worker thread to finish but don't need its return value, if any; otherwise you have to explicily deal with the unused return value:
_ <- waitThread t1 return ()
which is a bit tedious. Instead, you can just use this convenience function:waitThread_ t1
The trailing underscore in the name of this function follows the same convetion as found in Control.Monad, which has mapM_ which does the same as mapM but which likewise discards the return value.waitThreads' :: [Thread α] -> Program τ [Either SomeException α]core-program Core.Program.Threads Wait for many threads to complete. This function is intended for the scenario where you fire off a number of worker threads with forkThread but rather than leaving them to run independantly, you need to wait for them all to complete. The results of the threads that complete successfully will be returned as Right values. Should any of the threads being waited upon throw an exception, those exceptions will be returned as Left values. If you don't need to analyse the failures individually, then you can just collect the successes using Data.Either's rights:
responses <- waitThreads' info "Aggregating results..." combineResults (rights responses)
Likewise, if you do want to do something with all the failures, you might find lefts useful:mapM_ (warn . intoRope . displayException) (lefts responses)
If the thread calling waitThreads' is cancelled, then all the threads being waited upon will also be cancelled. This often occurs within a timeout or similar control measure implemented using raceThreads_. Should the thread that spawned all the workers and is waiting for their results be told to cancel because it lost the "race", the child threads need to be told in turn to cancel so as to avoid those threads being leaked and continuing to run as zombies. This function takes care of that. (this extends waitThread' to work across a list of Threads, taking care to ensure the cancellation behaviour described throughout this module)socketReader :: forall (m :: Type -> Type) . MonadIO m => Socket -> Producer ByteString m ()daemons Control.Pipe.Socket Stream data from the socket.