2009-06-03 20 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模塊實現異常。在文章的後半部分注意彙編語言的可怕滑動。