2009-06-03 5 views
0

Ich schreibe eine gleichzeitige Transaktion Bibliothek in C und festgestellt, das folgende Problem. Lassen Sie uns ein Beispiel Transaktions Mitglied Pseudo-Code prüfen, wo die „Transaktion“ mit der Transaktion Master einen Kommunikationskanal darstellt:Wie simuliert man Ausnahmen in C mit 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"); 
} 

In gleichzeitige Transaktionen können wir stimmen nur, wenn wir für die Abstimmung vom Master gefragt werden. Der Master kann jedoch jederzeit trans_abort(member) aufrufen, wodurch das angegebene Mitglied gezwungen wird, die Transaktion abzubrechen. Die ABBRUCH-Nachricht kann von dem Mitglied in jeder Ausführungsphase empfangen werden und in diesem Fall sollte es nicht warten, bis die Ausführung trans_ready() erreicht. Wenn z. B. ein trans_rcv()-Aufruf in dem späteren Code vorhanden ist, würde der Prozess auf Warten auf die Daten vom Master warten, die nie gesendet werden.

Nun, der Punkt. Ich habe bereits den Code, um die Abbruchfunktion zu registrieren, die die Änderungen rückgängig macht, aber ich hätte auch gerne einen zusätzlichen Mechanismus, der es erlaubt, den Rest der verbleibenden Operationen zu überspringen und sofort zum Abstimmungscode zu springen. Ich habe eine Idee, hier gehe zu verwenden, Ausnahmen zu simulieren:

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

... 

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

jedoch ifs für jeden Aufruf von trans_rcv oder trans_send schreiben, ist nicht sehr komfortabel, vor allem, wenn der Transaktionscode komplex ist. Haben Sie eine Idee für eine bessere Lösung oder ist das der einzige Weg? Es muss übrigens nicht goto verwenden :).

+0

Lassen Sie uns sehen, wie viele Leute mit etwas wie "goto? AAAAAAAAAAAAAARGH" kommen: P –

+0

goto? AAAAAAAAAAAAARGH –

Antwort

5

Wenn der ifs eingeben das Problem ist, können Sie einen Makro verwenden, wie:

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

Wenn trans_rcv Parameter hat, sollte dies (in gcc, zumindest) arbeiten:

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

Makros ... wie seltsam ich sie vergessen habe. Danke im Voraus! – Zyx

+2

Stellen Sie sicher, dass Sie das if in a do when false umbrechen. Das heißt, dass Sie trans_rcv_CHK am Ende mit einem Semikolon aufrufen und keine unbeabsichtigten Konsequenzen haben. Siehe: http://c2.com/cgi/wiki/Wiki?TrivialDoWhileLoop –

+1

@sharth: guter Punkt, danke. Ich fügte der Antwort die Schleife hinzu. – tsg

3

Persönlich würde ich dies kodieren, indem ich eine while-Schleife mit einer switch-basierten State-Machine darin benutze.

7

goto funktioniert nur innerhalb einer Funktion, die wahrscheinlich zu viel eine Einschränkung für Ausnahmemechanismus ist.

Ich würde empfehlen, setjmp/longjmp Funktionen zu verwenden - siehe Wikipedia für Details.

3

Eine der besten Quellen für exception handling in C. Grundsätzlich, wie Leute bei RTOS Ausnahmen für ihr RTFile-Modul implementiert haben. Hüten Sie sich vor dem schrecklichen Schlupf in die Assemblersprache nach der zweiten Hälfte des Artikels.