Как смоделировать исключения в C с goto? - PullRequest
0 голосов
/ 03 июня 2009

Я пишу библиотеку параллельных транзакций в C и обнаружил следующую проблему. Рассмотрим пример псевдокода члена транзакции, где «транзакция» представляет канал связи с хозяином транзакции:

transaction = trans_join();

do_some_ops();

/* receive the data from the master */
trans_rcv(transaction, data);

do_some_ops();

trans_send(transaction, answer);

/* wait for the possibility for voting */
trans_ready(transaction);

/* vote for commiting and wait for the voting results. */
if(trans_commit(answer))
{
   printf("Final commiting the changes.\n");
}
else
{
   printf("Rolling back the changes.\n");
}

В параллельных транзакциях мы можем голосовать только в том случае, если мастер попросит нас проголосовать. Однако мастер может вызвать trans_abort(member) в любое время, заставив указанного участника отменить транзакцию. Сообщение ABORT может быть получено участником на любой стадии выполнения, и в этом случае оно не должно ждать, пока выполнение не достигнет вызова trans_ready(). Например, если в последующем коде есть вызов trans_rcv(), процесс будет зависать в ожидании данных от мастера, которые никогда не будут отправлены.

Теперь, точка. У меня уже есть код для регистрации функции отмены, которая откатывает изменения, но я также хотел бы иметь дополнительный механизм, который позволил бы пропустить оставшиеся операции и сразу перейти к коду голосования. У меня есть идея использовать goto здесь для симуляции исключений:

if(!trans_rcv()) /* fail, we received the abort message */
{
   goto abort_code;
}

...

abort_code:
trans_ready(transaction);
/* etc. */

Однако запись ifs для каждого вызова trans_rcv или trans_send не очень удобна, особенно если код транзакции сложный. У вас есть идея для лучшего решения или это единственный способ? Он не должен использовать goto, кстати:).

Ответы [ 5 ]

7 голосов
/ 03 июня 2009

goto работает только внутри одной функции, что, вероятно, является слишком большим ограничением для механизма исключений.

Я бы предложил использовать функции setjmp / longjmp - подробности см. Википедия .

5 голосов
/ 03 июня 2009

Если проблема заключается в наборе IF, вы можете использовать макрос, например:

#define trans_rcv_CHK do { \
     if (!trans_rcv()) \
     { \
          goto abort_code; \
     } \
} while(0)

Если у trans_rcv есть параметры, это должно работать (по крайней мере, в gcc):

#define trans_rcv_CHK(...) do { \
     if (!trans_rcv(__VA_ARGS__)) \
     { \
          goto abort_code; \
     } \
} while (0)
3 голосов
/ 03 июня 2009

Один из лучших источников для обработки исключений в C . В основном, как люди в RTOS реализовали исключения для своего модуля RTFile. Остерегайтесь ужасного проскальзывания на языке ассемблера после второй половины статьи.

3 голосов
/ 03 июня 2009

Лично я бы написал это, используя цикл while с конечным автоматом на основе коммутатора.

1 голос
/ 03 июня 2009

См. «Интерфейсы и реализации C Хэнсона: методы создания программного обеспечения многократного использования ». Он обеспечивает механизм исключения, основанный на setjmp() и longjmp(). Код доступен с лицензией MIT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...