@@ -28,7 +28,7 @@ coroutine throw an exception.
28
28
Coroutine builders come in two flavors: propagating exceptions automatically ([ launch] and [ actor] ) or
29
29
exposing them to users ([ async] and [ produce] ).
30
30
When 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 ` ,
32
32
while the latter are relying on the user to consume the final
33
33
exception, for example via [ await] [ Deferred.await ] or [ receive] [ ReceiveChannel.receive ]
34
34
([ 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
246
246
247
247
### Exceptions aggregation
248
248
249
- When multiple children of a coroutine fail with an exception the
249
+ When multiple children of a coroutine fail with an exception, the
250
250
general rule is "the first exception wins", so the first exception gets handled.
251
251
All additional exceptions that happen after the first one are attached to the first exception as suppressed ones.
252
252
@@ -296,8 +296,8 @@ CoroutineExceptionHandler got java.io.IOException with suppressed [java.lang.Ari
296
296
297
297
<!-- - TEST-->
298
298
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.
301
301
302
302
Cancellation exceptions are transparent and are unwrapped by default:
303
303
@@ -353,14 +353,14 @@ A good example of such a requirement is a UI component with the job defined in i
353
353
have failed, it is not always necessary to cancel (effectively kill) the whole UI component,
354
354
but 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.
355
355
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 .
358
358
359
359
#### Supervision job
360
360
361
- For these purposes [ SupervisorJob] [ SupervisorJob() ] can be used.
361
+ The [ SupervisorJob] [ SupervisorJob() ] can be used for these purposes .
362
362
It 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:
364
364
365
365
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
366
366
@@ -372,24 +372,24 @@ fun main() = runBlocking {
372
372
with (CoroutineScope (coroutineContext + supervisor)) {
373
373
// launch the first child -- its exception is ignored for this example (don't do this in practice!)
374
374
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" )
377
377
}
378
378
// launch the second child
379
379
val secondChild = launch {
380
380
firstChild.join()
381
381
// 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" )
383
383
try {
384
384
delay(Long .MAX_VALUE )
385
385
} finally {
386
386
// 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" )
388
388
}
389
389
}
390
390
// wait until the first child fails & completes
391
391
firstChild.join()
392
- println (" Cancelling supervisor" )
392
+ println (" Cancelling the supervisor" )
393
393
supervisor.cancel()
394
394
secondChild.join()
395
395
}
@@ -403,18 +403,18 @@ fun main() = runBlocking {
403
403
The output of this code is:
404
404
405
405
``` 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
410
410
```
411
411
<!-- - TEST-->
412
412
413
413
414
414
#### Supervision scope
415
415
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
418
418
just like [ coroutineScope] does.
419
419
420
420
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
@@ -428,19 +428,19 @@ fun main() = runBlocking {
428
428
supervisorScope {
429
429
val child = launch {
430
430
try {
431
- println (" Child is sleeping" )
431
+ println (" The child is sleeping" )
432
432
delay(Long .MAX_VALUE )
433
433
} finally {
434
- println (" Child is cancelled" )
434
+ println (" The child is cancelled" )
435
435
}
436
436
}
437
437
// Give our child a chance to execute and print using yield
438
438
yield ()
439
- println (" Throwing exception from scope" )
439
+ println (" Throwing an exception from the scope" )
440
440
throw AssertionError ()
441
441
}
442
442
} catch (e: AssertionError ) {
443
- println (" Caught assertion error" )
443
+ println (" Caught an assertion error" )
444
444
}
445
445
}
446
446
```
@@ -452,21 +452,21 @@ fun main() = runBlocking {
452
452
The output of this code is:
453
453
454
454
``` 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
459
459
```
460
460
<!-- - TEST-->
461
461
462
462
#### Exceptions in supervised coroutines
463
463
464
464
Another 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]
468
468
that 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).
470
470
471
471
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
472
472
@@ -480,12 +480,12 @@ fun main() = runBlocking {
480
480
}
481
481
supervisorScope {
482
482
val child = launch(handler) {
483
- println (" Child throws an exception" )
483
+ println (" The child throws an exception" )
484
484
throw AssertionError ()
485
485
}
486
- println (" Scope is completing" )
486
+ println (" The scope is completing" )
487
487
}
488
- println (" Scope is completed" )
488
+ println (" The scope is completed" )
489
489
}
490
490
```
491
491
@@ -496,10 +496,10 @@ fun main() = runBlocking {
496
496
The output of this code is:
497
497
498
498
``` text
499
- Scope is completing
500
- Child throws an exception
499
+ The scope is completing
500
+ The child throws an exception
501
501
CoroutineExceptionHandler got java.lang.AssertionError
502
- Scope is completed
502
+ The scope is completed
503
503
```
504
504
<!-- - TEST-->
505
505
@@ -517,8 +517,8 @@ Scope is completed
517
517
[ runBlocking ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
518
518
[ SupervisorJob() ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-supervisor-job.html
519
519
[ 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
521
520
[ 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
522
522
<!-- - INDEX kotlinx.coroutines.channels -->
523
523
[ actor ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
524
524
[ produce ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
0 commit comments