throw до и после распараллеливания. Тогда, если разные операторы
throw сгенерировали исключения в различных потоках, то программа
должна повести себя так, как если бы исключение было сгенерировано
в операторе, выполняющемся раньше в однопоточной программе.
2. Изменение состояния программы во фрагменте кода, генериру-
ющем исключение, должно соответствовать изменению состояния од-
нопоточного фрагмента кода. Например, если потоки в распараллелен-
ном цикле осуществляют запись в одну и ту же общую переменную,
то после генерации исключения значение этой переменной должно со-
ответствовать значению переменной на той итерации однопоточного
цикла, где произошло исключение.
Требование 2 можно смягчить. Дело в том, что некоторые перемен-
ные могут оказаться неактивными в результате обработки исключения.
Например, если исключение не обрабатывается в той же функции, где
находится распараллеливаемый фрагмент, то ни одна переменная этой
функции (при условии, что она не является синонимом для перемен-
ной более верхнего уровня либо глобальной, либо статической пере-
менной) не будет активной, так как они не прочитаются вследствие
перехода вверх по стеку. Кроме того, при возможности анализа обра-
ботчиков исключения также можно исследовать использование этих
переменных в обрабатывающих исключение функциях. Если в резуль-
тате генерации исключения эти переменные становятся неактивными
и в вызывающем коде, то их состояние можно не отслеживать. Это по-
зволяет оставлять их при генерации исключения в любом состоянии
и не тратить вычислительные ресурсы на отслеживание изменений
таких переменных. Таким образом, проведение проверки на использо-
вание в catch- и finally-блоках переменных, внешних по отношению к
распараллеливаемому фрагменту, дает возможность избежать наклад-
ных расходов.
Метод решения задачи.
Начнем процесс распараллеливания ис-
ходного кода программы. Распределим распараллеливаемый фрагмент
на потоки выполнения. В результате разбиения получим потоки, в ко-
торых один или несколько потоков могут сгенерировать исключение.
Проблема перехвата исключения и передачи его следующему за
распараллеливаемым фрагментом коду может быть решена с помощью
установки одного или нескольких флагов исключения. Для выставле-
ния флага исключения код всех потоков заключается в try-блоки. Со-
ответствующие этим try-блокам catch-блоки должны быть настроены
на перехват всех исключений, как и ошибок времени выполнения (на-
пример, с использованием инструкций
catch
(
Throwable thr
) в языке
Java [1] и
catch (. . . )
в языке C++ [7]). Задача обрамляющего обра-
ботчика исключений — выставление флага исключения и сохранение
объекта исключения для последующей передачи в последовательный
74 ISSN 0236-3933. Вестник МГТУ им. Н.Э. Баумана. Сер. “Приборостроение”. 2014. № 6