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 :).