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

Code before:
     *                 println("Done with the procedure $it")
     *             } finally {
     *                 semaphore.release()
     *             }
     *         }
     *     }
     * } finally {
     *     withContext(NonCancellable) {
     *         repeat(N_PERMITS) { semaphore.acquire() }
     *         println("All permits were successfully returned!")
     *     }
     * }
     * ```
     *
     * Here, we used [ATOMIC] to ensure that a semaphore that was acquired outside of the coroutine does get released
     * even if cancellation happens between `acquire()` and `launch`.
     * As a result, the semaphore will eventually regain all three permits.
     *
     * Behavior of [ATOMIC] can be described with the following examples:
     *
     * ```
     * // Example of cancelling atomically started coroutines
     * runBlocking {
     *     println("1. Atomically starting a coroutine that goes through a dispatch.")
     *     launch(start = CoroutineStart.ATOMIC) {
     *         check(!isActive) // attempting to suspend will throw
     *         println("4. A coroutine that went through a dispatch also starts.")
     *         try {
     *             delay(10.milliseconds)
     *             println("This code will never run.")
     *         } catch (e: CancellationException) {
     *             println("5. Cancellation at later points still works.")
     *             throw e
     *         }
     *     }
     *     println("2. Cancelling this coroutine and all of its children.")
     *     cancel()
     *     launch(Dispatchers.Unconfined, start = CoroutineStart.ATOMIC) {
     *         check(!isActive) // attempting to suspend will throw
     *         println("3. An undispatched coroutine starts.")
     *     }
     *     ensureActive() // we can even crash the current coroutine.
     * }
     * ```
     *
     * **Pitfall**: occasionally, it is an error to execute code after the coroutine was cancelled.
     * A notable example is working with UI on Android:
     * after a coroutine scope whose lifecycle is tied to to an UI element gets cancelled,
     * updating that UI element is not allowed and will throw an exception.
     */
    @ExperimentalCoroutinesApi // Since 1.0.0, no ETA on stability

Review comment (suggestion):
The combination of check and the comment is a bit confusing to me, I'd prefer printing `isActive` alongside the message `4.`, and / or mentioning "the coroutine starts despite being cancelled prior"

Code after:
     * ```
     * val mutex = Mutex()
     *
     * mutex.lock() // lock the mutex outside the coroutine
     * // ... // initial portion of the work, protected by the mutex
     * val job = launch(start = CoroutineStart.ATOMIC) {
     *     // the work must continue in a coroutine, but still under the mutex
     *     println("Coroutine running!")
     *     try {
     *         // this `try` block will be entered in any case because of ATOMIC
     *         println("Starting task...")
     *         delay(10.milliseconds) // throws due to cancellation
     *         println("Finished task.")
     *     } finally {
     *         mutex.unlock() // correctly release the mutex
     *     }
     * }
     *
     * job.cancelAndJoin() // we immediately cancel the coroutine.
     * mutex.withLock {
     *     println("The lock has been returned correctly!")
     * }
     * ```
     *
     * Here, we used [ATOMIC] to ensure that a mutex that was acquired outside the coroutine does get released
     * even if cancellation happens between `lock()` and `launch`.
     * As a result, the mutex will always be released.
     *
     * The behavior of [ATOMIC] can be described with the following examples:
     *
     * ```
     * // Example of cancelling atomically started coroutines
     * runBlocking {
     *     println("1. Atomically starting a coroutine that goes through a dispatch.")
     *     launch(start = CoroutineStart.ATOMIC) {
     *         check(!isActive) // attempting to suspend later will throw
     *         println("4. The coroutine was cancelled (isActive = $isActive), but starts anyway.")
     *         try {
     *             delay(10.milliseconds) // will throw: the coroutine is cancelled
     *             println("This code will never run.")
     *         } catch (e: CancellationException) {
     *             println("5. Cancellation at later points still works.")
     *             throw e
     *         }
     *     }
     *     println("2. Cancelling this coroutine and all of its children.")
     *     cancel()
     *     launch(Dispatchers.Unconfined, start = CoroutineStart.ATOMIC) {
     *         check(!isActive) // attempting to suspend will throw
     *         println("3. An undispatched coroutine starts.")
     *     }