Запутанный договор `select` - PullRequest
0 голосов
/ 03 июля 2018

Я бьюсь головой, пытаясь понять этот контракт select:

  1. Предложения

    onSend, onReceive, onReceiveOrNull и onLock атомарно отменяемы. Когда select throw CancellationException, это означает, что эти пункты не выполнили свои соответствующие операции.

  2. В качестве побочного эффекта атомарного отмены, сопрограмма с привязкой к потоку (например, к некоторому потоку пользовательского интерфейса) может продолжать выполняться даже после того, как она была отменена из того же потока в случае, когда эта операция выбора уже была возобновлена атомарно отменяемое предложение и продолжение было отправлено для выполнения в очередь потока.

Это то, что имеет смысл для меня, на примере контекста UI:

  • выражение select выбирает предложение и отправляет его код в очередь событий пользовательского интерфейса
  • когда код выбирается из очереди, в первую очередь проверяется флаг isActive. Если он понижен, код не запускается
  • это нарушило бы атомарность отмены: ни вы не получили CancellationException в предложении select, ни выполнение кода (отмена произошла, когда в очереди ожидал обратный вызов предложения)
  • , поэтому проверка isActive пропускается, и код запускается, хотя в то же время он был отменен

Однако это , а не гарантия, указанная в (1). В нем не сказано «либо ваш код обработки выполняется, либо вы получите CancellationException в выражении select». Он говорит только «если вы получили исключение, это означает, что код не был запущен». Эта гарантия может быть достигнута без поведения, указанного в (2), поэтому это не побочный эффект (1).

Кажется, что описание поведения в (2) является правильным, но предоставляемая им гарантия не соответствует описанию в (1). Это «если вы не получили CancellationException, тогда код обработчика будет запущен».

Разве в документации не должно указываться более надежная гарантия или ?

...