Я пишу библиотеку параллельных транзакций в 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
, кстати:).