Используйте concurrent, когда независимые выражения могут выполняться одновременно,
а вызывающему коду требуется единая запись с именованными результатами. В обычных
прикладных программах задавайте длительность и явное резервное значение
для тайм-аута.
Успеваем до истечения времени
Сохраните следующий код как concurrency-success.tpz:
let результат = concurrent(timeout: 3s) {
итого: 1 + 2
метка: "ready"
} else {
{ итого: -1, метка: "timeout" }
}
print("{результат.итого} {результат.метка}")Проверьте и запустите его:
topaz check concurrency-success.tpz
topaz run concurrency-success.tpzОбе задачи завершаются до истечения тайм-аута, поэтому их имена становятся полями результата:
3 readyЗапись связывает каждое значение с именем задачи. При этом она не отражает, какая из задач началась или завершилась раньше.
Выбираем запасную ветвь при тайм-ауте
Во второй программе одна из задач не может завершиться. Сохраните код как
concurrency-timeout.tpz:
function крутиться() -> int {
let mut счётчик = 0
while true { счётчик += 1 }
счётчик
}
let результат = concurrent(timeout: 5ms) {
зависло: крутиться()
} else {
{ зависло: -1 }
}
print("{результат.зависло}")Проверьте и запустите его:
topaz check concurrency-timeout.tpz
topaz run concurrency-timeout.tpzЕсли первым истекает тайм-аут, частичные результаты задач не возвращаются, а ветвь
else предоставляет итоговый результат:
-1Различаем три исхода
| Что произошло до истечения тайм-аута | Результат выражения |
|---|---|
| Всё задачи завершились | Запись с одним полем для каждой задачи |
| Первым истёк тайм-аут | Значение блока else |
| В задаче возникла ошибка выполнения | Всё выражение завершается ошибкой, и else не выполняется |
Если задача возвращает Err(error), ошибка выполнения не возникает. Этот Result
является обычным значением в именованном поле результата. Запасная ветвь должна
иметь тип, совместимый с записью успешных задач, поэтому в обоих примерах
успешная ветвь и else используют одинаковые имена полей и совместимые типы
значений.
Имена результатов и планирование
Имена задач сопоставляют результаты с полями записи. Порядок запуска и завершения, чередование вывода, справедливость планировщика и детерминированное чередование не специфицированы. Если порядок вывода важен, сначала объедините задачи, а затем выведите запись.
После тайм-аута отменой и очисткой ресурсов управляет политика среды выполнения. Последующие ошибки оставленных задач не передаются выражению Топаза. Код должен работать независимо от выбора планировщика и деталей очистки после тайм-аута.
Частые исправления
- Пишите
3sили5msбез пробела. Обращение к свойству вроде.secondsне является литералом времени. - Длительность тайм-аута при масштабировании в миллисекунды должна укладываться
в диапазон беззнакового
u64:0..=18446744073709551615. Точные максимальные значения составляют18446744073709551615ms,18446744073709551sи307445734561825m, а каждое следующее значение отклоняется с ошибкойTPZ5001. - Форма с тайм-аутом требует наличия
else, а простое объединение не принимаетelse. - Ветвь
elseобрабатывает только тайм-аут. Она не перехватывает ошибки выполнения и не извлекает значение изErr. - Имена задач должны быть уникальными. Синтаксиса для частичного результата не предусмотрено.
Простое объединение concurrent { ... } без тайм-аута уместно на углублённой
странице, когда ожидание всех задач выступает предметом примера. В обычных
сценариях эта форма не используется по умолчанию.
В Топазе отсутствуют неявная асинхронная модель, синтаксис async/await, доступные
пользователю дескрипторы задач, общая арифметика времени и фиксированный протокол
отмены. Наблюдаемые границы ошибок и порядка выполнения описаны на странице
Поведение среды выполнения, а знакомые синтаксические формы,
которые пока не поддерживаются, — на странице
Запрещённые и отложенные формы.