私はCでトランザクションライブラリを作成していますが、次の問題が見つかりました。さんは、「取引は」取引マスターとの通信チャネルを表しサンプルトランザクション会員擬似コードを、考えてみましょう:私たちはマスタによる投票を求めている場合にのみ、同時トランザクションでgotoで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. */
トランザクションコードが複雑な場合は特にしかし、trans_rcv
またはtrans_send
のすべての呼び出しのためにIFSを書くことは、非常に快適ではありません。よりよい解決策があるか、これが唯一の方法ですか?ちなみに、goto
を使用する必要はありません:)。 trans_rcvはパラメータがある場合
#define trans_rcv_CHK do { \
if (!trans_rcv()) \
{ \
goto abort_code; \
} \
} while(0)
が、これは(少なくとも、GCCで)動作するはずです::
#define trans_rcv_CHK(...) do { \
if (!trans_rcv(__VA_ARGS__)) \
{ \
goto abort_code; \
} \
} while (0)
"goto?AAAAAAAAAAAARGH"のようなものが何人来るのでしょうか?P –
goto? –