@@ -129,10 +129,6 @@
129-- >>> Stream.drain $ Stream.asyncly $ Stream.replicateM 10 $ delay 1
129-- >>> Stream.drain $ Stream.asyncly $ Stream.replicateM 10 $ delay 1
132−-- By default, there is a limit on how many concurrent actions may be executed
133−-- at a time, the "Concurrency Control" section describes combinators that can
134−-- be used to control the concurrency.
136-- We can use 'mapM' to map an action concurrently:
132-- We can use 'mapM' to map an action concurrently:
138-- >>> f x = delay 1 >> return (x + 1)
134-- >>> f x = delay 1 >> return (x + 1)
@@ -148,6 +144,20 @@
148-- constraint. However, a @MonadAsync m@ constraint does not necessarily mean
144-- constraint. However, a @MonadAsync m@ constraint does not necessarily mean
149-- that the combinator is concurrent.
145-- that the combinator is concurrent.
147+-- == Automatic Concurrency Control
149+-- 'SerialT' (and 'WSerialT') runs all tasks serially whereas 'ParallelT' runs
150+-- all tasks concurrently i.e. one thread per task. The stream types 'AsyncT',
151+-- 'WAsyncT', and 'AheadT' provide demand driven concurrency. It means that
152+-- based on the rate at which the consumer is consuming the stream, it
153+-- maintains the optimal number of threads to increase or decrease parallelism.
155+-- However, the programmer can control the maximum number of threads using
156+-- 'maxThreads'. It provides an upper bound on the concurrent IO requests or
157+-- CPU cores that can be used. 'maxBuffer' limits the number of evaluated
158+-- stream elements that we can buffer. See the "Concurrency Control" section
151-- == Combining Two streams
161-- == Combining Two streams
153-- Earlier we distinguished stream types based on the execution behavior of
163-- Earlier we distinguished stream types based on the execution behavior of