$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r59230 - sandbox/transaction/dev
From: strasser_at_[hidden]
Date: 2010-01-22 14:32:32
Author: stefans
Date: 2010-01-22 14:32:31 EST (Fri, 22 Jan 2010)
New Revision: 59230
URL: http://svn.boost.org/trac/boost/changeset/59230
Log:
 - made all public members of basic_transaction_manager static
 - added connect_resource, disconnect_resource
 - moved control over "transaction stack", i.e. binding to the parent transaction on commit/rollback
   from basic_transaction_manager to basic_transaction
 - use thread_specific_ptr<transaction> with a null cleanup function instead of
   thread_specific_ptr<transaction *> with default cleanup
 - thread local storage instead of thread_specific_ptr for GCC and MSVC
Text files modified: 
   sandbox/transaction/dev/basic_transaction.hpp         |    32 +++--                                   
   sandbox/transaction/dev/basic_transaction_manager.hpp |   220 ++++++++++++++++++--------------------- 
   sandbox/transaction/dev/exception.hpp                 |    22 ++--                                    
   3 files changed, 136 insertions(+), 138 deletions(-)
Modified: sandbox/transaction/dev/basic_transaction.hpp
==============================================================================
--- sandbox/transaction/dev/basic_transaction.hpp	(original)
+++ sandbox/transaction/dev/basic_transaction.hpp	2010-01-22 14:32:31 EST (Fri, 22 Jan 2010)
@@ -28,10 +28,10 @@
         /// Throws: \c no_active_transaction_manager, \c finalize_error, \c io_failure, \c thread_resource_error
         /// \brief Constructs a basic_transaction, beginning a new transaction scope
         explicit basic_transaction()
-		: manager(TxMgr::active())
-		, tx(manager.begin_transaction())
+		: parent(TxMgr::has_active_transaction() ? &TxMgr::active_transaction() : 0)
+		, tx(TxMgr::begin_transaction())
                 , done(false){
-		this->manager.bind_transaction(this->tx);
+		TxMgr::bind_transaction(this->tx);
         }
 
         /// The transaction is rolled back if it was not yet committed.
@@ -39,9 +39,10 @@
         /// Throws: Nothing
         /// \brief Destructs the basic_transaction object
         ~basic_transaction(){
+		this->pop();
                 if(!this->done){
                         try{
-				this->manager.rollback_transaction(this->tx);
+				TxMgr::rollback_transaction(this->tx);
                         }catch(...){
 #ifndef NDEBUG
                                 std::cerr << "ignored exception" << std::endl;
@@ -57,8 +58,9 @@
         /// \c archive_exception, \c io_failure, \c thread_resource_error, any exception thrown by the following user-supplied functions: \c T::T(), \c serialize(), \c save(), \c load(), \c construct(), \c equal(), \c finalize()
         /// \brief Commits the transaction.
         void commit(){
+		this->pop();
                 this->done=true;
-		this->manager.commit_transaction(this->tx);
+		TxMgr::commit_transaction(this->tx);
         }
 
         /// If this is a nested transaction, sets the active transaction to the parent transaction.
@@ -67,28 +69,36 @@
         /// Throws: \c io_failure, \c thread_resource_error
         /// \brief Unwinds all changes made during this transaction.
         void rollback(){
+		this->pop();
                 this->done=true;
-		this->manager.rollback_transaction(this->tx);
+		TxMgr::rollback_transaction(this->tx);
         }
 
         /// Throws: Nothing
         /// \brief Binds the current thread to this transaction
         void bind(){
-		this->manager.bind_transaction(this->tx);
+		TxMgr::bind_transaction(this->tx);
         }
 
         /// Throws: Nothing
         /// \brief If the current thread is bound to this transaction, unbinds it
         void unbind(){
-		if(this->manager.has_active_transaction() &&
-			&this->manager.active_transaction() == &this->tx){
-			this->manager.unbind_transaction();
+		if(TxMgr::has_active_transaction() &&
+			&TxMgr::active_transaction() == &this->tx){
+			TxMgr::unbind_transaction();
                 }
         }
 
         /// \cond
 private:
-	TxMgr &manager;
+	void pop(){
+		if(TxMgr::has_active_transaction() && &TxMgr::active_transaction() == &this->tx){
+			if(this->parent) TxMgr::bind_transaction(*this->parent);
+			else TxMgr::unbind_transaction();
+		}
+	}
+
+	typename TxMgr::transaction *parent;
         typename TxMgr::transaction tx;
         bool done;
         /// \endcond
Modified: sandbox/transaction/dev/basic_transaction_manager.hpp
==============================================================================
--- sandbox/transaction/dev/basic_transaction_manager.hpp	(original)
+++ sandbox/transaction/dev/basic_transaction_manager.hpp	2010-01-22 14:32:31 EST (Fri, 22 Jan 2010)
@@ -15,7 +15,7 @@
 #include <boost/persistent/detail/utility.hpp>
 #include <boost/persistent/detail/null_mutex.hpp>
 #include <boost/persistent/detail/mutex.hpp>
-#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/add_pointer.hpp>
 #include <boost/fusion/include/mpl.hpp>
 #include <boost/fusion/include/as_vector.hpp>
 #include <boost/fusion/include/count_if.hpp>
@@ -71,8 +71,8 @@
 				>::type
 			>::type::tag type;
                 };
-		typedef typename mpl::transform<resource_types,add_reference<mpl::_1> >::type resource_references;
-		typedef typename fusion::result_of::as_vector<resource_references>::type resources_tuple;
+		typedef typename mpl::transform<resource_types,add_pointer<mpl::_1> >::type resource_pointers;
+		typedef typename fusion::result_of::as_vector<resource_pointers>::type resources_tuple;
 
                 class transaction;
                 class transaction_construct_t{
@@ -105,6 +105,7 @@
                         mutex_type mutex;
                 };
         };
+	basic_transaction_manager();
         /// \endcond
 public:
         typedef typename detail::transaction transaction;
@@ -114,37 +115,34 @@
                 typedef typename detail::template default_resource<ServiceTag>::type type;
         };
 
-	/// This constructor is only available if this transaction manager uses only one
-	/// resource manager.
-	/// 
-	/// Throws: Nothing
-	/// \brief Constructs a basic_transaction_manager using the passed resource manager
-	/// \param resource The resource manager
-	explicit basic_transaction_manager(typename mpl::front<resource_types>::type &resource)
-		: resources(ref(resource))
-		, activetx(){
-		BOOST_STATIC_ASSERT(mpl::size<resource_types>::value==1);
-		this->bind();
-	}
-
-	/// Throws: Nothing
-	/// \brief Constructs a basic_transaction_manager using the passed resource managers
-	/// \param resources A Boost.Fusion Sequence of non-const references to the resource
-	///                  managers. For example, fusion::vector<res1_type &,res2_type &>
-	explicit basic_transaction_manager(typename detail::resources_tuple const &resources)
-		: resources(resources)
-		, activetx(){
-		this->bind();
+	/// TODO doc, not part of the concept
+	template<class Resource>
+	static void connect_resource(Resource &newres){
+		typedef typename Resource::tag tag;
+		typedef typename persistent::detail::index_by_tag<resource_types,tag>::type index;
+		Resource *&res=fusion::at<index>(resources);
+		if(res) persistent::detail::throw_(resource_error());
+		res=&newres;
+	}
+
+	/// TODO doc, not part of the concept
+	template<class ResourceTag>
+	static void disconnect_resource(ResourceTag tag=ResourceTag()){
+		typedef typename persistent::detail::index_by_tag<resource_types,ResourceTag>::type index;
+		fusion::at<index>(resources)=0;		
         }
 
         template<class Tag>
-	typename persistent::detail::type_by_tag<resource_types,Tag>::type &resource(Tag tag=Tag()){
+	static typename persistent::detail::type_by_tag<resource_types,Tag>::type &resource(Tag tag=Tag()){
+		typedef typename persistent::detail::type_by_tag<resource_types,Tag>::type resource_type;
                 typedef typename persistent::detail::index_by_tag<resource_types,Tag>::type index;
-		return fusion::at<index>(this->resources);
+		resource_type *res=fusion::at<index>(resources);
+		if(res) return *res;
+		else persistent::detail::throw_(resource_error());
         }
 
         template<class Tag>
-	typename persistent::detail::type_by_tag<resource_types,Tag>::type::transaction &
+	static typename persistent::detail::type_by_tag<resource_types,Tag>::type::transaction &
         resource_transaction(transaction &tx,Tag tag=Tag()){
                 typedef typename persistent::detail::type_by_tag<resource_types,Tag>::type resource_type;
                 typedef typename persistent::detail::index_by_tag<resource_types,Tag>::type index;
@@ -157,93 +155,66 @@
                 //manager is the only one, or according to user configuration.
                 lock_guard<typename transaction::mutex_type> l(tx.mutex);
                 if(!rtx){
-			resource_type &resource=fusion::at<index>(this->resources);
+			resource_type &res=resource(tag);
                         if(tx.parent){
                                 //TODO optimization: if 10 nested transactions were created in one resource manager,
                                 //and then a second resource manager is called for the first time in the innermost
                                 //transaction, 10 nested transactions are created in the second resource manager,
                                 //even though it would be enough to create one transaction
                                 //that gets committed only when the outermost global transaction is committed.
+				//(or is moved to the parent on commit instead of performing an actual commit?)
 
-				typename resource_type::transaction &parentrtx=this->resource_transaction<Tag>(*tx.parent);
-				rtx=in_place(resource.begin_nested_transaction(parentrtx));
+				typename resource_type::transaction &parentrtx=resource_transaction<Tag>(*tx.parent);
+				rtx=in_place(res.begin_nested_transaction(parentrtx));
                         }else{
-				rtx=in_place(resource.begin_root_transaction());
+				rtx=in_place(res.begin_root_transaction());
                         }
                 }
                 return *rtx;
         }
 
-	typename detail::transaction_construct_t begin_transaction(){
-		if(this->has_active_transaction()) return typename detail::transaction_construct_t(&this->active_transaction());
-		else return typename detail::transaction_construct_t(0);
-	}
-
-	void commit_transaction(transaction &tx){
-		this->bind_transaction(tx);
-
-		try{
-			std::size_t nr=fusion::count_if(tx.resource_transactions,is());
-			if(nr > 0){
-				if(nr == 1){
-					//FIXME the local transaction commit might access other resource managers
-					//(e.g. for reference counting). that can start another resource transaction
-					//and a two-phase-commit must take place.
-					//finish-phase must be introduced to make sure the commit itself doesn't
-					//access other resource managers
-					this->for_each_transaction(tx,committer());
-				}else{
-					persistent::detail::throw_(unsupported_exception()); //TODO distributed transaction
-				}
-			}
-		}catch(...){ //commit_transaction is called exactly once, even if something goes wrong. unbind transaction:
-			if(tx.parent) this->bind_transaction(*tx.parent);
-			else this->unbind_transaction();
-			throw;
-		}
-		if(tx.parent) this->bind_transaction(*tx.parent);
-		else this->unbind_transaction();
+	static typename detail::transaction_construct_t begin_transaction(){
+		return typename detail::transaction_construct_t(active_transaction(mpl::bool_<Threads>()));
         }
 
-	void rollback_transaction(transaction &tx){
-		this->bind_transaction(tx);
+	static void commit_transaction(transaction &tx){
+		bind_transaction(tx);
 
-		try{ this->for_each_transaction(tx,rollbacker()); }
-		catch(...){
-			if(tx.parent) this->bind_transaction(*tx.parent);
-			else this->unbind_transaction();
-			throw;
+		std::size_t nr=fusion::count_if(tx.resource_transactions,is());
+		if(nr > 0){
+			if(nr == 1){
+				//FIXME the local transaction commit might access other resource managers
+				//(e.g. for reference counting). that can start another resource transaction
+				//and a two-phase-commit must take place.
+				//finish-phase must be introduced to make sure the commit itself doesn't
+				//access other resource managers
+				for_each_transaction(tx,committer());
+			}else{
+				persistent::detail::throw_(unsupported_exception()); //TODO distributed transaction
+			}
                 }
-
-		if(tx.parent) this->bind_transaction(*tx.parent);
-		else this->unbind_transaction();
         }
 
-	void bind_transaction(transaction &tx){
-		this->active_transaction(&tx,mpl::bool_<Threads>());
-	}
-	void unbind_transaction(){
-		this->active_transaction(0,mpl::bool_<Threads>());
+	static void rollback_transaction(transaction &tx){
+		bind_transaction(tx);
+
+		for_each_transaction(tx,rollbacker());
         }
 
-	transaction &active_transaction() const{
-		if(transaction *tx=this->active_transaction(mpl::bool_<Threads>())) return *tx;
-		else persistent::detail::throw_(no_active_transaction());
+	static void bind_transaction(transaction &tx){
+		active_transaction(&tx,mpl::bool_<Threads>());
         }
-	bool has_active_transaction() const{
-		return this->active_transaction(mpl::bool_<Threads>()) ? true : false;
+	static void unbind_transaction(){
+		active_transaction(0,mpl::bool_<Threads>());
         }
 
-	static bool has_active(){
-		return active_;
+	static transaction &active_transaction(){
+		if(transaction *tx=active_transaction(mpl::bool_<Threads>())) return *tx;
+		else persistent::detail::throw_(no_active_transaction());
         }
-
-	static basic_transaction_manager &active(){
-		if(active_) return *active_;
-		else persistent::detail::throw_(no_active_transaction_manager());
+	static bool has_active_transaction(){
+		return active_transaction(mpl::bool_<Threads>()) ? true : false;
         }
-	void bind(){ active_=this; }
-	static void unbind(){ active_=0; }
 
         /// \cond
 private:
@@ -266,53 +237,70 @@
         };
         template<class F>
         struct for_each_helper{
-		explicit for_each_helper(basic_transaction_manager *this_,transaction &tx,F const &f) : this_(this_),tx(tx),f(f){}
+		explicit for_each_helper(transaction &tx,F const &f) : tx(tx),f(f){}
                 template<class U>
                 void operator()(U) const{
                         typedef typename mpl::at<resource_types,U>::type resource_type;
                         optional<typename resource_type::transaction> &rtx=fusion::at<U>(tx.resource_transactions);
                         if(rtx){
-				resource_type &rmgr=fusion::at<U>(this_->resources);
-				f(rmgr,*rtx);
+				resource_type *rmgr=fusion::at<U>(resources);
+				BOOST_ASSERT(rmgr);
+				f(*rmgr,*rtx);
                         }
                 }
         private:
-		basic_transaction_manager *this_;
                 transaction &tx;
                 F f;
         };
         template<class F>
-	void for_each_transaction(transaction &tx,F const &f){
+	static void for_each_transaction(transaction &tx,F const &f){
                 static unsigned int const size=mpl::size<resource_types>::type::value;
                 typedef mpl::range_c<unsigned int,0,size> range;
-		mpl::for_each<range>(for_each_helper<F>(this,tx,f));
-	}
-	void active_transaction(transaction *newtx,mpl::true_){
-		if(transaction **tx=this->activetx.get()) *tx=newtx;
-		else this->activetx.reset(new transaction *(newtx));
-	}
-	void active_transaction(transaction *newtx,mpl::false_){
-		this->activetx=newtx;
-	}
-	transaction *active_transaction(mpl::true_) const{
-		if(transaction **tx=this->activetx.get()){
-			if(*tx) return *tx;
-		}
-		return 0;	
-	}
-	transaction *active_transaction(mpl::false_) const{
-		return this->activetx;
+		mpl::for_each<range>(for_each_helper<F>(tx,f));
         }
+#if defined(__GNUG__) || defined(BOOST_MSVC)
+	template<class T>
+	static void active_transaction(transaction *newtx,T){ activetx=newtx; }
+	template<class T>
+	static transaction *active_transaction(T){ return activetx; }
+	typedef transaction *activetx_type;
+	#ifdef BOOST_MSVC
+		static __declspec(thread) transaction *activetx; //TODO MSVC untested
+	#else
+		static __thread transaction *activetx;
+	#endif
+#else
+	static void active_transaction(transaction *newtx,mpl::true_){ activetx.reset(newtx); }
+	static void active_transaction(transaction *newtx,mpl::false_){ activetx=newtx; }
+	static transaction *active_transaction(mpl::true_){ return activetx.get(); }
+	static transaction *active_transaction(mpl::false_){ return activetx; }
+	typedef typename mpl::if_c<
+		Threads,
+		thread_specific_ptr<transaction>,
+		transaction *>::type activetx_type;	
+	activetx_type activetx;
+#endif
 
-	typename detail::resources_tuple const resources;
-	//TODO optimization: use thread local variable instead of thread_specific_ptr
-	typename mpl::if_c<Threads,thread_specific_ptr<transaction *>,transaction *>::type activetx;
-	static basic_transaction_manager *active_; 
+
+	typedef typename detail::resources_tuple resources_type;
+	static resources_type resources;
         /// \endcond
 };
 
-template<class Resources,bool Threads,bool TThreads>
-basic_transaction_manager<Resources,Threads,TThreads> *basic_transaction_manager<Resources,Threads,TThreads>::active_=0;
+template<class Res,bool Thr,bool TThr>
+typename basic_transaction_manager<Res,Thr,TThr>::resources_type
+basic_transaction_manager<Res,Thr,TThr>::resources;
+
+template<class Res,bool Thr,bool TThr>
+#if defined(__GNUG__)
+__thread
+#elif defined(BOOST_MSVC)
+__declspec(thread)
+#endif
+typename basic_transaction_manager<Res,Thr,TThr>::activetx_type
+basic_transaction_manager<Res,Thr,TThr>::activetx(0); //the 0-argument either initializes
+//the pointer to 0, or passes a 0 cleanup function to the thread_specific_ptr constructor.
+
 
 }
 }
Modified: sandbox/transaction/dev/exception.hpp
==============================================================================
--- sandbox/transaction/dev/exception.hpp	(original)
+++ sandbox/transaction/dev/exception.hpp	2010-01-22 14:32:31 EST (Fri, 22 Jan 2010)
@@ -43,8 +43,8 @@
 ///Indicates that the operation required an active transaction but there was no active transaction set for this thread.
 struct no_active_transaction : persistent::exception{};
 
-///Indicates that the operation required an active transaction manager but there is none set.
-struct no_active_transaction_manager : persistent::exception{};
+///TODO doc
+struct resource_error : persistent::exception{};
 
 ///Indicates that the operation is not supported by this implementation
 struct unsupported_exception : persistent::exception{};
@@ -58,20 +58,20 @@
 
 template<class TxMgr,class Iterator>
 struct isolation_unwind_visitor{
-	void operator()(TxMgr &txmgr,isolation_exception const &iso){
+	void operator()(isolation_exception const &iso){
                 typedef typename mpl::deref<Iterator>::type resource_type;
                 if(visolation_exception<resource_type> const *viso=dynamic_cast<visolation_exception<resource_type> const *>(&iso)){
-			viso->unwind(txmgr);
+			viso->template unwind<TxMgr>();
                 }else{
                         isolation_unwind_visitor<TxMgr,typename mpl::next<Iterator>::type> visit;
-			visit(txmgr,iso);
+			visit(iso);
                 }
         }
 };
 
 template<class TxMgr>
 struct isolation_unwind_visitor<TxMgr,typename mpl::end<typename TxMgr::resource_types>::type>{
-	void operator()(TxMgr &,isolation_exception const &){
+	void operator()(isolation_exception const &){
                 BOOST_ASSERT(false);
         }
 };
@@ -82,9 +82,9 @@
 struct isolation_exception : persistent::exception{
         ///Rethrows the exception if the active transaction is a nested transaction but the isolation exception was caused by a parent transaction of it.
         template<class TxMgr>
-	void unwind(TxMgr &txmgr=TxMgr::active()) const{ //pseudo-virtual
+	void unwind() const{ //pseudo-virtual
                 detail::isolation_unwind_visitor<TxMgr,typename mpl::begin<typename TxMgr::resource_types>::type> visit;
-		visit(txmgr,*this);
+		visit(*this);
         }
 };
 
@@ -95,11 +95,11 @@
 struct visolation_exception : isolation_exception{
         visolation_exception(typename ResMgr::transaction *unwind_to) : to(unwind_to){}
         template<class TxMgr>
-	void unwind(TxMgr &txmgr) const{ //pseudo-virtual
+	void unwind() const{ //pseudo-virtual
                 if(this->to){
-			typename ResMgr::transaction &tx=txmgr.template resource_transaction<typename ResMgr::tag>(txmgr.active_transaction());
+			typename ResMgr::transaction &tx=TxMgr::template resource_transaction<typename ResMgr::tag>(TxMgr::active_transaction());
                         if(&tx != this->to) throw;
-		}else if(txmgr.has_active_transaction()) throw;
+		}else if(TxMgr::has_active_transaction()) throw;
         }
 private:
         typename ResMgr::transaction *to;