Я бьюсь головой, пытаясь понять этот контракт select
:
Предложения
onSend
, onReceive
, onReceiveOrNull
и onLock
атомарно отменяемы. Когда select throw CancellationException
, это означает, что эти пункты не выполнили свои соответствующие операции.
В качестве побочного эффекта атомарного отмены, сопрограмма с привязкой к потоку (например, к некоторому потоку пользовательского интерфейса) может продолжать выполняться даже после того, как она была отменена из того же потока в случае, когда эта операция выбора уже была возобновлена атомарно отменяемое предложение и продолжение было отправлено для выполнения в очередь потока.
Это то, что имеет смысл для меня, на примере контекста UI
:
- выражение
select
выбирает предложение и отправляет его код в очередь событий пользовательского интерфейса
- когда код выбирается из очереди, в первую очередь проверяется флаг
isActive
. Если он понижен, код не запускается
- это нарушило бы атомарность отмены: ни вы не получили
CancellationException
в предложении select
, ни выполнение кода (отмена произошла, когда в очереди ожидал обратный вызов предложения)
- , поэтому проверка
isActive
пропускается, и код запускается, хотя в то же время он был отменен
Однако это , а не гарантия, указанная в (1). В нем не сказано «либо ваш код обработки выполняется, либо вы получите CancellationException
в выражении select
». Он говорит только «если вы получили исключение, это означает, что код не был запущен». Эта гарантия может быть достигнута без поведения, указанного в (2), поэтому это не побочный эффект (1).
Кажется, что описание поведения в (2) является правильным, но предоставляемая им гарантия не соответствует описанию в (1). Это «если вы не получили CancellationException
, тогда код обработчика будет запущен».
Разве в документации не должно указываться более надежная гарантия или ?