
Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
I would prefer the transaction be available on retry. Of courset, this need to have a restart function.
to me this seems similar to
if(int v=f()){ //... }else{ //v is not in available here. }
since the retry{} clause is syntactically a new scope.
You are wrong here. The variable v is accesible on the else part.
oh. I guess that also means that if "v" has a destructor it is called at the end of the else-clause. so if this is a correct parallel the transaction should indeed be destructed at the end of the retry-clause. we can achieve that by moving the declaration of basic_transaction one line to the top, above "try{". but this still doesn't mean that stm::set_priority has anything to work with in the retry{} clause. (other than setting the priority of a transaction that is destructed shortly thereafter)
this can not happen. see the call to nullify(). the whole lifetime of commit_on_destruction is wrapped in a try{} clause. if it throws, commit_on_destruction is nullified. so ~commit_on_destruction does not throw if the scope is exited by exception, and I see no problem with throwing from a destructor otherwise, not even in the case the macros are used in user's destructors. am I missing something?
Yes. In your code the try wrapping the commit_on_destruction variable doesn't nullify the variable as it is out of scope. See (1) and (2)
could you elaborate? I don't see anything wrong. commit_on_destruction::~commit_on_destruction can throw, but ONLY if the user did not. so how can it happen that an exception is thrown during exception unwinding that leads to abort()?
#define BOOST_TRANSACT_BASIC_BEGIN_TRANSACTION(TXMGR) \ { \ int ___control; \ while(true){ \ try{ \ (1) boost::transact::basic_transaction<TXMGR> ___tx; \ boost::transact::detail::commit_on_destruction<TXMGR> ___commit(___tx); \ try{ \ (2) do{ \ ___control=1;
#define BOOST_TRANSACT_BASIC_RETRY(TXMGR) \ ___control=0; \ break; \ }while((___control=2),false); \ }catch(...){ \ (2) ___commit.nullify(); \ throw; \ } \ break; \ }catch(boost::transact::isolation_exception &___i){ \ (2) ___i.unwind<TXMGR>(); \ ___control=0;
I find quite clear the pseudo-code . I was just saying that it would be great to have something like that in C++. Templates work with Types, variables and constants, but don't allows to pass code as parameters.
I looked up c++0x lambda expressions a while ago, which are supposed to allow passing code, but I'd still prefer macros. with c++0x lambdas it would look something like transaction([](){ //user code },[](){ //code on retry });
Option a) has no sens, has the user is not aware of an internal loop.
There is a difference between breaking in the transaction block and breaking on the retry block. Breaking the loop on the the transaction block is expected to succeed the transaction. The retry block is here to repare the fact the transaction is isolated. If the user doesn't reach to repare maybe the solution is to throw the isolation_exception.
Maybe asserting that there are no break/continue will be a good thing.
I agree in principle, it doesn't make much sense to break from there. why would the user want to exit the scope in the same path as if the transactino succeeded. but I think, if he does, breaking from the user loop is expected behaviour. take e.g. a try catch block: for(...){ try{ //... }catch(...){ break; } } does the "break" make sense? hardly. why would you continue with the application as if the whole loop succeeded. but you still expect it to work. I'm not trying to encourage use of "break" there, but if you use it I think you'd expect it to work, not raise an assertion. agreed?
on a related note, I think it should not be possible to rethrow from a retry{} clause:
Why?
because the user isn't even aware that an exception was thrown. from his viewpoint, we could have implemented the whole thing with if(!tx.commit()){ //user's retry code }
I would like the following:
begin_transaction{ //... }retry{ if(retries++ == 5) throw; }end_retry;
what's wrong with explicitely stating the type of exception he wants to throw, instead of rethrowing an exception, even though there is no "catch" clause visible?