2009-06-03 21 views
0

我正在C编写一个并发事务库,并发现以下问题。让我们考虑一个样本交易员伪代码,其中“交易”代表与交易高手的通信信道:如何在C中模拟异常与goto?

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()调用,则该进程将在等待来自主服务器的数据时挂起,这将永远不会发送。

现在,重点。我已经有了注册中止函数的代码来回滚这些更改,但是我还希望有一个额外的机制可以跳过剩余的其余操作并立即跳转到投票代码。我有一个主意,用转到这里来模拟例外:

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

... 

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

然而,对于trans_rcvtrans_send每次调用写IFS不是很舒服,特别是如果交易代码是复杂的。你有任何想法提供更好的解决方案,或者这是唯一的方法吗?顺便说一句:)它不必使用goto

+0

让我们来看看有多少人会有像“goto?AAAAAAAAAAAAARGH”:P – 2009-06-03 09:30:45

+0

goto? AAAAAAAAAAAAARGH – 2009-06-03 19:04:45

回答

5

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

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

7

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

我建议使用setjmp/longjmp函数 - 详见Wikipedia

3

exception handling in C的最佳来源之一。基本上RTOS的人们如何为其RTFile模块实现异常。在文章的后半部分注意汇编语言的可怕滑动。