Boost logo

Boost :

Subject: Re: [boost] [transact] transaction language macros (was: Re: [transact] code in sandbox)
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2010-02-19 15:15:34


Hi Stefan,
----- Original Message -----
From: <strasser_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Friday, February 19, 2010 4:07 PM
Subject: [boost] [transact] transaction language macros (was: Re: [transact] code in sandbox)

>
> here's my implementation of the macros for discussion:
>
> https://svn.boost.org/trac/boost/changeset/59760

Here's the mine for TBoost.STM
http://svn.boost.org/svn/boost/sandbox/stm/branches/vbe/boost/stm/language_like.hpp

The main differences is that the name of the transaction variable is explicit and that I have added one more try-catch level I have suggested off list.

> below are some example use cases. the (unachievable) ideal syntax would be
>
> transaction{
> //...
> }
>
> for each case.
> actual syntax:
>
> begin_transaction{
> //...
> }end_transaction;
>
>
> in user loops with support for control statements:
>
> for(...){
> begin_transaction{
> if(something) break;
> }end_transaction_in_loop;
> }
>
> the non-loop variant can be used in user loops if there are no control
> statements used.
>
> user code on retry, for example, limiting the number of retries to 5:
>
> int retries=0;
> begin_transaction{
> //...
> }retry{
> if(retries++ == 5) break;
> }end_retry;
>
> the same in a user loop:
>
> for(...){
> begin_transaction{
> if(something) break;
> }retry{
> ...
> }end_retry_in_loop;
> }
>
> the same can be used for the (RM-specific) case we've discussed before
> to increase transaction priority on retry:
>
> int priority=0;
> begin_transaction{
> stm::set_priority(priority);
> //...
> }retry{
> ++priority;
> }end_retry;
>
> stm::set_priority() can use transaction_manager::active_transaction()
> to obtain the transaction.
 
I would prefer

int priority=0;
begin_transaction{
    //...
}retry{
    stm::set_priority(priority++);
}end_retry;

> rolling back a transaction on exception:
>
> try{
> begin_transaction{
> //...
> throw my_exc();
> //...
> }end_transaction;
> }catch(my_exc &){
> //transaction is rolled back
> }
>
> committing the transaction in case of a specific exception:
>
> begin_transaction{
> try{
> //...
> throw my_exc();
> //...
> }catch(my_exc &){
> //tx will commit if my_exc is not rethrown
> }
> }end_transaction;
>
>
> invalid use cases:
>
> using in_loop outside of user loops:
>
> begin_transaction{
>
> }end_transaction_in_loop; //compiler error: illegal "break"
>
>
> using control statements without in_loop:
>
> for(...){
> begin_transaction{
> if(something) break;
> }end_transaction; //error
> }
>
> this raises a runtime assertion if something==true.
> ideal would be a compiler error, but I don't think that is possible.

I like the assertion.
 
> are there any additional use cases to consider?

* committing the transaction and rethrowing a specific exception:

begin_transaction{
   try{
     //...
     throw my_exc();
     //...
   }catch(my_exc &){
        commit();
        throw;
   }
}end_transaction;

This needs to use the transaction_manager::active_transaction() but will not change the state of commit_on_destruction variable.
So we will commit twice. BTW, what is the result of?
    tx.commit();
    tx.commit();

* rollback the transaction and ignore a specific exception:

begin_transaction{
   try{
     //...
     throw my_exc();
     //...
   }catch(my_exc &){
        rollback(); or set_rollback_only();
   }
}end_transaction;

This needs to use the transaction_manager::active_transaction() but will not change the state of commit_on_destruction variable.
So we will commit after rollback. BTW, what is the result of?
    tx.rollback();
    tx.commit();

* Should the following compile?

begin_transaction
   statement1;
   statement1;
end_transaction;

That is, are the enclosing braces needed?

* Just a remark: the following case doesn't do what the user could expect as the user is unable to set the variable __control to 0. It should be stated clearly on the documentation that the user needs to use consistently the macros and that mixing macros and the class level functions is risky.

begin_transaction{
   try{
     //...
   }catch(boost::transact::isolation_exception & ex){
        // do something before retry
   }
}end_transaction;

for(;;)
begin_transaction{
   try{
     //...
   }catch(boost::transact::isolation_exception & ex){
        // do something before retry
   }
}end_transaction_in_loop;
}

> comments on syntax?

As any macro in Boost.Transact must be prefixed with BOOST_TRANSACT, maybe
BOOST_TRANSACT_TRANSACTION/BOOST_TRANSACT_END could be more appropiated than
BOOST_TRANSACT_BEGIN_TRANSACTION/BOOST_TRANSACT_END_TRANSACTION

BOOST_TRANSACT_TRANSACTION {
   //...
} BOOST_TRANSACT_END ;

BOOST_TRANSACT_TRANSACTION {
   //...
} BOOST_TRANSACT_RETRY {
    //...
} BOOST_TRANSACT_END_RETRY;

We could add a 3rd level of try-catch around the user code, so the user can do

BOOST_TRANSACT_TRANSACTION {
   //...
} BOOST_TRANSACT_ON_EXCEPTION(Ex1) {
...
} BOOST_TRANSACT_ON_EXCEPTION(Ex2){
    BOOST_STM_COMMIT_AND_RETHROW();
}BOOST_TRANSACT_ON_EXCEPTION(Ex2){
    BOOST_STM_ABORT(); // no rethrow
}BOOST_TRANSACT_END ;

Best,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk