
Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
There are two main ways to manage with user exceptions: * exceptions commit transactions - corresponds to the current C++ behavior * exceptions abort on exit - corresponds to rollback
I think we should look at this from the user's perspective first and why he would use either of those ways to manage exceptions.
this guideline on exception safety can help us a lot in this I think: http://www.boost.org/community/exception_safety.html
by the definitions of section 3 there, transactions are nothing more than a vehicle to achieve the "strong" exception guarantee.
using "exceptions commit transactions" by your definitino above (which imho does not correspond to current c++ behaviour, if you follow exception guidelines) would mean that you intentionally only use a "basic" exception guarantee for a certain function/transaction scope.
why would that be desirable? as section 5 of david abrahams' paper notes, "From a client's point-of-view, the strongest possible level of safety would be ideal.", and then goes on with considerations on when to accept a "basic" guarantee for performance reasons.
these don't apply for us, as we already impose the overhead described in paragraph 2 on every operation.
I would make a difference between nested transactions and root transactions.
* When a nested transaction throws a user exception the user can handle this exception between the root transaction and the nested transaction. The question is which state of the transaction will be the better to let the user to manage with the user exception? If the nested transaction is rollback the user is unable to know the state of the system when the exception was thrown. But if the transaction is commited, the user will have access to the state as it was when the exception was thrown.
doesn't STM completely roll back an aborted nested transaction so that the root transaction can be committed as if the nested transaction never happened? it should. example: assert(tx_a == 0); transaction{ tx_a=1; try{ transaction{ tx_a=2; throw 5; } }catch(int){} assert(tx_a == 1); } assert(tx_a == 1); the inner transaction scope has exactly the same behaviour as any other function with a "strong" exception guarantee. I don't see a difference between nested and root transactions.
The fact that the functions including nested transactions doesn't satisfy even "The basic guarantee: that the invariants of the component are preserved, and no resources are leaked." it is not important as the action has not been commited completly, as only the root transaction will realize the visible commit.
it satisfies the strong guarantee from the viewpoint of the user, i.e. from inside the (still running) root transaction. that the root transaction is not yet published to other threads or to a persistent state doesn't matter, does it?