Структура программы

Конкурентность

Выполняйте задачи через concurrent, выбирайте результат тайм-аута через else и отличайте Err от ошибки выполнения.

Выполняйте независимые задачи через concurrent и собирайте результаты в именованные поля записи. Задайте тайм-аут и укажите в else результат на случай, если время истечёт.

Установите Топаз по разделу Первая программа. Сохраните каждую программу ниже в рабочей папке и выполняйте её команды из этой папки.

Завершаем работу до тайм-аута

Сохраните код в файле concurrency-success.tpz.

TOPAZ
let результат = concurrent(timeout: 3s) {
    итого: 1 + 2
    метка: "ready"
} else {
    { итого: -1, метка: "timeout" }
}

print("{результат.итого} {результат.метка}")

Проверьте и запустите его.

BASH
topaz check concurrency-success.tpz
topaz run concurrency-success.tpz

Обе команды завершаются с кодом 0. Когда обе задачи завершаются за три секунды, программа выводит значения полей результата.

Вывод
3 ready

Каждое именованное выражение внутри concurrent задаёт одну задачу, также называемую arm. Здесь итого вычисляет 3, а метка даёт "ready". Их имена становятся полями записи с результатами. Запись не показывает, какая задача началась или завершилась первой.

Возвращаем другое значение при тайм-ауте

В этой программе одна задача продолжает выполнять цикл. Сохраните код в файле concurrency-timeout.tpz.

TOPAZ
function крутиться() -> int {
    let mut счётчик = 0
    while true { счётчик += 1 }
    счётчик
}

let результат = concurrent(timeout: 5ms) {
    зависло: крутиться()
} else {
    { зависло: -1 }
}

print("{результат.зависло}")

Проверьте и запустите его.

BASH
topaz check concurrency-timeout.tpz
topaz run concurrency-timeout.tpz

Через пять миллисекунд тайм-аут выбирает else, который задаёт весь результат. Обе команды завершаются с кодом 0.

Вывод
-1

При тайм-ауте результаты задач не возвращаются, даже если некоторые задачи уже завершились. Если ваша задача должна завершаться, исправьте условие цикла или входные данные. Возврат значения при тайм-ауте не исправляет незавершённую работу.

Различаем завершение, тайм-аут и ошибки выполнения

Что произошлоРезультат выражения
Все задачи завершились до тайм-аутаЗапись с одним полем для каждой задачи
Время истекло раньшеЗначение блока else
До тайм-аута в задаче возникла ошибка выполненияВсё выражение завершается ошибкой, без выполнения else

Ошибка выполнения, называемая fault, останавливает вычисление, например при выходе за границы массива. Задача, возвращающая Err(error), завершается с обычным значением Result. Это значение попадает в поле с именем задачи. Блок else обрабатывает тайм-аут, не перехватывает ошибки выполнения и не извлекает значения из Err.

Тип результата else должен быть совместим с записью успешных результатов. В обоих примерах обе ветви используют одинаковые имена полей и совместимые типы полей.

Задаём порядок вывода

Если порядок вывода важен, печатайте после возврата из concurrent. Имена задач обозначают результаты, но среда выполнения не определяет порядок запуска и завершения задач. Также не определены чередование вывода, справедливость распределения времени между задачами и повторяемость чередования от запуска к запуску.

После тайм-аута среда выполнения решает, как отменять незавершённые задачи и очищать их ресурсы. Поздние ошибки выполнения задач, результаты которых уже не ожидаются, не передаются выражению Топаза. Не полагайтесь на определённый порядок отмены или очистки.

Записываем допустимый тайм-аут

Пишите целое число и сразу за ним ms, s или m, например 5ms или 3s. Пробелы и формы свойств вроде .seconds недопустимы. Литералы длительности используются в параметре timeout выражения concurrent.

После перевода в миллисекунды значение должно помещаться в беззнаковый u64, от 0 до 18446744073709551615. Большее значение вызывает TPZ5001. Уменьшите литерал до допустимого значения.

ЕдиницаНаибольший допустимый литерал
Миллисекунды18446744073709551615ms
Секунды18446744073709551s
Минуты307445734561825m

Давайте задачам разные имена. Тайм-аут требует else. Форма concurrent { ... } ждёт все задачи без тайм-аута и не допускает else. В примерах приложений явно задавайте тайм-аут.

В Топазе нет неявного асинхронного выполнения, async/await, доступных пользователю дескрипторов задач или общей арифметики длительностей. Об ошибках и порядке выполнения читайте в разделе Поведение среды выполнения, о неподдерживаемом синтаксисе в разделе Запрещённые и отложенные формы.