Repository: Kotlin/kotlinx.coroutines
File: kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt (Kotlin)

Code before:
     * // Invoked from arbitrary coroutines
     * launch(confined) {
     *     // This increment is sequential and race-free
     *     ++counter
     * }
     * ```
     * Note that there is no guarantee that the underlying system thread will always be the same.
     *
     * ### Dispatchers.IO
     *
     * `Dispatcher.IO` is considered _elastic_ for the purposes of limited parallelism -- the sum of
     * views is not restricted by the capacity of `Dispatchers.IO`.
     * It means that it is safe to replace `newFixedThreadPoolContext(nThreads)` with
     * `Dispatchers.IO.limitedParallelism(nThreads)` w.r.t. available number of threads.
     * See `Dispatchers.IO` documentation for more details.
     *
     * ### Restrictions and implementation details
     *
     * The default implementation of `limitedParallelism` does not support direct dispatchers,
     * such as executing the given runnable in place during [dispatch] calls.
     * Any dispatcher that may return `false` from [isDispatchNeeded] is considered direct.
     * For direct dispatchers, it is recommended to override this method
     * and provide a domain-specific implementation or to throw an [UnsupportedOperationException].
     *
     * Implementations of this method are allowed to return `this` if the current dispatchercan satisfy the requested parallelism,
     * for example when the maximal parallelsm provided by the dispatcher is less than the requested one.
     *
     * @throws IllegalArgumentException if the given [parallelism] is non-positive
     * @throws UnsupportedOperationException if the current dispatcher does not support limited parallelism views
     */
    @ExperimentalCoroutinesApi
    public open fun limitedParallelism(parallelism: Int): CoroutineDispatcher {
        parallelism.checkParallelism()
        return LimitedDispatcher(this, parallelism)
    }

    /**
     * Requests execution of a runnable [block].
     * The dispatcher guarantees that [block] will eventually execute, typically by dispatching it to a thread pool,
     * using a dedicated thread, or just executing the block in place.
     * The [context] parameter represents the context of the coroutine that is being dispatched,
     * or [EmptyCoroutineContext] if a non-coroutine-specific [Runnable] is dispatched instead.
     * Implementations may use [context] for additional context-specific information,
     * such as priority, whether the dispatched coroutine can be invoked in place,
     * coroutine name, and additional diagnostic elements.
     *
     * This method should guarantee that the given [block] will be eventually invoked,
     * otherwise the system may reach a deadlock state and never leave it.
     * The cancellation mechanism is transparent for [CoroutineDispatcher] and is managed by [block] internals.
     *
     * This method should generally be exception-safe. An exception thrown from this method

Review comment (suggestion):
```suggestion
     * Implementations of this method are allowed to return `this` if the current dispatcher can satisfy the requested parallelism,
     * for example when the maximal parallelism provided by the dispatcher is less than the requested one.
```

Code after:
     * // Invoked from arbitrary coroutines
     * launch(confined) {
     *     // This increment is sequential and race-free
     *     ++counter
     * }
     * ```
     * Note that there is no guarantee that the underlying system thread will always be the same.
     *
     * ### Dispatchers.IO
     *
     * `Dispatcher.IO` is considered _elastic_ for the purposes of limited parallelism -- the sum of
     * views is not restricted by the capacity of `Dispatchers.IO`.
     * It means that it is safe to replace `newFixedThreadPoolContext(nThreads)` with
     * `Dispatchers.IO.limitedParallelism(nThreads)` w.r.t. available number of threads.
     * See `Dispatchers.IO` documentation for more details.
     *
     * ### Restrictions and implementation details
     *
     * The default implementation of `limitedParallelism` does not support direct dispatchers,
     * such as executing the given runnable in place during [dispatch] calls.
     * Any dispatcher that may return `false` from [isDispatchNeeded] is considered direct.
     * For direct dispatchers, it is recommended to override this method
     * and provide a domain-specific implementation or to throw an [UnsupportedOperationException].
     *
     * Implementations of this method are allowed to return `this` if the current dispatcher already satisfies the parallelism requirement.
     * For example, `Dispatchers.Main.limitedParallelism(1)` returns `Dispatchers.Main`, because the main dispatcher is already single-threaded.
     *
     * @throws IllegalArgumentException if the given [parallelism] is non-positive
     * @throws UnsupportedOperationException if the current dispatcher does not support limited parallelism views
     */
    @ExperimentalCoroutinesApi
    public open fun limitedParallelism(parallelism: Int): CoroutineDispatcher {
        parallelism.checkParallelism()
        return LimitedDispatcher(this, parallelism)
    }

    /**
     * Requests execution of a runnable [block].
     * The dispatcher guarantees that [block] will eventually execute, typically by dispatching it to a thread pool,
     * using a dedicated thread, or just executing the block in place.
     * The [context] parameter represents the context of the coroutine that is being dispatched,
     * or [EmptyCoroutineContext] if a non-coroutine-specific [Runnable] is dispatched instead.
     * Implementations may use [context] for additional context-specific information,
     * such as priority, whether the dispatched coroutine can be invoked in place,
     * coroutine name, and additional diagnostic elements.
     *
     * This method should guarantee that the given [block] will be eventually invoked,
     * otherwise the system may reach a deadlock state and never leave it.
     * The cancellation mechanism is transparent for [CoroutineDispatcher] and is managed by [block] internals.
     *
     * This method should generally be exception-safe. An exception thrown from this method