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 :).
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.
Personally I would code this by using a while loop with a switch based state machine inside of it.
If typing the IFs is the problem, you could use a macro, like:
If trans_rcv has parameters, this should work (in gcc, at least):
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.See Hanson's "C Interfaces and Implementations: Techniques for Creating Reusable Software". It provides an exception mechanism based on
setjmp()
andlongjmp()
. The code is available with an MIT licence.