如何用goto模拟C语言中的异常?

发布于 2024-07-22 11:47:39 字数 1199 浏览 7 评论 0原文

我正在用 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");
}

在并发事务中,只有当主控要求我们投票时,我们才能投票。 然而,master可以随时调用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_rcvtrans_send 编写 ifs 并不是很舒服,尤其是如果交易代码很复杂。 您有更好的解决方案吗?还是这是唯一的方法? 顺便说一句,它不必使用 goto :)。

I'm writing a concurrent transaction library in C and found the following problem. Let's consider a sample transaction member pseudo-code, where the "transaction" represents a communication channel with the transaction master:

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");
}

In concurrent transactions, we can vote only if we are asked for the vote by the master. However, the master can call trans_abort(member) at any time, forcing the specified member to cancel the transaction. The ABORT message can be received by the member at any stage of execution and in this case unsually it should not wait till the execution reaches trans_ready() call. For example, if there is a trans_rcv() call in the later code, the process would hang on waiting for the data from the master which will be never sent.

Now, the point. I have already the code to register the aborting function that rolls back the changes, but I would also like to have an extra mechanism that would allow to skip the rest of the remaining operations and jump to the voting code immediately. I have an idea to use goto here to simulate exceptions:

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

...

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

However, writing ifs for every call of trans_rcv or trans_send is not very comfortable, especially if the transaction code is complex. Have you got any idea for a better solution or is this the only way? It does not have to use goto, by the way :).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

如果没结果 2024-07-29 11:47:39

goto 只能在一个函数内部工作,这对于异常机制来说可能是一个太大的限制。

我建议使用 setjmp/longjmp 函数 - 请参阅 维基百科了解详细信息。

goto works only inside one function, which is probably too much a limitation for exception mechanism.

I'd suggest to use setjmp/longjmp functions - see Wikipedia for details.

平定天下 2024-07-29 11:47:39

如果输入 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)

If typing the IFs is the problem, you could use a macro, like:

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

If trans_rcv has parameters, this should work (in gcc, at least):

#define trans_rcv_CHK(...) do { \
     if (!trans_rcv(__VA_ARGS__)) \
     { \
          goto abort_code; \
     } \
} while (0)
我三岁 2024-07-29 11:47:39

就我个人而言,我会使用 while 循环来编写此代码,其中包含基于开关的状态机。

Personally I would code this by using a while loop with a switch based state machine inside of it.

故笙诉离歌 2024-07-29 11:47:39

C 中的异常处理的最佳来源之一。 基本上 RTOS 的人们如何为其 RTFile 模块实现异常。 当心文章后半部分可怕的汇编语言。

One of the best source for exception handling in C. Basically how people at RTOS implemented exceptions for their RTFile module. Beware of the dreadful slip into assembly language past the second half of the article.

池木 2024-07-29 11:47:39

请参阅 Hanson 的“C 接口和实现:创建可重用软件的技术”。 它提供了基于setjmp()longjmp()的异常机制。 该代码可通过 MIT 许可证获得。

See Hanson's "C Interfaces and Implementations: Techniques for Creating Reusable Software". It provides an exception mechanism based on setjmp() and longjmp(). The code is available with an MIT licence.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文