我正在用C编写并发事务库,发现了以下问题。让我们考虑一个示例事务成员伪代码,其中“transaction”表示与事务主机的通信通道:

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),强制指定的成员取消事务。成员可以在执行的任何阶段接收中止消息,在这种情况下,它不应该等到执行达到trans_ready()调用。例如,如果在后面的代码中有一个trans_rcv()调用,则进程将挂起等待来自永远不会发送的主机的数据。
现在,重点。我已经有了注册回滚更改的中止函数的代码,但我还希望有一个额外的机制,允许跳过其余操作并立即跳转到投票代码。我想用goto来模拟异常:
if(!trans_rcv()) /* fail, we received the abort message */
{
   goto abort_code;
}

...

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

但是,为每个trans_rcvtrans_send调用编写ifs不是很舒服,尤其是在事务代码很复杂的情况下。你有什么更好的解决办法吗?这是唯一的办法吗?它不必使用goto,顺便说一句:)。

最佳答案

如果输入IFs是问题所在,则可以使用宏,例如:

#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)

09-11 20:44