$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r60906 - in sandbox/transaction: boost/transact libs/transact libs/transact/build libs/transact/doc libs/transact/doc/html libs/transact/example libs/transact/src libs/transact/test libs/transaction
From: strasser_at_[hidden]
Date: 2010-03-28 17:46:33
Author: stefans
Date: 2010-03-28 17:46:32 EDT (Sun, 28 Mar 2010)
New Revision: 60906
URL: http://svn.boost.org/trac/boost/changeset/60906
Log:
 - transaction restart service
 - fixed behaviour of isolation_exception::unwind()
 - fixed basic_transaction behaviour wrt transaction binding according to the new macros
 - changed basic_transaction_manager defaults to non-lazy transaction starts
 - active transaction -> current transaction
Added:
   sandbox/transaction/boost/transact/resource_manager.hpp   (contents, props changed)
   sandbox/transaction/libs/transact/
   sandbox/transaction/libs/transact/build/
   sandbox/transaction/libs/transact/doc/
   sandbox/transaction/libs/transact/doc/html/
   sandbox/transaction/libs/transact/example/
   sandbox/transaction/libs/transact/src/
   sandbox/transaction/libs/transact/test/
   sandbox/transaction/libs/transact/test/transaction_stack_unwind.cpp   (contents, props changed)
Removed:
   sandbox/transaction/libs/transaction/
Text files modified: 
   sandbox/transaction/boost/transact/basic_transaction.hpp          |    58 ++------                                
   sandbox/transaction/boost/transact/basic_transaction_manager.hpp  |   246 ++++++++++++++++++++++----------------- 
   sandbox/transaction/boost/transact/exception.hpp                  |    38 +++--                                   
   sandbox/transaction/boost/transact/simple_transaction_manager.hpp |   108 ++++++++++------                        
   4 files changed, 243 insertions(+), 207 deletions(-)
Modified: sandbox/transaction/boost/transact/basic_transaction.hpp
==============================================================================
--- sandbox/transaction/boost/transact/basic_transaction.hpp	(original)
+++ sandbox/transaction/boost/transact/basic_transaction.hpp	2010-03-28 17:46:32 EDT (Sun, 28 Mar 2010)
@@ -25,15 +25,15 @@
 class basic_transaction : noncopyable{
 public:
     /// Binds the new transaction to this thread.
-    /// If there already is an active transaction, the new transaction will be a nested transaction
-    /// of the active transaction.
+    /// If there already is an current transaction, the new transaction will be a nested transaction
+    /// of the current transaction.
     ///
     /// Throws: \c no_transaction_manager, \c io_failure, \c thread_resource_error,
     /// resource-specific exceptions
     /// thrown by resource managers beginning local transactions.
     /// \brief Constructs a basic_transaction, beginning a new transaction scope
     explicit basic_transaction()
-        : parent(TxMgr::has_active_transaction() ? &TxMgr::active_transaction() : 0)
+        : parent(TxMgr::has_current_transaction() ? &TxMgr::current_transaction() : 0)
         , tx(TxMgr::begin_transaction())
         , done(false){
         TxMgr::bind_transaction(this->tx);
@@ -54,52 +54,29 @@
 #endif
             }
         }
-        try{
-            this->pop();
-        }catch(...){
-#ifndef NDEBUG
-            std::cerr << "ignored exception" << std::endl;
-#endif
-        }
+        //bind_ and unbind_transaction can throw thread_resource_error.
+        //in the unlikely case it is actually thrown, it is not ignored, even though this is a destructor.
+        //if the current transaction cannot be bound correctly all following transactional operations are invalid.
+        //abort() is preferrable to that.
+        if(this->parent) TxMgr::bind_transaction(*this->parent);
+        else TxMgr::unbind_transaction();
     }
 
-    /// If this is a nested transaction, sets the active transaction to the parent transaction.
-    /// If this is a root transaction, resets the active transaction.
-    ///
     /// Throws: \c isolation_exception, \c io_failure, \c thread_resource_error,
     /// resource-specific exceptions thrown by resource managers committing local
     /// transactions.
     /// \brief Commits the transaction.
     void commit(){
         this->done=true;
-        try{
-            TxMgr::commit_transaction(this->tx);
-        }catch(...){
-            this->pop();
-            throw;
-        }
-    }
-    /// \cond
-    void commit_(){
-        this->commit();
+        TxMgr::commit_transaction(this->tx);
     }
-    /// \endcond
 
-    /// If this is a nested transaction, sets the active transaction to the parent transaction.
-    /// If this is a root transaction, resets the active transaction.
-    ///
     /// Throws: \c io_failure, \c thread_resource_error, resource-specific exceptions
     /// thrown by resource managers rolling back transactions.
     /// \brief Unwinds all changes made during this transaction.
     void rollback(){
         this->done=true;
-        try{
-            TxMgr::rollback_transaction(this->tx);
-        }catch(...){
-            this->pop();
-            throw;
-        }
-        this->pop();
+        TxMgr::rollback_transaction(this->tx);
     }
 
     /// Throws: thread_resource_error
@@ -111,21 +88,18 @@
     /// Throws: thread_resource_error
     /// \brief If the current thread is bound to this transaction, unbinds it
     void unbind(){
-        if(TxMgr::has_active_transaction() &&
-            &TxMgr::active_transaction() == &this->tx){
+        if(TxMgr::has_current_transaction() &&
+            &TxMgr::current_transaction() == &this->tx){
             TxMgr::unbind_transaction();
         }
     }
 
-    void restart(){}
+    void restart(){
+        TxMgr::restart_transaction(this->tx);
+    }
 
     /// \cond
 private:
-    void pop(){
-        if(this->parent) TxMgr::bind_transaction(*this->parent);
-        else TxMgr::unbind_transaction();
-    }
-
     typename TxMgr::transaction *parent;
     typename TxMgr::transaction tx;
     bool done;
Modified: sandbox/transaction/boost/transact/basic_transaction_manager.hpp
==============================================================================
--- sandbox/transaction/boost/transact/basic_transaction_manager.hpp	(original)
+++ sandbox/transaction/boost/transact/basic_transaction_manager.hpp	2010-03-28 17:46:32 EDT (Sun, 28 Mar 2010)
@@ -12,6 +12,7 @@
 #include <boost/transact/detail/mutex.hpp>
 #include <boost/transact/exception.hpp>
 #include <boost/transact/detail/static_tss.hpp>
+#include <boost/transact/resource_manager.hpp>
 #include <boost/type_traits/add_pointer.hpp>
 #include <boost/fusion/include/mpl.hpp>
 #include <boost/fusion/include/as_vector.hpp>
@@ -54,14 +55,6 @@
 struct get_tag{
     typedef typename Resource::tag type;
 };
-template<class Resources>
-struct default_lazy_resources{
-    typedef typename mpl::if_c<
-        mpl::size<Resources>::value==1,
-        mpl::empty_sequence,
-        typename mpl::transform<Resources,get_tag<mpl::_1> >::type
-    >::type type;
-};
 
 template<class State,class F>
 struct runtime_folder{
@@ -96,101 +89,107 @@
 ///        access of the resource transaction. This can be beneficial when 2 or more
 ///        resource managers are used but not every resource is accessed in a global
 ///        transaction.
-///        By default, all resource transactions
-///        are started lazily, unless there is only one resource manager used.
 /// \brief A transaction manager
 template<
     class Resources,
     bool Threads=true,
     bool TThreads=true,
-    class Lazy=typename detail::default_lazy_resources<Resources>::type
+    class Lazy=mpl::empty_sequence
 >
 class basic_transaction_manager : noncopyable{
 /// \cond
     BOOST_STATIC_ASSERT(Threads || !TThreads);
+public:
+    class transaction;
 private:
-    struct detail{
-        typedef typename mpl::transform<
-            Resources,
-            transact::detail::get_tag<mpl::_1>
-        >::type resource_tags;
+    typedef typename mpl::transform<
+        Resources,
+        transact::detail::get_tag<mpl::_1>
+    >::type resource_tags;
 
-        template<class Resource>
-        struct make_resource_pair{
-            typedef mpl::pair<typename Resource::tag,Resource> type;
-        };
-        typedef typename mpl::fold<
-            Resources,
-            mpl::map0<>,
-            mpl::insert<mpl::_1,make_resource_pair<mpl::_2> >
-        >::type resource_types_by_tag;
+    template<class Resource>
+    struct make_resource_pair{
+        typedef mpl::pair<typename Resource::tag,Resource> type;
+    };
+    typedef typename mpl::fold<
+        Resources,
+        mpl::map0<>,
+        mpl::insert<mpl::_1,make_resource_pair<mpl::_2> >
+    >::type resource_types_by_tag;
+
+    template<class Tag>
+    struct resource_type{
+        typedef typename mpl::at<resource_types_by_tag,Tag>::type type;
+    };
+
+    class transaction_construct_t{
+        explicit transaction_construct_t(transaction *parent)
+            : parent(parent){}
+        friend class basic_transaction_manager;
+        transaction *parent;
+    };
+
+    struct currenttx_tag{};
+    typedef transact::detail::static_thread_specific_ptr<
+        transaction,
+        currenttx_tag,
+        Threads> currenttx;
 
+    template<class Resource>
+    struct get_services{
+        typedef typename Resource::services type;
+    };
+    struct detail{ //for QuickBook
+        typedef typename basic_transaction_manager::transaction_construct_t transaction_construct_t;
         template<class Tag>
         struct resource_type{
-            typedef typename mpl::at<resource_types_by_tag,Tag>::type type;
-        };
-
-        template<class Resource>
-        struct get_services{
-            typedef typename Resource::services type;
+            typedef typename basic_transaction_manager::template resource_type<Tag>::type type;
         };
-        template<class Service>
+        template<class ServiceTag>
         struct default_resource{
             typedef typename mpl::deref<
                 typename mpl::find_if<
                     Resources,
-                    mpl::contains<get_services<mpl::_1>,Service>
+                    mpl::contains<get_services<mpl::_1>,ServiceTag>
                 >::type
             >::type::tag type;
         };
+    };
 
-        class transaction;
-        class transaction_construct_t{
-            explicit transaction_construct_t(transaction *parent)
-                : parent(parent){}
-            friend class basic_transaction_manager;
-            transaction *parent;
-        };
-
-        class transaction : noncopyable{
-        public:
-            explicit transaction(transaction_construct_t const &c) : parent(c.parent){
-                mpl::for_each<resource_tags>(beginner(*this));
-            }
-        private:
-            friend class basic_transaction_manager;
-    
-            template<class Resource>
-            struct make_resource_transaction_pair{
-                typedef fusion::pair<typename Resource::tag,optional<typename Resource::transaction> > type;
-            };
-            typedef typename fusion::result_of::as_map<
-                typename mpl::transform<
-                    Resources,
-                    make_resource_transaction_pair<mpl::_1>
-                >::type
-            >::type resource_transactions_type;
-            resource_transactions_type resource_transactions;
-
-            transaction * const parent;
+    /// \endcond
+public:
+    class transaction : noncopyable{
+    /// \cond
+    public:
+        explicit transaction(transaction_construct_t const &c) : parent(c.parent){
+            mpl::for_each<resource_tags>(beginner(*this));
+        }
+    private:
+        friend class basic_transaction_manager;
 
-            typedef typename mpl::if_c<
-                TThreads,
-                transact::detail::mutex_type,
-                transact::detail::null_lockable
-            >::type mutex_type;
-    
-            mutex_type mutex;
+        template<class Resource>
+        struct make_resource_transaction_pair{
+            typedef fusion::pair<typename Resource::tag,optional<typename Resource::transaction> > type;
         };
-    };
-    struct activetx_tag{};
-    typedef transact::detail::static_thread_specific_ptr<
-        typename detail::transaction,
-        activetx_tag,
-        Threads> activetx;
+        typedef typename fusion::result_of::as_map<
+            typename mpl::transform<
+                Resources,
+                make_resource_transaction_pair<mpl::_1>
+            >::type
+        >::type resource_transactions_type;
+        resource_transactions_type resource_transactions;
+
+        transaction * const parent;
+
+        typedef typename mpl::if_c<
+            TThreads,
+            transact::detail::mutex_type,
+            transact::detail::null_lockable
+        >::type mutex_type;
+
+        mutex_type mutex;
     /// \endcond
-public:
-    typedef typename detail::transaction transaction;
+    };
     typedef Resources resource_types;
     template<class ServiceTag>
     struct default_resource{
@@ -218,61 +217,64 @@
     }
 
     template<class Tag>
-    static typename detail::resource_type<Tag>::type &resource(Tag tag=Tag()){
-        typename detail::resource_type<Tag>::type *res
+    static typename detail::template resource_type<Tag>::type &resource(Tag tag=Tag()){
+        typename resource_type<Tag>::type *res
             =fusion::at_key<Tag>(resources);
         if(res) return *res;
         else throw resource_error();
     }
 
     template<class Tag>
-    static typename detail::resource_type<Tag>::type::transaction &
+    static typename detail::template resource_type<Tag>::type::transaction &
     resource_transaction(transaction &tx,Tag tag=Tag()){
         return resource_transaction(tx,tag,typename mpl::contains<Lazy,Tag>());
     }
 
     static typename detail::transaction_construct_t begin_transaction(){
-        return typename detail::transaction_construct_t(activetx::get());
+        return transaction_construct_t(currenttx::get());
     }
 
     static void commit_transaction(transaction &tx){
-        typedef typename detail::resource_tags tags;
         bind_transaction(tx);
 
         //call finish_transaction until all transactions return false
-        while(transact::detail::runtime_fold<tags>(false,finisher(tx)));
+        while(transact::detail::runtime_fold<resource_tags>(false,finisher(tx)));
 
-        mpl::for_each<tags>(preparer<false>(tx)); //prepare transient two-phase transactions
+        mpl::for_each<resource_tags>(preparer<false>(tx)); //prepare transient two-phase transactions
         //count persistent transactions and transactions that only support one-phase commit:
-        std::size_t pers=transact::detail::runtime_fold<tags>(0,persistent_counter(tx));
+        std::size_t pers=transact::detail::runtime_fold<resource_tags>(0,persistent_counter(tx));
         if(pers > 1){
-            mpl::for_each<tags>(preparer<true>(tx)); //prepare persistent transactions
+            mpl::for_each<resource_tags>(preparer<true>(tx)); //prepare persistent transactions
             //TODO write commit message to log
-            mpl::for_each<tags>(committer<true>(tx)); //commit persistent transactions
+            mpl::for_each<resource_tags>(committer<true>(tx)); //commit persistent transactions
         }else{
-            mpl::for_each<tags>(committer<true>(tx)); //commit persistent transaction unprepared
+            mpl::for_each<resource_tags>(committer<true>(tx)); //commit persistent transaction unprepared
         }
-        mpl::for_each<tags>(committer<false>(tx)); //commit transient two-phase transactions
+        mpl::for_each<resource_tags>(committer<false>(tx)); //commit transient two-phase transactions
     }
 
     static void rollback_transaction(transaction &tx){
         bind_transaction(tx);
-        mpl::for_each<detail::resource_tags>(rollbacker(tx));
+        mpl::for_each<resource_tags>(rollbacker(tx));
+    }
+
+    static void restart_transaction(transaction &tx){
+        mpl::for_each<resource_tags>(restarter(tx));
     }
 
     static void bind_transaction(transaction &tx){
-        activetx::reset(&tx);
+        currenttx::reset(&tx);
     }
     static void unbind_transaction(){
-        activetx::reset(0);
+        currenttx::reset(0);
     }
 
-    static transaction &active_transaction(){
-        if(transaction *tx=activetx::get()) return *tx;
-        else throw no_active_transaction();
+    static transaction ¤t_transaction(){
+        if(transaction *tx=currenttx::get()) return *tx;
+        else throw no_transaction();
     }
-    static bool has_active_transaction(){
-        return activetx::get() ? true : false;
+    static bool has_current_transaction(){
+        return currenttx::get() ? true : false;
     }
 
     /// \cond
@@ -281,7 +283,7 @@
         explicit persistent_counter(transaction &tx) : tx(tx){}
         template<class Tag>
         std::size_t operator()(std::size_t c,Tag){
-            typedef typename detail::resource_type<Tag>::type res_type;
+            typedef typename resource_type<Tag>::type res_type;
             if(is_persistent<res_type>::type::value){
                 if(fusion::at_key<Tag>(tx.resource_transactions)){
                     return c+1;
@@ -296,7 +298,7 @@
         explicit finisher(transaction &tx) : tx(tx){}
         template<class Tag>
         bool operator()(bool repeat,Tag tag){
-            typedef typename detail::resource_type<Tag>::type res_type;
+            typedef typename resource_type<Tag>::type res_type;
             optional<typename res_type::transaction> &rtx=
                 fusion::at_key<Tag>(tx.resource_transactions);
             if(rtx){
@@ -320,7 +322,7 @@
         void begin(Tag,mpl::true_ lazy){}
         template<class Tag>
         void begin(Tag,mpl::false_ lazy){
-            typedef typename detail::resource_type<Tag>::type res_type;
+            typedef typename resource_type<Tag>::type res_type;
             res_type *rmgr=fusion::at_key<Tag>(resources);
             if(rmgr){
                 optional<typename res_type::transaction> &rtx=
@@ -336,9 +338,9 @@
         transaction &tx;
     };
     template<class Tag>
-    static typename detail::resource_type<Tag>::type::transaction &
+    static typename detail::template resource_type<Tag>::type::transaction &
     resource_transaction(transaction &tx,Tag tag,mpl::true_ lazy){
-        typedef typename detail::resource_type<Tag>::type res_type;
+        typedef typename resource_type<Tag>::type res_type;
         optional<typename res_type::transaction> &rtx=
             fusion::at_key<Tag>(tx.resource_transactions);
 
@@ -362,9 +364,9 @@
         return *rtx;
     }
     template<class Tag>
-    static typename detail::resource_type<Tag>::type::transaction &
+    static typename detail::template resource_type<Tag>::type::transaction &
     resource_transaction(transaction &tx,Tag tag,mpl::false_ lazy){
-        typedef typename detail::resource_type<Tag>::type res_type;
+        typedef typename resource_type<Tag>::type res_type;
         optional<typename res_type::transaction> &rtx=
             fusion::at_key<Tag>(tx.resource_transactions);
         BOOST_ASSERT(rtx);
@@ -384,7 +386,7 @@
         explicit committer(transaction &tx) : tx(tx){}
         template<class Tag>
         void operator()(Tag){
-            typedef typename detail::resource_type<Tag>::type res_type;
+            typedef typename resource_type<Tag>::type res_type;
             if(Persistent == is_persistent<res_type>::type::value){
                 optional<typename res_type::transaction> &rtx=
                     fusion::at_key<Tag>(tx.resource_transactions);
@@ -403,9 +405,9 @@
         explicit preparer(transaction &tx) : tx(tx){}
         template<class Tag>
         void operator()(Tag){
-            typedef typename detail::resource_type<Tag>::type res_type;
+            typedef typename resource_type<Tag>::type res_type;
             if(Persistent == is_persistent<res_type>::type::value){
-                typedef typename detail::resource_type<Tag>::type res_type;
+                typedef typename resource_type<Tag>::type res_type;
                 optional<typename res_type::transaction> &rtx=
                     fusion::at_key<Tag>(tx.resource_transactions);
                 if(rtx){
@@ -432,16 +434,44 @@
         explicit rollbacker(transaction &tx) : tx(tx){}
         template<class Tag>
         void operator()(Tag){
-            typedef typename detail::resource_type<Tag>::type res_type;
+            typedef typename resource_type<Tag>::type res_type;
+            optional<typename res_type::transaction> &rtx=
+                fusion::at_key<Tag>(tx.resource_transactions);
+            if(rtx){
+                res_type *res=fusion::at_key<Tag>(resources);
+                BOOST_ASSERT(res);
+                res->rollback_transaction(*rtx);
+            }
+        }
+    private:
+        transaction &tx;
+    };
+    struct restarter{
+        explicit restarter(transaction &tx) : tx(tx){}
+        template<class Tag>
+        void operator()(Tag){
+            typedef typename resource_type<Tag>::type res_type;
             optional<typename res_type::transaction> &rtx=
                 fusion::at_key<Tag>(tx.resource_transactions);
             if(rtx){
                 res_type *res=fusion::at_key<Tag>(resources);
                 BOOST_ASSERT(res);
+                this->operator()(*res,rtx,typename mpl::contains<typename res_type::services,transaction_restart_service_tag>::type());
                 res->rollback_transaction(*rtx);
             }
         }
     private:
+        template<class Resource>
+        void operator()(Resource &res,optional<typename Resource::transaction> &rtx,mpl::true_ service){
+            res.restart_transaction(*rtx);
+        }
+        template<class Resource>
+        void operator()(Resource &res,optional<typename Resource::transaction> &rtx,mpl::false_ service){
+            rtx=none;
+            beginner begin(this->tx);
+            begin(typename Resource::tag()); //TODO optimization: looked up twice. esp. with stateful tags.
+        }
+
         transaction &tx;
     };
     template<class Resource>
Modified: sandbox/transaction/boost/transact/exception.hpp
==============================================================================
--- sandbox/transaction/boost/transact/exception.hpp	(original)
+++ sandbox/transaction/boost/transact/exception.hpp	2010-03-28 17:46:32 EDT (Sun, 28 Mar 2010)
@@ -7,7 +7,7 @@
 #ifndef BOOST_TRANSACT_EXCEPTION_HEADER_HPP
 #define BOOST_TRANSACT_EXCEPTION_HEADER_HPP
 
-#include <stdexcept>
+#include <exception>
 #include <boost/mpl/begin.hpp>
 #include <boost/mpl/end.hpp>
 #include <boost/mpl/next.hpp>
@@ -27,8 +27,9 @@
 ///\brief Indicates that an internal operation reading from/writing to files failed.
 struct io_failure : transact::exception{};
 
-///\brief Indicates that this operation required an active transaction but there was no active transaction bound for this thread.
-struct no_active_transaction : transact::exception{};
+///\brief Indicates that this operation required a transaction but there was no transaction bound to this thread, or that the operation
+///required an active transaction but the transaction bound to this thread was inactive.
+struct no_transaction : transact::exception{};
 
 ///\brief Indicates an error with regard to connecting a resource to a transaction manager
 struct resource_error : transact::exception{};
@@ -78,13 +79,14 @@
 ///\c isolation_exception is an abstract base class. The derived class
 ///\c resource_isolation_exception can be used to throw this exception.
 struct isolation_exception : transact::exception{
-    ///Rethrows the exception if the active transaction is a nested transaction but the isolation exception was caused by a parent transaction of it.
+    ///Rethrows the exception if the current transaction is a nested transaction but the isolation exception was caused by a parent transaction of it,
+    ///or if the isolation_exception was caused independently of a transaction.
+    ///\pre TxMgr::current_transaction() must be a rolled back transaction
     template<class TxMgr>
     void unwind() const{ //pseudo-virtual
         detail::isolation_unwind_visitor<TxMgr,typename mpl::begin<typename TxMgr::resource_types>::type> visit;
         visit(*this);
     }
-    virtual ~isolation_exception()throw (){}
 protected:
     isolation_exception(){}
 };
@@ -97,22 +99,26 @@
 template<class ResMgr>
 struct resource_isolation_exception : isolation_exception{
     ///\brief Constructs a resource_isolation_exception
-    ///\param unwind_to A pointer to the transaction that ought to be active when
-    ///unwind() returns. Must be a transaction on the nested transaction
-    ///stack. If 0, unwind() rethrows the exception until all transactions
-    ///including the root transaction are destroyed.
-    explicit resource_isolation_exception(typename ResMgr::transaction *unwind_to)
-        : to(unwind_to){}
+    resource_isolation_exception() : retry(0){}
+
+    ///\brief Constructs a resource_isolation_exception
+    ///\param retry The transaction that caused the isolation_exception and ought to be repeated.
+    ///Must be a transaction on the nested transaction stack.
+    explicit resource_isolation_exception(typename ResMgr::transaction &retry)
+        : retry(&retry){}
+
+    ///Throws: thread_resource_error. no_transaction if \c retry was not on the nested transaction stack or it was removed before unwind() was called.
     ///\brief Equivalent to <tt>isolation_exception::unwind<TxMgr>()</tt>
+    ///\pre TxMgr::current_transaction() must be a rolled back transaction
     template<class TxMgr>
     void unwind() const{ //pseudo-virtual
-        if(this->to){
-            typename ResMgr::transaction &tx=TxMgr::resource_transaction(TxMgr::active_transaction(),typename ResMgr::tag());
-            if(&tx != this->to) throw;
-        }else if(TxMgr::has_active_transaction()) throw;
+        if(this->retry){
+            typename ResMgr::transaction ¤ttx=TxMgr::resource_transaction(TxMgr::current_transaction(),typename ResMgr::tag());
+            if(this->retry != ¤ttx) throw;
+        }else throw;
     }
 private:
-    typename ResMgr::transaction *to;
+    typename ResMgr::transaction *retry;
 };
 
 }
Added: sandbox/transaction/boost/transact/resource_manager.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/resource_manager.hpp	2010-03-28 17:46:32 EDT (Sun, 28 Mar 2010)
@@ -0,0 +1,19 @@
+//          Copyright Stefan Strasser 2010.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_TRANSACT_RESOURCE_MANAGER_HPP
+#define BOOST_TRANSACT_RESOURCE_MANAGER_HPP
+
+namespace boost{
+namespace transact{
+
+struct transaction_restart_service_tag{};
+
+}
+}
+
+
+#endif
Modified: sandbox/transaction/boost/transact/simple_transaction_manager.hpp
==============================================================================
--- sandbox/transaction/boost/transact/simple_transaction_manager.hpp	(original)
+++ sandbox/transaction/boost/transact/simple_transaction_manager.hpp	2010-03-28 17:46:32 EDT (Sun, 28 Mar 2010)
@@ -8,11 +8,14 @@
 #define BOOST_TRANSACT_SIMPLE_TRANSACTION_MANAGER_HEADER_HPP
 
 #include <boost/mpl/vector.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/bool.hpp>
 #include <boost/utility/in_place_factory.hpp>
 #include <boost/optional/optional.hpp>
 #include <boost/transact/exception.hpp>
 #include <boost/noncopyable.hpp>
 #include <boost/transact/detail/static_tss.hpp>
+#include <boost/transact/resource_manager.hpp>
 
 namespace boost{
 namespace transact{
@@ -27,44 +30,48 @@
 // \brief A transaction manager that only supports one resource manager.
 template<class Resource,bool Threads=true>
 class simple_transaction_manager : noncopyable{
+public:
+    class transaction;
 private:
-    struct detail{
-        class transaction;
-        class transaction_construct_t{
-            explicit transaction_construct_t(transaction *parent)
-                : parent(parent){}
-            friend class simple_transaction_manager;
-            friend class transaction;
-            transaction *parent;
-        };
-
-        class transaction : noncopyable{
-        public:
-            explicit transaction(transaction_construct_t const &c)
-                : parent(c.parent){
-                if(res){
-                    if(this->parent){
-                        this->rtx=in_place(res->begin_nested_transaction(*this->parent->rtx));
-                    }else{
-                        this->rtx=in_place(res->begin_root_transaction());
-                    }
-                }
-            }
-        private:
-            friend class simple_transaction_manager;
-            optional<typename Resource::transaction> rtx;
-            transaction * const parent;
-        };
+    class transaction_construct_t{
+        explicit transaction_construct_t(transaction *parent)
+            : parent(parent){}
+        friend class simple_transaction_manager;
+        friend class transaction;
+        transaction *parent;
     };
-    struct activetx_tag{};
+    struct currenttx_tag{};
     typedef transact::detail::static_thread_specific_ptr<
-        typename detail::transaction,
-        activetx_tag,
-        Threads> activetx;
+        transaction,
+        currenttx_tag,
+        Threads> currenttx;
+
+    struct detail{ //for QuickBook
+        typedef typename simple_transaction_manager::transaction_construct_t transaction_construct_t;
+    };
     /// \endcond
 public:
-    typedef typename detail::transaction transaction;
-    typedef mpl::vector<Resource> resource_types;
+    class transaction : noncopyable{
+    /// \cond
+    public:
+        explicit transaction(transaction_construct_t const &c)
+            : parent(c.parent){
+            if(res){
+                if(this->parent){
+                    BOOST_ASSERT(this->parent->rtx);
+                    this->rtx=in_place(res->begin_nested_transaction(*this->parent->rtx));
+                }else{
+                    this->rtx=in_place(res->begin_root_transaction());
+                }
+            }
+        }
+    private:
+        friend class simple_transaction_manager;
+        optional<typename Resource::transaction> rtx;
+        transaction * const parent;
+    /// \endcond
+    };
+    typedef mpl::vector1<Resource> resource_types;
     template<class ServiceTag>
     struct default_resource{
         typedef typename Resource::tag type;
@@ -96,7 +103,7 @@
     }
 
     static typename detail::transaction_construct_t begin_transaction(){
-        return typename detail::transaction_construct_t(activetx::get());
+        return transaction_construct_t(currenttx::get());
     }
 
     static void commit_transaction(transaction &tx){
@@ -116,22 +123,41 @@
         }
     }
 
+    static void restart_transaction(transaction &tx){
+        if(res){
+            BOOST_ASSERT(tx.rtx);
+            restart_transaction(tx,typename mpl::contains<typename Resource::services,transaction_restart_service_tag>::type());
+        }
+    }
+
     static void bind_transaction(transaction &tx){
-        activetx::reset(&tx);
+        currenttx::reset(&tx);
     }
     static void unbind_transaction(){
-        activetx::reset(0);
+        currenttx::reset(0);
     }
-    static transaction &active_transaction(){
-        if(transaction *tx=activetx::get()) return *tx;
-        else throw no_active_transaction();
+    static transaction ¤t_transaction(){
+        if(transaction *tx=currenttx::get()) return *tx;
+        else throw no_transaction();
     }
-    static bool has_active_transaction(){
-        return activetx::get() ? true : false;
+    static bool has_current_transaction(){
+        return currenttx::get() ? true : false;
     }
 
     /// \cond
 private:
+    static void restart_transaction(transaction &tx,mpl::true_ service){
+        res->restart_transaction(*tx.rtx);
+    }
+    static void restart_transaction(transaction &tx,mpl::false_ service){
+        if(tx.parent){
+            BOOST_ASSERT(tx.parent->rtx);
+            tx.rtx=in_place(res->begin_nested_transaction(*tx.parent->rtx));
+        }else{
+            tx.rtx=in_place(res->begin_root_transaction());
+        }
+    }
+
     static Resource *res;
     /// \endcond
 };
Added: sandbox/transaction/libs/transact/test/transaction_stack_unwind.cpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/libs/transact/test/transaction_stack_unwind.cpp	2010-03-28 17:46:32 EDT (Sun, 28 Mar 2010)
@@ -0,0 +1,65 @@
+#include <boost/transact/simple_transaction_manager.hpp>
+#include <boost/mpl/empty_sequence.hpp>
+#include <boost/assert.hpp>
+
+using namespace boost;
+using namespace transact;
+
+struct my_rm{
+    typedef int transaction;
+    typedef mpl::empty_sequence services;
+    struct tag{};
+    transaction begin_root_transaction(){ return 0; }
+    transaction begin_nested_transaction(transaction){ return 0; }
+    void commit_transaction(transaction){}
+    bool finish_transaction(transaction){ return false; }
+    void rollback_transaction(transaction){}
+};
+
+
+typedef simple_transaction_manager<my_rm> my_tm;
+#define BOOST_TRANSACT_CONFIGURATION my_tm
+
+#include <boost/transact/language.hpp>
+
+
+int test(int contextnr){
+    my_tm::transaction *txs[5];
+    int retried=-1;
+    begin_transaction{
+        txs[0]=&my_tm::current_transaction();
+        begin_transaction{
+            txs[1]=&my_tm::current_transaction();
+            begin_transaction{
+                txs[2]=&my_tm::current_transaction();
+                begin_transaction{
+                    txs[3]=&my_tm::current_transaction();
+                    begin_transaction{
+                        txs[4]=&my_tm::current_transaction();
+                        my_rm::transaction &rtx=my_tm::resource_transaction(*txs[contextnr]);
+                        throw resource_isolation_exception<my_rm>(rtx);
+                    }retry{
+                        return 4;
+                    }end_retry;
+                }retry{
+                    return 3;
+                }end_retry;
+            }retry{
+                return 2;
+            }end_retry;
+        }retry{
+            return 1;
+        }end_retry;
+    }retry{
+        return 0;
+    }end_retry;
+}
+
+
+int main(){
+    my_rm rm;
+    my_tm::connect_resource(rm);
+    for(int c=0;c<5;++c){
+        BOOST_ASSERT( test(c) == c );
+    }
+}