@@ -28,7 +28,7 @@ coroutine throw an exception.
2828Coroutine builders come in two flavors: propagating exceptions automatically ([ launch] and [ actor] ) or
2929exposing them to users ([ async] and [ produce] ).
3030When these builders are used to create a _ root_ coroutine, that is not a _ child_ of another coroutine,
31- the former builder treat exceptions as ** uncaught** exceptions, similar to Java's ` Thread.uncaughtExceptionHandler ` ,
31+ the former builders treat exceptions as ** uncaught** exceptions, similar to Java's ` Thread.uncaughtExceptionHandler ` ,
3232while the latter are relying on the user to consume the final
3333exception, for example via [ await] [ Deferred.await ] or [ receive] [ ReceiveChannel.receive ]
3434([ produce] and [ receive] [ ReceiveChannel.receive ] are covered later in [ Channels] ( https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/channels.md ) section).
@@ -246,7 +246,7 @@ CoroutineExceptionHandler got java.lang.ArithmeticException
246246
247247### Exceptions aggregation
248248
249- When multiple children of a coroutine fail with an exception the
249+ When multiple children of a coroutine fail with an exception, the
250250general rule is "the first exception wins", so the first exception gets handled.
251251All additional exceptions that happen after the first one are attached to the first exception as suppressed ones.
252252
@@ -296,8 +296,8 @@ CoroutineExceptionHandler got java.io.IOException with suppressed [java.lang.Ari
296296
297297<!-- - TEST-->
298298
299- > Note, this mechanism currently works only on Java version 1.7+.
300- Limitation on JS and Native is temporary and will be fixed in the future.
299+ > Note that this mechanism currently only works on Java version 1.7+.
300+ The JS and Native restrictions are temporary and will be lifted in the future.
301301
302302Cancellation exceptions are transparent and are unwrapped by default:
303303
@@ -353,14 +353,14 @@ A good example of such a requirement is a UI component with the job defined in i
353353have failed, it is not always necessary to cancel (effectively kill) the whole UI component,
354354but if UI component is destroyed (and its job is cancelled), then it is necessary to fail all child jobs as their results are no longer needed.
355355
356- Another example is a server process that spawns several children jobs and needs to _ supervise_
357- their execution, tracking their failures and restarting just those children jobs that had failed.
356+ Another example is a server process that spawns multiple child jobs and needs to _ supervise_
357+ their execution, tracking their failures and only restarting the failed ones .
358358
359359#### Supervision job
360360
361- For these purposes [ SupervisorJob] [ SupervisorJob() ] can be used.
361+ The [ SupervisorJob] [ SupervisorJob() ] can be used for these purposes .
362362It is similar to a regular [ Job] [ Job() ] with the only exception that cancellation is propagated
363- only downwards. It is easy to demonstrate with an example:
363+ only downwards. This can easily be demonstrated using the following example:
364364
365365<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
366366
@@ -372,24 +372,24 @@ fun main() = runBlocking {
372372 with (CoroutineScope (coroutineContext + supervisor)) {
373373 // launch the first child -- its exception is ignored for this example (don't do this in practice!)
374374 val firstChild = launch(CoroutineExceptionHandler { _, _ -> }) {
375- println (" First child is failing" )
376- throw AssertionError (" First child is cancelled" )
375+ println (" The first child is failing" )
376+ throw AssertionError (" The first child is cancelled" )
377377 }
378378 // launch the second child
379379 val secondChild = launch {
380380 firstChild.join()
381381 // Cancellation of the first child is not propagated to the second child
382- println (" First child is cancelled: ${firstChild.isCancelled} , but second one is still active" )
382+ println (" The first child is cancelled: ${firstChild.isCancelled} , but the second one is still active" )
383383 try {
384384 delay(Long .MAX_VALUE )
385385 } finally {
386386 // But cancellation of the supervisor is propagated
387- println (" Second child is cancelled because supervisor is cancelled" )
387+ println (" The second child is cancelled because the supervisor was cancelled" )
388388 }
389389 }
390390 // wait until the first child fails & completes
391391 firstChild.join()
392- println (" Cancelling supervisor" )
392+ println (" Cancelling the supervisor" )
393393 supervisor.cancel()
394394 secondChild.join()
395395 }
@@ -403,18 +403,18 @@ fun main() = runBlocking {
403403The output of this code is:
404404
405405``` text
406- First child is failing
407- First child is cancelled: true, but second one is still active
408- Cancelling supervisor
409- Second child is cancelled because supervisor is cancelled
406+ The first child is failing
407+ The first child is cancelled: true, but the second one is still active
408+ Cancelling the supervisor
409+ The second child is cancelled because the supervisor was cancelled
410410```
411411<!-- - TEST-->
412412
413413
414414#### Supervision scope
415415
416- For _ scoped _ concurrency [ supervisorScope ] can be used instead of [ coroutineScope ] for the same purpose . It propagates cancellation
417- in one direction only and cancels all children only if it has failed itself. It also waits for all children before completion
416+ Instead of [ coroutineScope ] , we can use [ supervisorScope ] for _ scoped _ concurrency . It propagates the cancellation
417+ in one direction only and cancels all its children only if it failed itself. It also waits for all children before completion
418418just like [ coroutineScope] does.
419419
420420<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
@@ -428,19 +428,19 @@ fun main() = runBlocking {
428428 supervisorScope {
429429 val child = launch {
430430 try {
431- println (" Child is sleeping" )
431+ println (" The child is sleeping" )
432432 delay(Long .MAX_VALUE )
433433 } finally {
434- println (" Child is cancelled" )
434+ println (" The child is cancelled" )
435435 }
436436 }
437437 // Give our child a chance to execute and print using yield
438438 yield ()
439- println (" Throwing exception from scope" )
439+ println (" Throwing an exception from the scope" )
440440 throw AssertionError ()
441441 }
442442 } catch (e: AssertionError ) {
443- println (" Caught assertion error" )
443+ println (" Caught an assertion error" )
444444 }
445445}
446446```
@@ -452,21 +452,21 @@ fun main() = runBlocking {
452452The output of this code is:
453453
454454``` text
455- Child is sleeping
456- Throwing exception from scope
457- Child is cancelled
458- Caught assertion error
455+ The child is sleeping
456+ Throwing an exception from the scope
457+ The child is cancelled
458+ Caught an assertion error
459459```
460460<!-- - TEST-->
461461
462462#### Exceptions in supervised coroutines
463463
464464Another crucial difference between regular and supervisor jobs is exception handling.
465- Every child should handle its exceptions by itself via exception handling mechanism.
466- This difference comes from the fact that child's failure is not propagated to the parent.
467- It means that coroutines launched directly inside [ supervisorScope] _ do_ use the [ CoroutineExceptionHandler]
465+ Every child should handle its exceptions by itself via the exception handling mechanism.
466+ This difference comes from the fact that child's failure does not propagate to the parent.
467+ It means that coroutines launched directly inside the [ supervisorScope] _ do_ use the [ CoroutineExceptionHandler]
468468that is installed in their scope in the same way as root coroutines do
469- (see [ CoroutineExceptionHandler] ( #coroutineexceptionhandler ) section for details).
469+ (see the [ CoroutineExceptionHandler] ( #coroutineexceptionhandler ) section for details).
470470
471471<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
472472
@@ -480,12 +480,12 @@ fun main() = runBlocking {
480480 }
481481 supervisorScope {
482482 val child = launch(handler) {
483- println (" Child throws an exception" )
483+ println (" The child throws an exception" )
484484 throw AssertionError ()
485485 }
486- println (" Scope is completing" )
486+ println (" The scope is completing" )
487487 }
488- println (" Scope is completed" )
488+ println (" The scope is completed" )
489489}
490490```
491491
@@ -496,10 +496,10 @@ fun main() = runBlocking {
496496The output of this code is:
497497
498498``` text
499- Scope is completing
500- Child throws an exception
499+ The scope is completing
500+ The child throws an exception
501501CoroutineExceptionHandler got java.lang.AssertionError
502- Scope is completed
502+ The scope is completed
503503```
504504<!-- - TEST-->
505505
@@ -517,8 +517,8 @@ Scope is completed
517517[ runBlocking ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
518518[ SupervisorJob() ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-supervisor-job.html
519519[ Job() ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job.html
520- [ supervisorScope ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/supervisor-scope.html
521520[ coroutineScope ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
521+ [ supervisorScope ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/supervisor-scope.html
522522<!-- - INDEX kotlinx.coroutines.channels -->
523523[ actor ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
524524[ produce ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
0 commit comments