Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r62338 - in sandbox/transaction: boost/transact boost/transact/detail libs/transact/test
From: strasser_at_[hidden]
Date: 2010-05-30 20:44:24


Author: stefans
Date: 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
New Revision: 62338
URL: http://svn.boost.org/trac/boost/changeset/62338

Log:
 - DistributedTransactionService
 - simple_TM changes from changeset 61877 applied to basic_TM:
   NestedTransactionService, flat nested transactions, support for stateful tags
 - isolation_exception: support for flat nested transactions
 - removed combined_mutex: violated boost::mutex::unlock() precondition
 - test/transaction_stack_unwind.cpp: adjusted to interface changes
 - object_access: too much to list
Added:
   sandbox/transaction/boost/transact/archive.hpp (contents, props changed)
   sandbox/transaction/boost/transact/detail/algorithm.hpp (contents, props changed)
   sandbox/transaction/boost/transact/detail/config.hpp (contents, props changed)
   sandbox/transaction/boost/transact/detail/transaction_manager.hpp (contents, props changed)
Text files modified:
   sandbox/transaction/boost/transact/basic_transaction.hpp | 3
   sandbox/transaction/boost/transact/basic_transaction_manager.hpp | 877 +++++++++++++++++++++++----------------
   sandbox/transaction/boost/transact/detail/buffering_file.hpp | 1
   sandbox/transaction/boost/transact/detail/file.hpp | 5
   sandbox/transaction/boost/transact/detail/filebuf_file.hpp | 1
   sandbox/transaction/boost/transact/detail/mutex.hpp | 69 ---
   sandbox/transaction/boost/transact/detail/sectorizing_file.hpp | 1
   sandbox/transaction/boost/transact/detail/static_tss.hpp | 2
   sandbox/transaction/boost/transact/detail/syncing_file.hpp | 42 +
   sandbox/transaction/boost/transact/exception.hpp | 101 ++--
   sandbox/transaction/boost/transact/object_access.hpp | 451 ++------------------
   sandbox/transaction/boost/transact/resource_manager.hpp | 5
   sandbox/transaction/boost/transact/simple_transaction_manager.hpp | 276 ++++++-----
   sandbox/transaction/libs/transact/test/transaction_stack_unwind.cpp | 20
   14 files changed, 825 insertions(+), 1029 deletions(-)

Added: sandbox/transaction/boost/transact/archive.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/archive.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -0,0 +1,421 @@
+// 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_ARCHIVE_HPP
+#define BOOST_TRANSACT_ARCHIVE_HPP
+
+#include <boost/optional/optional.hpp>
+#include <boost/utility/in_place_factory.hpp>
+#include <boost/ref.hpp>
+#include <boost/assert.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
+#include <boost/serialization/wrapper.hpp>
+#include <boost/archive/archive_exception.hpp>
+#include <boost/transact/array_extension.hpp>
+#include <iterator>
+#include <algorithm>
+#include <cstring>
+#include <typeinfo>
+
+#ifndef NO_BOOST_SERIALIZATION
+
+#include <boost/archive/basic_binary_iarchive.hpp>
+#include <boost/archive/basic_binary_oarchive.hpp>
+#include <boost/archive/impl/basic_binary_iarchive.ipp>
+#include <boost/archive/impl/basic_binary_oarchive.ipp>
+#include <string>
+
+#endif
+
+
+
+namespace boost{
+namespace transact{
+
+namespace detail{
+
+#ifndef NO_BOOST_SERIALIZATION
+
+template<class Base>
+class serialization_oarchive : public archive::basic_binary_oarchive<serialization_oarchive<Base> >{
+ typedef archive::basic_binary_oarchive<serialization_oarchive<Base> > base_type;
+public:
+ explicit serialization_oarchive(Base &ar)
+ : base_type(archive::no_header | archive::no_codecvt)
+ , base(ar){}
+
+ void save_binary(void const *data,std::size_t size){
+ this->base.save_binary(data,size);
+ }
+ template<class T>
+ void save_override(T const &t,int){
+ this->base << t;
+ }
+ using base_type::save_override; //for serialization primitives -> binary conversion
+
+ template<class T>
+ void save(T const &t){
+ this->base << t; //boost.serialization can save serialization primitives bypassing override, e.g. class names
+ }
+private:
+ Base &base;
+};
+
+template<class Base>
+class serialization_iarchive : public archive::basic_binary_iarchive<serialization_iarchive<Base> >{
+ typedef archive::basic_binary_iarchive<serialization_iarchive<Base> > base_type;
+public:
+ explicit serialization_iarchive(Base &ar)
+ : base_type(archive::no_header | archive::no_codecvt)
+ , base(ar){}
+
+ void load_binary(void *data,std::size_t size){
+ this->base.load_binary(data,size);
+ }
+ template<class T>
+ void load_override(T &t,int){
+ this->load(t);
+ }
+ using base_type::load_override;
+
+ template<class T>
+ void load(T &t){
+ this->load(t,typename serialization::is_wrapper<T>::type());
+ }
+private:
+ template<class T>
+ void load(T const &t,mpl::true_ wrapper){
+ this->base >> const_cast<T &>(t);
+ }
+ template<class T>
+ void load(T &t,mpl::false_ wrapper){
+ this->base >> t;
+ }
+
+ Base &base;
+};
+
+#endif
+
+}
+
+
+template<class Derived>
+class basic_oarchive{
+public:
+ typedef mpl::true_ is_saving;
+ typedef mpl::false_ is_loading;
+ template<class T>
+ basic_oarchive &operator&(T const &t){
+ return that().operator<<(t);
+ }
+ template<class T>
+ basic_oarchive &operator<<(T const &t){
+ that().save(t);
+ return *this;
+ }
+ template<class T>
+ void save(T const &t);
+ void save(std::string const &s){
+ std::size_t const size=s.size();
+ that() << size;
+ if(size > 0) that().save_binary(s.data(),size);
+ }
+ void save(std::wstring const &s){
+ std::size_t const size=s.size();
+ that() << size;
+ if(size > 0) that().save_binary(s.data(),size * sizeof(wchar_t));
+ }
+ void save(char const *s){
+ std::size_t const size=std::strlen(s);
+ that() << size;
+ if(size > 0) that().save_binary(s,size);
+ }
+ void save(wchar_t const *s){
+ std::size_t const size=std::wcslen(s);
+ that() << size;
+ if(size > 0) that().save_binary(s,size*sizeof(wchar_t));
+ }
+private:
+ Derived &that(){
+ return static_cast<Derived &>(*this);
+ }
+#ifndef NO_BOOST_SERIALIZATION
+public:
+ detail::serialization_oarchive<Derived> &serialization_archive(){
+ if(!this->sarchive){
+ this->sarchive=in_place(boost::ref(that()));
+ }
+ return *this->sarchive;
+ }
+private:
+ optional<detail::serialization_oarchive<Derived> > sarchive;
+#endif
+};
+
+template<class Derived>
+class basic_iarchive{
+public:
+ typedef mpl::false_ is_saving;
+ typedef mpl::true_ is_loading;
+ template<class T>
+ basic_iarchive &operator&(T &t){
+ return that().operator>>(t);
+ }
+ template<class T>
+ basic_iarchive &operator>>(T &t){
+ that().load(t);
+ return *this;
+ }
+ template<class T>
+ void load(T &t);
+ void load(std::string &s){
+ std::size_t size;
+ that() >> size;
+ s.resize(size);
+ that().load_binary(&*s.begin(),size); //boost.serialization does the same thing
+ }
+ void load(std::wstring &s,mpl::false_,mpl::false_ bitwise){
+ std::size_t size;
+ that() >> size;
+ s.resize(size);
+ if(size > 0) that().load_binary(const_cast<wchar_t *>(s.data()),size*sizeof(wchar_t)); //boost.serialization does the same thing
+ }
+ void load(char *s,mpl::false_,mpl::false_ bitwise){
+ std::size_t size;
+ that() >> size;
+ if(size > 0) that().load_binary(s,size);
+ s[size]=0;
+ }
+ void load(wchar_t *s,mpl::false_,mpl::false_ bitwise){
+ std::size_t size;
+ that() >> size;
+ if(size > 0) that().load_binary(s,size*sizeof(wchar_t));
+ s[size]=0;
+ }
+private:
+ Derived &that(){
+ return static_cast<Derived &>(*this);
+ }
+#ifndef NO_BOOST_SERIALIZATION
+public:
+ detail::serialization_iarchive<Derived> &serialization_archive(){
+ if(!this->sarchive){
+ this->sarchive=in_place(boost::ref(that()));
+ }
+ return *this->sarchive;
+ }
+private:
+ optional<detail::serialization_iarchive<Derived> > sarchive;
+#endif
+};
+
+template<class Derived,class OutputIterator>
+class basic_char_oarchive : public basic_oarchive<Derived>{
+public:
+ explicit basic_char_oarchive(OutputIterator const &out) : out(out){}
+ template<class Size>
+ void save_binary(void const *vdata,Size size){
+ this->save_binary(static_cast<char const *>(vdata),size,typename array_extension<OutputIterator>::type());
+ }
+private:
+ template<class Size>
+ void save_binary(char const *data,Size size,mpl::true_){
+ this->out.assign(data,size);
+ }
+ template<class Size>
+ void save_binary(char const *data,Size size,mpl::false_){
+ std::copy(data,data+size,this->out);
+ }
+
+ OutputIterator out;
+};
+
+template<class Derived,class InputIterator>
+class basic_char_iarchive : public basic_iarchive<Derived>{
+public:
+ basic_char_iarchive(InputIterator const &begin,InputIterator const &end)
+ : in(begin), end(end){
+ BOOST_ASSERT(end - begin >= 0);
+ }
+ template<class Size>
+ void load_binary(void *vdata,Size size){
+ char *data=static_cast<char *>(vdata);
+ this->load_binary(
+ data,
+ size,
+ typename std::iterator_traits<InputIterator>::iterator_category(),
+ typename continuous_values<InputIterator>::type()
+ );
+ }
+private:
+ template<class Size>
+ void load_binary(char *data,Size size,std::random_access_iterator_tag,mpl::true_ contvals){
+ if(std::size_t(this->end - this->in) < size) throw archive::archive_exception(archive::archive_exception::stream_error);
+ std::memcpy(data,&*this->in,size);
+ this->in+=size;
+ }
+ template<class Size>
+ void load_binary(char *data,Size size,std::random_access_iterator_tag,mpl::false_ contvals){
+ if(std::size_t(this->end - this->in) < size) throw archive::archive_exception(archive::archive_exception::stream_error);
+ std::copy(data,data+size,this->in);
+ }
+ template<class Size,class Category>
+ void load_binary(char *data,Size size,Category,mpl::false_ contvals){
+ for(std::size_t c=0;c<size;++c){
+ if(this->in == this->end) throw archive::archive_exception(archive::archive_exception::stream_error);
+ *data++=*this->in++;
+ }
+ }
+
+ InputIterator in;
+ InputIterator end;
+};
+
+
+template<class OutputIterator>
+class char_oarchive : public basic_char_oarchive<char_oarchive<OutputIterator>,OutputIterator>{
+ typedef basic_char_oarchive<char_oarchive,OutputIterator> base_type;
+public:
+ explicit char_oarchive(OutputIterator const &out) : base_type(out){}
+};
+
+template<class InputIterator>
+class char_iarchive : public basic_char_iarchive<char_iarchive<InputIterator>,InputIterator>{
+ typedef basic_char_iarchive<char_iarchive<InputIterator>,InputIterator> base_type;
+public:
+ char_iarchive(InputIterator const &begin,InputIterator const &end) : base_type(begin,end){}
+};
+
+namespace detail{
+
+template<class OutputIterator>
+class memory_oarchive : public basic_char_oarchive<memory_oarchive<OutputIterator>,OutputIterator>{
+ typedef basic_char_oarchive<memory_oarchive<OutputIterator>,OutputIterator> base_type;
+public:
+ explicit memory_oarchive(OutputIterator const &out) : base_type(out){}
+ void save(std::type_info const *type){
+ this->save(reinterpret_cast<std::size_t>(type));
+ }
+ using base_type::save;
+};
+
+template<class InputIterator>
+class memory_iarchive : public basic_char_iarchive<memory_iarchive<InputIterator>,InputIterator>{
+ typedef basic_char_iarchive<memory_iarchive<InputIterator>,InputIterator> base_type;
+public:
+ memory_iarchive(InputIterator const &begin,InputIterator const &end) : base_type(begin,end){}
+ void load(std::type_info const *&type){
+ this->load(reinterpret_cast<std::size_t &>(type));
+ }
+ using base_type::load;
+};
+
+template<class InputIterator>
+class compare_archive : public basic_oarchive<compare_archive<InputIterator> >{
+ typedef basic_oarchive<compare_archive<InputIterator> > base_type;
+public:
+ compare_archive(InputIterator const &begin,InputIterator const &end)
+ : in(begin),end(end)
+ , equal_(true){
+ BOOST_ASSERT(end - begin >= 0);
+ }
+ template<class Size>
+ void save_binary(void const *vdata,Size size){
+ char const *data=static_cast<char const *>(vdata);
+ this->save_binary(
+ data,
+ size,
+ typename std::iterator_traits<InputIterator>::iterator_category(),
+ typename continuous_values<InputIterator>::type()
+ );
+ }
+ void save(std::type_info const *type){
+ this->save(reinterpret_cast<std::size_t>(type));
+ }
+ template<class T>
+ void save(T const &t){
+ if(this->equal_){ //not equal()!
+ base_type::save(t);
+ }
+ }
+ bool equal() const{ return this->equal_ && this->in == this->end; }
+private:
+ template<class Size>
+ void save_binary(char const *data,Size size,std::random_access_iterator_tag,mpl::true_ contvals){
+ if((std::size_t(this->end - this->in) < size) || (std::memcmp(data,&*this->in,size) != 0)) this->equal_=false;
+ else this->in+=size;
+ }
+ template<class Size>
+ void save_binary(char const *data,Size size,std::random_access_iterator_tag,mpl::false_ contvals){
+ if((std::size_t(this->end - this->in) < size) || (!std::equal(data,data+size,this->in))) this->equal_=false;
+ else this->in+=size;
+ }
+ template<class Size,class Category>
+ void save_binary(char const *data,Size size,Category,mpl::false_ contvals){
+ for(std::size_t c=0;c<size;++c){
+ if((this->in == this->end) || (*data++ != *this->in++)){
+ this->equal_=false;
+ break;
+ }
+ }
+ }
+
+ InputIterator in;
+ InputIterator end;
+ bool equal_;
+};
+
+template<class UnaryFunction>
+class apply_archive : public basic_oarchive<apply_archive<UnaryFunction> >{
+ typedef basic_oarchive<apply_archive<UnaryFunction> > base_type;
+public:
+ explicit apply_archive(UnaryFunction const &f) : f(f){}
+ void save_binary(void const *,std::size_t){}
+ template<class T>
+ void save(T const &t);
+ using base_type::save;
+
+ template<class T>
+ void operator()(T const &t) const{
+ this->f(t);
+ }
+private:
+ UnaryFunction f;
+};
+
+
+}
+
+
+
+}
+}
+
+#include <boost/transact/object_access.hpp>
+
+template<class Derived>
+template<class T>
+void boost::transact::basic_oarchive<Derived>::save(T const &t){
+ object_access::save(that(),t);
+}
+
+template<class Derived>
+template<class T>
+void boost::transact::basic_iarchive<Derived>::load(T &t){
+ object_access::load(that(),t);
+}
+
+template<class UnaryFunction>
+template<class T>
+void boost::transact::detail::apply_archive<UnaryFunction>::save(T const &t){
+ this->f(t);
+ object_access::apply(*this,t);
+}
+
+
+#endif
\ No newline at end of file

Modified: sandbox/transaction/boost/transact/basic_transaction.hpp
==============================================================================
--- sandbox/transaction/boost/transact/basic_transaction.hpp (original)
+++ sandbox/transaction/boost/transact/basic_transaction.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -42,7 +42,7 @@
     /// The transaction is rolled back if it is still active. Exceptions
     /// caused by rolling back the transaction are ignored.
     ///
- /// Throws: Nothing
+ /// Throws: thread_resource_error
     /// \brief Destructs the basic_transaction object
     ~basic_transaction(){
         if(!this->done){
@@ -84,6 +84,7 @@
     /// resource-specific exceptions thrown by resource managers restarting transactions.
     /// \brief Restarts the transactions
     void restart(){
+ if(!this->done) this->rollback();
         TxMgr::restart_transaction(this->tx);
         this->done=false;
     }

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-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -8,170 +8,562 @@
 #define BOOST_TRANSACT_BASIC_TRANSACTION_MANAGER_HEADER_HPP
 
 #include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
 #include <boost/utility/in_place_factory.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/optional/optional.hpp>
-#include <boost/mpl/transform.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/mpl/at.hpp>
 #include <boost/mpl/map.hpp>
-#include <boost/mpl/for_each.hpp>
 #include <boost/mpl/empty_sequence.hpp>
 #include <boost/mpl/bool.hpp>
-#include <boost/mpl/deref.hpp>
-#include <boost/mpl/find_if.hpp>
-#include <boost/mpl/contains.hpp>
+#include <boost/mpl/fold.hpp>
 #include <boost/mpl/insert.hpp>
 #include <boost/mpl/empty.hpp>
+#include <boost/mpl/set.hpp>
+#include <boost/mpl/has_key.hpp>
 #include <boost/fusion/adapted/mpl.hpp>
-#include <boost/fusion/sequence/intrinsic/at.hpp>
 #include <boost/fusion/sequence/intrinsic/at_key.hpp>
 #include <boost/fusion/support/pair.hpp>
 #include <boost/fusion/container/map/convert.hpp>
+#include <boost/iterator/transform_iterator.hpp>
 #include <boost/transact/detail/mutex.hpp>
 #include <boost/transact/exception.hpp>
 #include <boost/transact/detail/static_tss.hpp>
+#include <boost/transact/detail/algorithm.hpp>
+#include <boost/transact/detail/transaction_manager.hpp>
 #include <boost/transact/resource_manager.hpp>
-
-//TODO: TransactionManager::resources, nested transaction emulation, stateful tags
+#include <boost/unordered_map.hpp>
+#include <boost/scoped_array.hpp>
+#include <functional>
 
 namespace boost{
 namespace transact{
 
+template<
+ class Resources,
+ bool FlatNested=false,
+ class Lazy=mpl::empty_sequence,
+ bool Threads=true,
+ bool TThreads=true
+> class basic_transaction_manager;
+
+
 namespace detail{
 
-template<class Resource>
-struct get_tag{
- typedef typename Resource::tag type;
+namespace basic_transaction_manager{
+
+template<class Tag,class Resource>
+class tag_resource_map : noncopyable{
+private:
+ typedef unordered_map<Tag,std::pair<Resource *,std::size_t> > map_type;
+ struct transformer : std::unary_function<typename map_type::value_type const,std::pair<Tag,Resource *> >{
+ std::pair<Tag,Resource *> operator()(typename map_type::value_type const &in) const{
+ return std::pair<Tag,Resource *>(in.first,in.second.first);
+ }
+ };
+public:
+ typedef transform_iterator<transformer,typename map_type::const_iterator> iterator;
+ void connect(Tag const &tag,Resource &res){
+ if(!this->map.insert(std::make_pair(tag,std::make_pair(&res,0))).second) throw resource_error();
+ this->reindex();
+ }
+ void disconnect(Tag const &tag){
+ if(this->map.erase(tag) != 1) throw resource_error();
+ this->reindex();
+ }
+ Resource &get(Tag const &tag) const{
+ typename map_type::const_iterator it=this->map.find(tag);
+ if(it == this->map.end()) throw resource_error();
+ BOOST_ASSERT(it->second.first);
+ return *it->second.first;
+ }
+ Resource &get(Tag const &tag,std::size_t &index) const{
+ typename map_type::const_iterator it=this->map.find(tag);
+ if(it == this->map.end()) throw resource_error();
+ BOOST_ASSERT(it->second.first);
+ index=it->second.second;
+ return *it->second.first;
+ }
+ std::pair<iterator,iterator> range() const{
+ return std::pair<iterator,iterator>(iterator(this->map.begin(),transformer()),iterator(this->map.end(),transformer()));
+ }
+ std::size_t size() const{
+ return this->map.size();
+ }
+ bool empty() const{
+ return this->map.empty();
+ }
+private:
+ void reindex(){
+ //unordered containers have ForwardIterators, this implies that there is a defined order as long as the container isn`t modified:
+ std::size_t index=0;
+ for(typename map_type::iterator it=this->map.begin();it != this->map.end();++it){
+ it->second.second=index++;
+ }
+ }
+
+ map_type map;
+};
+
+
+template<class Resources>
+class resources : noncopyable{
+private:
+ template<class Pair>
+ struct make_tag_resource_pair{
+ typedef fusion::pair<
+ typename Pair::first,
+ tag_resource_pair<typename Pair::first,typename Pair::second>
+ > type;
+ };
+ template<class Pair>
+ struct make_tag_resource_map{
+ typedef fusion::pair<
+ typename Pair::first,
+ tag_resource_map<typename Pair::first,typename Pair::second>
+ > type;
+ };
+ template<class Pair>
+ struct tag_is_empty{
+ typedef is_empty<typename Pair::first> type;
+ };
+ typedef typename fusion::result_of::as_map<
+ typename mpl::fold<
+ Resources,
+ mpl::vector0<>,
+ mpl::push_back<
+ mpl::_1,
+ mpl::if_<
+ tag_is_empty<mpl::_2>,
+ make_tag_resource_pair<mpl::_2>,
+ make_tag_resource_map<mpl::_2>
+ >
+ >
+ >::type
+ >::type type_map_type;
+ template<class Tag,class Resource>
+ struct resource_type{
+ typedef typename mpl::if_<
+ is_empty<Tag>,
+ tag_resource_pair<Tag,Resource>,
+ tag_resource_map<Tag,Resource>
+ >::type type;
+ };
+public:
+ template<class Tag>
+ typename mpl::at<Resources,Tag>::type &get(Tag const &tag){
+ return fusion::at_key<Tag>(this->type_map).get(tag);
+ }
+ template<class Tag>
+ typename mpl::at<Resources,Tag>::type &get(Tag const &tag,std::size_t &index){
+ return fusion::at_key<Tag>(this->type_map).get(tag,index);
+ }
+ template<class Tag>
+ void connect(Tag const &tag,typename mpl::at<Resources,Tag>::type &res){
+ fusion::at_key<Tag>(this->type_map).connect(tag,res);
+ }
+ template<class Tag>
+ void disconnect(Tag const &tag){
+ fusion::at_key<Tag>(this->type_map).disconnect(tag);
+ }
+ template<class Tag>
+ struct iterator{
+ typedef typename mpl::at<Resources,Tag>::type Resource;
+ typedef typename resource_type<Tag,Resource>::type::iterator type;
+ };
+ template<class Tag>
+ std::pair<typename iterator<Tag>::type,typename iterator<Tag>::type> range() const{
+ return fusion::at_key<Tag>(this->type_map).range();
+ }
+ template<class Tag>
+ std::size_t size() const{
+ return fusion::at_key<Tag>(this->type_map).size();
+ }
+private:
+ type_map_type type_map;
+};
+
+template<class Resources>
+class resource_transactions : noncopyable{
+public:
+ resource_transactions() : rolled_back_(false){}
+ bool rolled_back() const{ return this->rolled_back_; }
+ void rolled_back(bool rb){ this->rolled_back_=rb; }
+ template<class Tag>
+ optional<typename mpl::at<Resources,Tag>::type::transaction> &get(std::size_t index){
+ return fusion::at_key<Tag>(this->tx).get(index);
+ }
+ template<class Tag>
+ void size(std::size_t size){
+ fusion::at_key<Tag>(this->tx).size(size);
+ }
+private:
+ template<class Resource>
+ class transaction{
+ public:
+ optional<typename Resource::transaction> &get(std::size_t index){
+ BOOST_ASSERT(index == 0);
+ return this->tx;
+ }
+ void size(std::size_t size){
+ BOOST_ASSERT(size <= 1);
+ }
+ private:
+ optional<typename Resource::transaction> tx;
+ };
+ template<class Resource>
+ class transaction_array{
+ public:
+ optional<typename Resource::transaction> &get(std::size_t index){
+ return this->tx[index];
+ }
+ void size(std::size_t size){
+ if(size > 0){
+ this->tx.reset(new optional<typename Resource::transaction>[size]);
+ }
+ }
+ private:
+ scoped_array<optional<typename Resource::transaction> > tx;
+ };
+ template<class Pair>
+ struct make_transaction{
+ typedef fusion::pair<
+ typename Pair::first,
+ transaction<typename Pair::second>
+ > type;
+ };
+ template<class Pair>
+ struct make_transaction_array{
+ typedef fusion::pair<
+ typename Pair::first,
+ transaction_array<typename Pair::second>
+ > type;
+ };
+ template<class Pair>
+ struct tag_is_empty{
+ typedef is_empty<typename Pair::first> type;
+ };
+ typedef typename fusion::result_of::as_map<
+ typename mpl::fold<
+ Resources,
+ mpl::vector0<>,
+ mpl::push_back<
+ mpl::_1,
+ mpl::if_<
+ tag_is_empty<mpl::_2>,
+ make_transaction<mpl::_2>,
+ make_transaction_array<mpl::_2>
+ >
+ >
+ >::type
+ >::type tx_type;
+ tx_type tx;
+ bool rolled_back_;
 };
 
-template<class State,class F>
-struct runtime_folder{ //TODO mit fusion::fold austauschen
- explicit runtime_folder(State &state,F &f)
- : state(state),f(f){}
- template<class U>
- void operator()(U x){
- state=f(state,x);
+template<class It,class End,class Resources,class F>
+void for_each(resources<Resources> &,resource_transactions<Resources> &,F &,mpl::true_ end){}
+
+template<class It,class End,class Resources,class F>
+void for_each(resources<Resources> &ress,resource_transactions<Resources> &txs,F &f,mpl::false_ end){
+ typedef typename mpl::deref<It>::type::first Tag;
+ typedef typename mpl::deref<It>::type::second Resource;
+ typedef typename resources<Resources>::template iterator<Tag>::type iterator;
+ std::pair<iterator,iterator> range=ress.template range<Tag>();
+ std::size_t index=0;
+ for(iterator it=range.first;it != range.second;++it,++index){
+ optional<typename Resource::transaction> &tx=txs.get<Tag>(index);
+ f(it->first,*it->second,tx);
+ }
+
+ typedef typename mpl::next<It>::type Next;
+ for_each<Next,End>(ress,txs,f,typename is_same<Next,End>::type());
+}
+
+template<class Resources,class F>
+void for_each(resources<Resources> &ress,resource_transactions<Resources> &txs,F f){
+ for_each<typename mpl::begin<Resources>::type,typename mpl::end<Resources>::type>(
+ ress,txs,f,typename mpl::empty<Resources>::type()
+ );
+}
+
+template<class F,class State>
+struct folder{
+public:
+ explicit folder(F const &f,State &state) : f(f),state(state){}
+ template<class Tag,class Resource>
+ void operator()(Tag const &tag,Resource const &res,optional<typename Resource::transaction> &tx){
+ this->state=this->f(tag,res,tx,this->state);
     }
 private:
+ F f;
     State &state;
- F &f;
 };
 
-template<class Sequence,class State,class F>
-State runtime_fold(State state,F f){
- mpl::for_each<Sequence>(runtime_folder<State,F>(state,f));
+template<class Resources,class State,class F>
+State fold(resources<Resources> &ress,resource_transactions<Resources> &txs,F const &f,State state){
+ for_each<Resources>(ress,txs,folder<F,State>(f,state));
     return state;
 }
 
+template<class Resources,class LazySet,bool TThreads>
+class transaction : noncopyable{
+public:
+ template<class T>
+ transaction(T const &c) : parent_(c.parent){
+ resources<Resources> &ress=c.resources;
+ this->construct(ress,typename T::flat());
+ }
+private:
+//public:
+ template<class,bool,class,bool,bool> friend class transact::basic_transaction_manager;
+
+ template<class Tag>
+ typename mpl::at<Resources,Tag>::type::transaction &resource_transaction(resources<Resources> &ress,Tag const &tag){
+ typedef typename mpl::at<Resources,Tag>::type Resource;
+ std::size_t index;
+ Resource &res=ress.get(tag,index);
+ optional<typename Resource::transaction> &rtx=this->rtxs->get<Tag>(index);
+ this->lazy_begin(tag,res,rtx,ress,typename mpl::has_key<LazySet,Tag>::type());
+ BOOST_ASSERT(rtx);
+ return *rtx;
+ }
+ void commit(resources<Resources> &ress){
+ if(this->flat_nested()){
+ if(this->rtxs->rolled_back()) throw no_transaction();
+ return; // flat nested transaction commit is a no-op
+ }else{
+ BOOST_ASSERT(this->rtxs_storage && this->rtxs == &*this->rtxs_storage);
+ //finish until all finish_transaction()s return false
+ while(basic_transaction_manager::fold(ress,*this->rtxs_storage,finisher(),false));
+
+ for_each(ress,*this->rtxs_storage,preparer<false>()); //prepare non-durable two-phase transactions
+ //count durable transactions and transactions that only support one-phase commit:
+ std::size_t dur=basic_transaction_manager::fold(ress,*this->rtxs_storage,durable_counter(),std::size_t(0));
+ if(dur > 1){
+ for_each(ress,*this->rtxs_storage,preparer<true>()); //prepare durable transactions
+ //TODO write commit message to log
+ }
+ //commit durable transactions first, because there might have been only
+ //one durable transaction, which might still fail because it was not prepared:
+ for_each(ress,*this->rtxs_storage,committer<true>());
+ for_each(ress,*this->rtxs_storage,committer<false>());
+ }
+ }
+
+ void rollback(resources<Resources> &ress){
+ if(!this->rtxs->rolled_back()){ //a flat nested transaction might have rolled back before
+ this->rtxs->rolled_back(true);
+ for_each(ress,*this->rtxs,rollbacker());
+ }
+ }
+ void restart(resources<Resources> &ress){
+ if(this->flat_nested()) throw unsupported_operation();
+ BOOST_ASSERT(this->rtxs_storage);
+ beginner<false> begin(this->parent(),ress);
+ for_each(ress,*this->rtxs_storage,restarter<beginner<false> >(begin));
+ }
+
+ transaction *parent() const{ return this->parent_; }
+private:
+ void construct(resources<Resources> &ress,mpl::true_ flat){
+ if(this->parent()){
+ this->rtxs=this->parent()->rtxs;
+ BOOST_ASSERT(this->rtxs);
+ if(this->rtxs->rolled_back()){
+ //user tried to begin a transaction in a closed transaction scope that was not restarted even though
+ //an open transaction inside it was rolled back:
+ throw no_transaction();
+ }
+ }else this->construct_closed(ress);
+ }
+ void construct(resources<Resources> &ress,mpl::false_ flat){
+ this->construct_closed(ress);
+ }
+ void construct_closed(resources<Resources> &ress){
+ this->rtxs_storage=in_place();
+ this->rtxs=&*this->rtxs_storage;
+ detail::for_each<Resources>(rtx_sizer(*this->rtxs_storage,ress));
+ for_each(ress,*this->rtxs_storage,beginner<false>(this->parent(),ress));
+ }
+
+ struct rtx_sizer{
+ rtx_sizer(resource_transactions<Resources> &txs,resources<Resources> &ress) : txs(txs),ress(ress){}
+ template<class Pair>
+ void operator()(){
+ //make room for as many resource transactions as there are resources connected:
+ typedef typename Pair::first Tag;
+ txs.size<Tag>(ress.size<Tag>());
+ }
+ private:
+ resource_transactions<Resources> &txs;
+ resources<Resources> &ress;
+ };
+ friend struct transact::detail::beginner<transaction,resources<Resources> >;
+ template<bool ConstructLazy>
+ struct beginner : transact::detail::beginner<transaction,resources<Resources> >{
+ typedef transact::detail::beginner<transaction,resources<Resources> > base_type;
+
+ beginner(transaction *parent,resources<Resources> &ress) : base_type(parent,ress){}
+ template<class Tag,class Resource>
+ void operator()(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx){
+ static bool const lazy=mpl::has_key<LazySet,Tag>::type::value && !ConstructLazy;
+ this->begin(tag,res,tx,mpl::bool_<lazy>());
+ }
+ private:
+ template<class Tag,class Resource>
+ void begin(Tag const &,Resource &,optional<typename Resource::transaction> &tx,mpl::true_ lazy){
+ BOOST_ASSERT(!tx);
+ }
+ template<class Tag,class Resource>
+ void begin(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx,mpl::false_ lazy){
+ BOOST_ASSERT(!tx);
+ base_type::operator()(tag,res,tx);
+ BOOST_ASSERT(tx);
+ }
+ };
+ template<bool Durable>
+ struct preparer{
+ template<class Tag,class Resource>
+ void operator()(Tag const &,Resource &res,optional<typename Resource::transaction> &tx){
+ if(tx) this->prepare(res,*tx,typename has_service<Resource,distributed_transaction_service_tag>::type());
+ }
+ private:
+ template<class Resource>
+ void prepare(Resource &res,typename Resource::transaction &rtx,mpl::true_ distributedservice){
+ if(Durable == Resource::durable){
+ res.prepare_transaction(rtx);
+ }
+ }
+ template<class Resource>
+ void prepare(Resource &,typename Resource::transaction &,mpl::false_ distributedservice){
+ if(Durable) throw unsupported_operation();
+ }
+ };
+ template<bool Durable>
+ struct committer : transact::detail::committer{
+ template<class Tag,class Resource>
+ void operator()(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx){
+ this->commit(tag,res,tx,typename has_service<Resource,distributed_transaction_service_tag>::type());
+ }
+ private:
+ template<class Tag,class Resource>
+ void commit(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx,mpl::true_ distributedservice){
+ if(Durable == Resource::durable){
+ transact::detail::committer::operator()(tag,res,tx);
+ }
+ }
+ template<class Tag,class Resource>
+ void commit(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx,mpl::false_ distributedservice){
+ if(Durable) transact::detail::committer::operator()(tag,res,tx);
+ }
+ };
+ struct durable_counter{
+ template<class Tag,class Resource>
+ std::size_t operator()(Tag const &,Resource &,optional<typename Resource::transaction> &tx,std::size_t count){
+ return count + (tx && this->durable<Resource>(typename has_service<Resource,distributed_transaction_service_tag>::type()) ? 1 : 0);
+ }
+ private:
+ template<class Resource>
+ bool durable(mpl::true_ distributedservice) const{
+ return Resource::durable;
+ }
+ template<class Resource>
+ bool durable(mpl::false_ distributedservice) const{
+ return true;
+ }
+ };
+ bool flat_nested() const{
+ return this->parent() && this->parent()->rtxs == this->rtxs;
+ }
+
+ template<class Tag,class Resource>
+ void lazy_begin(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx,resources<Resources> &ress,mpl::true_ lazy){
+ lock_guard<mutex_type> l(this->mutex);
+ if(!tx){
+ beginner<true> begin(this->parent,ress);
+ begin(tag,res,tx);
+ }
+ BOOST_ASSERT(tx);
+ }
+ template<class Tag,class Resource>
+ void lazy_begin(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx,resources<Resources> &ress,mpl::false_ lazy){}
+
+ resource_transactions<Resources> *rtxs; // never 0. == *rtxs_storage for closed transactions, == *parent->parent->...->rtxs_storage for open transactions.
+ transaction *parent_;
+ optional<resource_transactions<Resources> > rtxs_storage;
+
+ typedef typename mpl::if_c<
+ TThreads && !mpl::empty<LazySet>::value,
+ boost::mutex,
+ transact::detail::null_lockable
+ >::type mutex_type;
+ mutex_type mutex;
+};
+
+}
+
 }
 
 /// Model of TransactionManager. Only members that are not part of that concept are documented here.
 ///
 /// Template parameters:
 /// \li \c Resources A MPL Sequence containing the types of the resource managers used.
-/// \li \c Threads \c true if multiple threads are used to access this transaction manager.
-/// \li \c TThreads \c true if multiple threads are used to access the same transaction. Can be \c false if multiple threads are used to access the transaction manager, but not to access the same transaction.
 /// \li \c Lazy A MPL Sequence of resource tags of those resource managers whose transactions
 /// ought to be started lazily, i.e. the local transaction of the resource manager
 /// is not started when the global transaction is started but on first
 /// 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.
+/// \li \c Threads \c true if multiple threads are used to access this transaction manager.
+/// \li \c TThreads \c true if multiple threads are used to access the same transaction. Can be \c false if multiple threads are used to access the transaction manager, but not to access the same transaction.
 /// \brief A transaction manager
 template<
     class Resources,
- bool Threads=true,
- bool TThreads=true,
- class Lazy=mpl::empty_sequence
+ bool FlatNested,
+ class Lazy,
+ bool Threads,
+ bool TThreads
>
 class basic_transaction_manager : noncopyable{
 /// \cond
     BOOST_STATIC_ASSERT(Threads || !TThreads);
-public:
- class transaction;
 private:
- 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 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 detail{ //for QuickBook
+ typedef typename mpl::fold< //TODO optimization: dont fold if Resources already is a mpl::map
+ Resources,
+ mpl::map0<>,
+ mpl::insert<mpl::_1,mpl::_2>
+ >::type resource_types;
+ typedef typename mpl::fold< //TODO optimization: dont fold if Lazy already is a mpl::set
+ Lazy,
+ mpl::set0<>,
+ mpl::insert<mpl::_1,mpl::_2>
+ >::type lazy_set;
+ typedef transact::detail::basic_transaction_manager::transaction<resource_types,lazy_set,TThreads> transaction;
+ typedef typename transact::detail::basic_transaction_manager::resources<resource_types> resources_type;
+ class transaction_construct_t{
+ transaction_construct_t(resources_type &resources,transaction *parent)
+ : resources(resources),parent(parent){}
+ friend class basic_transaction_manager;
+ template<class,class,bool> friend class transact::detail::basic_transaction_manager::transaction;
+ resources_type &resources;
+ transaction * const parent;
+ typedef mpl::bool_<FlatNested> flat; //TODO
+ };
     };
-
     struct currenttx_tag{};
     typedef transact::detail::static_thread_specific_ptr<
- transaction,
+ typename detail::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 basic_transaction_manager::template resource_type<Tag>::type type;
- };
- };
-
     /// \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;
-
- 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;
-
- typedef typename mpl::if_c<
- TThreads && !mpl::empty<Lazy>::value,
- transact::detail::mutex_type,
- transact::detail::null_lockable
- >::type mutex_type;
-
- mutex_type mutex;
- /// \endcond
- };
- typedef Resources resource_types;
+ typedef typename detail::transaction transaction;
+ typedef typename detail::resource_types resource_types;
 
+ //TODO evtl. nicht-konstruierbar machen und log anders starten?
     /// A basic_transaction_manager constructed using this constructor
     /// is not able to commit transactions that involve two or more persistent
     /// resource managers, i.e. that require a two phase commit protocol.
@@ -179,63 +571,51 @@
     basic_transaction_manager(){}
 
     /// TODO doc, not part of the concept
- template<class Resource>
- static void connect_resource(Resource &newres){
- Resource *&res=fusion::at_key<typename Resource::tag>(resources);
- if(res) throw resource_error();
- res=&newres;
+ template<class Tag>
+ static void connect_resource(typename mpl::at<resource_types,Tag>::type &newres,Tag const &tag=Tag()){
+ resources_.connect(tag,newres);
     }
 
     /// TODO doc, not part of the concept
     template<class ResourceTag>
     static void disconnect_resource(ResourceTag tag=ResourceTag()){
- fusion::at<ResourceTag>(resources)=0;
+ resources_.disconnect(tag);
     }
 
     template<class Tag>
- 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();
+ static typename mpl::at<resource_types,Tag>::type &resource(Tag tag=Tag()){
+ return resources_.get(tag);
     }
 
     template<class Tag>
- static typename detail::template resource_type<Tag>::type::transaction &
+ struct resource_iterator{
+ typedef typename detail::resources_type::template iterator<Tag>::type type;
+ };
+ template<class Tag>
+ static std::pair<typename resource_iterator<Tag>::type,typename resource_iterator<Tag>::type> resources(){
+ return resources_.template range<Tag>();
+ }
+
+ template<class Tag>
+ static typename mpl::at<resource_types,Tag>::type::transaction &
     resource_transaction(transaction &tx,Tag tag=Tag()){
- return resource_transaction(tx,tag,typename mpl::contains<Lazy,Tag>());
+ return tx.resource_transaction(resources_,tag);
     }
 
     static typename detail::transaction_construct_t begin_transaction(){
- return transaction_construct_t(currenttx::get());
+ return typename detail::transaction_construct_t(resources_,currenttx::get());
     }
 
     static void commit_transaction(transaction &tx){
         bind_transaction(tx);
-
- //call finish_transaction until all transactions return false
- while(transact::detail::runtime_fold<resource_tags>(false,finisher(tx)));
-
- 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<resource_tags>(0,persistent_counter(tx));
- if(pers > 1){
- mpl::for_each<resource_tags>(preparer<true>(tx)); //prepare persistent transactions
- //TODO write commit message to log
- mpl::for_each<resource_tags>(committer<true>(tx)); //commit persistent transactions
- }else{
- mpl::for_each<resource_tags>(committer<true>(tx)); //commit persistent transaction unprepared
- }
- mpl::for_each<resource_tags>(committer<false>(tx)); //commit transient two-phase transactions
+ tx.commit(resources_);
     }
 
     static void rollback_transaction(transaction &tx){
- bind_transaction(tx);
- mpl::for_each<resource_tags>(rollbacker(tx));
+ tx.rollback(resources_);
     }
-
     static void restart_transaction(transaction &tx){
- mpl::for_each<resource_tags>(restarter(tx));
+ tx.restart(resources_);
     }
 
     static void bind_transaction(transaction &tx){
@@ -245,233 +625,28 @@
         currenttx::reset(0);
     }
 
- static transaction &current_transaction(){
- if(transaction *tx=currenttx::get()) return *tx;
- else throw no_transaction();
+ static transaction *current_transaction(){
+ return currenttx::get();
     }
- static bool has_current_transaction(){
- return currenttx::get() ? true : false;
+ static transaction *parent_transaction(transaction &tx){
+ return tx.parent();
     }
 
     /// \cond
 private:
- struct persistent_counter{
- explicit persistent_counter(transaction &tx) : tx(tx){}
- template<class Tag>
- std::size_t operator()(std::size_t c,Tag){
- 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;
- }
- }
- return c;
- }
- private:
- transaction &tx;
- };
- struct finisher{
- explicit finisher(transaction &tx) : tx(tx){}
- template<class Tag>
- bool operator()(bool repeat,Tag 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 *rmgr=fusion::at_key<Tag>(resources);
- BOOST_ASSERT(rmgr);
- return rmgr->finish_transaction(*rtx) || repeat;
- }
- return repeat;
- }
- private:
- transaction &tx;
- };
- struct beginner{
- explicit beginner(transaction &tx) : tx(tx){}
- template<class Tag>
- void operator()(Tag tag){
- this->begin(tag,typename mpl::contains<Lazy,Tag>::type());
- }
- private:
- template<class Tag>
- void begin(Tag,mpl::true_ lazy){}
- template<class Tag>
- void begin(Tag,mpl::false_ lazy){
- typedef typename resource_type<Tag>::type res_type;
- res_type *rmgr=fusion::at_key<Tag>(resources);
- if(rmgr){
- optional<typename res_type::transaction> &rtx=
- fusion::at_key<Tag>(tx.resource_transactions);
- BOOST_ASSERT(!rtx);
- if(tx.parent){
- typename res_type::transaction &parentrtx=
- resource_transaction<Tag>(*tx.parent);
- rtx=in_place(rmgr->begin_nested_transaction(parentrtx));
- }else rtx=in_place(rmgr->begin_root_transaction());
- }
- }
- transaction &tx;
- };
- template<class Tag>
- static typename detail::template resource_type<Tag>::type::transaction &
- resource_transaction(transaction &tx,Tag tag,mpl::true_ lazy){
- typedef typename resource_type<Tag>::type res_type;
- optional<typename res_type::transaction> &rtx=
- fusion::at_key<Tag>(tx.resource_transactions);
-
- lock_guard<typename transaction::mutex_type> l(tx.mutex);
- if(!rtx){
- res_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 res_type::transaction &parentrtx=resource_transaction<Tag>(*tx.parent);
- rtx=in_place(res.begin_nested_transaction(parentrtx));
- }else{
- rtx=in_place(res.begin_root_transaction());
- }
- }
- return *rtx;
- }
- template<class Tag>
- static typename detail::template resource_type<Tag>::type::transaction &
- resource_transaction(transaction &tx,Tag tag,mpl::false_ lazy){
- typedef typename resource_type<Tag>::type res_type;
- optional<typename res_type::transaction> &rtx=
- fusion::at_key<Tag>(tx.resource_transactions);
- BOOST_ASSERT(rtx);
- return *rtx;
- }
- template<class Resource>
- struct is_persistent{
- typedef mpl::true_ type; //FIXME
- };
- template<class Resource>
- struct is_two_phase{
- typedef mpl::false_ type; //FIXME
- };
-
- template<bool Persistent>
- struct committer{
- explicit committer(transaction &tx) : tx(tx){}
- template<class Tag>
- void operator()(Tag){
- 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);
- if(rtx){
- res_type *res=fusion::at_key<Tag>(resources);
- BOOST_ASSERT(res);
- res->commit_transaction(*rtx);
- }
- }
- }
- private:
- transaction &tx;
- };
- template<bool Persistent>
- struct preparer{
- explicit preparer(transaction &tx) : tx(tx){}
- template<class Tag>
- void operator()(Tag){
- typedef typename resource_type<Tag>::type res_type;
- if(Persistent == is_persistent<res_type>::type::value){
- 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->prepare(*res,*rtx,typename is_two_phase<res_type>::type());
- }
- }
- }
- private:
- template<class Resource>
- void prepare(Resource &res,typename Resource::transaction &rtx,mpl::true_){
- res.prepare_transaction(rtx);
- }
- template<class Resource>
- void prepare(Resource &res,typename Resource::transaction &rtx,mpl::false_){
- //a resource that does not support two-phase-commit was used
- //together with other persistent resources
- throw unsupported_operation();
- }
- transaction &tx;
- };
- struct rollbacker{
- explicit rollbacker(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);
- 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>
- struct make_resource_ptr_pair{
- typedef fusion::pair<typename Resource::tag,Resource *> type;
- };
- typedef typename fusion::result_of::as_map<
- typename mpl::transform<
- Resources,
- make_resource_ptr_pair<mpl::_1>
- >::type
- >::type resources_type;
- static resources_type resources;
-
+ typedef typename detail::resources_type resources_type;
+ static resources_type resources_;
     /// \endcond
 };
 
-template<class Res,bool Thr,bool TThr,class Lazy>
-typename basic_transaction_manager<Res,Thr,TThr,Lazy>::resources_type
-basic_transaction_manager<Res,Thr,TThr,Lazy>::resources;
+
+template<class Resources,bool FlatNested,class Lazy,bool Threads,bool TThreads>
+typename basic_transaction_manager<Resources,FlatNested,Lazy,Threads,TThreads>::resources_type
+basic_transaction_manager<Resources,FlatNested,Lazy,Threads,TThreads>::resources_;
 
 }
 }
 
 
 
-#endif
\ No newline at end of file
+#endif

Added: sandbox/transaction/boost/transact/detail/algorithm.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/detail/algorithm.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -0,0 +1,92 @@
+// 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_DETAIL_ALGORITH_HPP
+#define BOOST_TRANSACT_DETAIL_ALGORITH_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/transact/detail/config.hpp>
+
+namespace boost{
+namespace transact{
+namespace detail{
+
+//same as mpl::for_each, but without constructing the element
+
+template<class It,class End,class F>
+void for_each(F &f,mpl::true_){}
+
+template<class It,class End,class F>
+void for_each(F &f,mpl::false_){
+ typedef typename mpl::deref<It>::type Element;
+ f.BOOST_NESTED_OPERATOR_TEMPLATE operator()<Element>();
+
+ typedef typename mpl::next<It>::type Next;
+ for_each<Next,End>(f,typename boost::is_same<Next,End>::type());
+}
+
+template<class Sequence,class F>
+void for_each(F f){
+ typedef typename mpl::begin<Sequence>::type Begin;
+ typedef typename mpl::end<Sequence>::type End;
+ for_each<Begin,End>(f,typename boost::is_same<Begin,End>::type());
+}
+
+//same as for_each, but stop iterating when the function returns false
+
+template<class It,class End,class F>
+bool for_each_if(F &f,mpl::true_){
+ return true;
+}
+
+template<class It,class End,class F>
+bool for_each_if(F &f,mpl::false_){
+ typedef typename mpl::deref<It>::type Element;
+ if(f.BOOST_NESTED_OPERATOR_TEMPLATE operator()<Element>()){
+ typedef typename mpl::next<It>::type Next;
+ return for_each_if<Next,End>(f,typename boost::is_same<Next,End>::type());
+ }else return false;
+}
+
+template<class Sequence,class F>
+bool for_each_if(F f){
+ typedef typename mpl::begin<Sequence>::type Begin;
+ typedef typename mpl::end<Sequence>::type End;
+ return for_each_if<Begin,End>(f,typename boost::is_same<Begin,End>::type());
+}
+
+
+template<class It,class End,class State,class F>
+State fold(F &,State const &state,mpl::true_){
+ return state;
+}
+
+template<class It,class End,class State,class F>
+State fold(F &f,State const &state,mpl::false_){
+ typedef typename mpl::deref<It>::type Element;
+ typedef typename mpl::next<It>::type Next;
+ return fold<Next,End>(f,f.BOOST_NESTED_OPERATOR_TEMPLATE operator()<Element>(state),typename boost::is_same<Next,End>::type());
+}
+
+template<class Sequence,class State,class F>
+State fold(F f,State const &initial){
+ typedef typename mpl::begin<Sequence>::type Begin;
+ typedef typename mpl::end<Sequence>::type End;
+ return fold<Begin,End>(f,initial,typename boost::is_same<Begin,End>::type());
+}
+
+
+}
+}
+}
+
+
+#endif

Modified: sandbox/transaction/boost/transact/detail/buffering_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/buffering_file.hpp (original)
+++ sandbox/transaction/boost/transact/detail/buffering_file.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -1,4 +1,5 @@
 // Copyright Stefan Strasser 2009 - 2010.
+// Copyright Bob Walters 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)

Added: sandbox/transaction/boost/transact/detail/config.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/detail/config.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -0,0 +1,17 @@
+// 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_DETAIL_CONFIG_HPP
+#define BOOST_TRANSACT_DETAIL_CONFIG_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_MSVC
+#define BOOST_NESTED_OPERATOR_TEMPLATE
+#else
+#define BOOST_NESTED_OPERATOR_TEMPLATE template
+#endif
+
+#endif

Modified: sandbox/transaction/boost/transact/detail/file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/file.hpp (original)
+++ sandbox/transaction/boost/transact/detail/file.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -1,3 +1,8 @@
+// Copyright Bob Walters 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_DETAIL_FILE_HPP
 #define BOOST_TRANSACT_DETAIL_FILE_HPP
 

Modified: sandbox/transaction/boost/transact/detail/filebuf_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/filebuf_file.hpp (original)
+++ sandbox/transaction/boost/transact/detail/filebuf_file.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -11,6 +11,7 @@
 #include <string>
 #include <boost/mpl/size_t.hpp>
 #include <boost/transact/exception.hpp>
+#include <boost/transact/detail/file.hpp>
 
 #ifdef BOOST_MSVC
 #pragma warning(push)

Modified: sandbox/transaction/boost/transact/detail/mutex.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/mutex.hpp (original)
+++ sandbox/transaction/boost/transact/detail/mutex.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -6,8 +6,6 @@
 #ifndef BOOST_TRANSACT_DETAIL_MUTEX_HPP
 #define BOOST_TRANSACT_DETAIL_MUTEX_HPP
 
-#include <boost/thread/mutex.hpp>
-
 namespace boost{
 namespace transact{
 namespace detail{
@@ -22,72 +20,5 @@
 }
 }
 
-
-
-#ifdef BOOST_ATOMIC
-#include <boost/atomic.hpp>
-#include <boost/assert.hpp>
-
-namespace boost{
-namespace transact{
-namespace detail{
-
-class combined_mutex{
-public:
- combined_mutex() : count(-1){
- this->smutex.lock();
- }
- void lock(){
- int old=this->count.fetch_add(1,boost::memory_order_acquire);
- if(old >= 0){
- try{
- this->smutex.lock();
- }catch(...){
- --this->count;
- throw;
- }
- }
- }
- void unlock(){
- int old=this->count.fetch_sub(1,boost::memory_order_release);
- BOOST_ASSERT(old >= 0);
- if(old > 0) this->smutex.unlock();
- }
- ~combined_mutex(){
- BOOST_ASSERT(this->count.load() == -1);
- this->smutex.unlock();
- }
-private:
- boost::mutex smutex;
- boost::atomic<int> count;
-};
-
-
-typedef combined_mutex mutex_type;
-
-
-}
-}
-}
-
-#else
-
-
-namespace boost{
-namespace transact{
-namespace detail{
-
-typedef boost::mutex mutex_type;
-
-}
-}
-}
-
-
-#endif
-
-
-
-
 #endif
 

Modified: sandbox/transaction/boost/transact/detail/sectorizing_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/sectorizing_file.hpp (original)
+++ sandbox/transaction/boost/transact/detail/sectorizing_file.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -11,6 +11,7 @@
 #include <boost/static_assert.hpp>
 #include <boost/assert.hpp>
 #include <cstring>
+#include <boost/transact/detail/file.hpp>
 
 namespace boost{
 namespace transact{

Modified: sandbox/transaction/boost/transact/detail/static_tss.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/static_tss.hpp (original)
+++ sandbox/transaction/boost/transact/detail/static_tss.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -24,7 +24,7 @@
     static_thread_specific_ptr();
 public:
 
-#if ((__GNUC__== 3) && (__GNUC_MINOR__ > 4) || __GNUC__>= 4)
+#if (__GNUC__== 3 && __GNUC_MINOR__ > 4) || __GNUC__>= 4
     static void reset(T *p=0){ ptr=p; }
     static T *get(){ return ptr; }
 private:

Modified: sandbox/transaction/boost/transact/detail/syncing_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/syncing_file.hpp (original)
+++ sandbox/transaction/boost/transact/detail/syncing_file.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -1,4 +1,5 @@
-// Copyright Stefan Strasser 2009 - 2010.
+// Copyright Stefan Strasser 2009 - 2010
+// Copyright Bob Walters 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)
@@ -33,34 +34,37 @@
         ofile filedes;
 
 private:
- void write_ahead(size_type const &s){
- BOOST_ASSERT(s % write_ahead_size == 0);
- if(this->pos != s){
- filedes.seek(s);
- }
- char data[write_page_size]; memset(data,0,write_page_size);
- BOOST_STATIC_ASSERT(write_ahead_size % write_page_size == 0);
- for(std::size_t c=0;c<write_ahead_size / write_page_size;++c){
- filedes.write(data,write_page_size);
- }
- filedes.sync();
- filedes.seek(this->pos);
- }
     void write_ahead(size_type const &start,size_type const &end){
         BOOST_ASSERT(start % write_ahead_size == 0);
         BOOST_ASSERT(end % write_ahead_size == 0);
- for(size_type off=start;off < end;off+=write_ahead_size) this->write_ahead(off);
+ BOOST_STATIC_ASSERT(write_ahead_size % page_size == 0);
+ filedes.seek(start);
+ for(size_type off=start;off < end;off+=page_size){
+ filedes.write(empty_page.data,page_size);
+ }
+ filedes.sync();
+ filedes.seek(this->pos);
     }
 
     static std::size_t const write_ahead_size=10*1024*1024;
- static std::size_t const write_page_size=4096;
+ static std::size_t const page_size=4096;
+
+ struct empty_page_type{
+ empty_page_size(){
+ std::memset(data,0,page_size);
+ }
+ char data[page_size];
+ }
+ static empty_page_type empty_page;
+ int filedes;
 };
 
+syncing_seq_ofile::empty_page_type syncing_seq_ofile::empty_page;
+
 inline syncing_seq_ofile::syncing_seq_ofile(std::string const &name)
     : pos(0)
- , filedes(name)
-{
- this->write_ahead(0);
+ , filedes(name){
+ this->write_ahead(0,write_ahead_size);
 }
 
 void syncing_seq_ofile::write(void const *data,std::size_t size){

Added: sandbox/transaction/boost/transact/detail/transaction_manager.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/detail/transaction_manager.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -0,0 +1,171 @@
+// Copyright Stefan Strasser 2010.
+// Copyright Vicente J. Botet Escriba 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_DETAIL_TAG_RESOURCE_PAIR_HPP
+#define BOOST_TRANSACT_DETAIL_TAG_RESOURCE_PAIR_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/optional/optional.hpp>
+#include <boost/transact/exception.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/assert.hpp>
+#include <boost/mpl/has_key.hpp>
+#include <boost/transact/resource_manager.hpp>
+#include <boost/transact/exception.hpp>
+
+namespace boost{
+namespace transact{
+
+namespace detail{
+
+template<class Tag,class Resource>
+class tag_resource_pair : noncopyable{
+public:
+ typedef std::pair<Tag,Resource *> *iterator;
+ void connect(Tag const &tag,Resource &res){
+ if(this->pair){
+ if(this->tag_is_equal(tag)) throw resource_error();
+ else throw unsupported_operation();
+ }
+ this->pair=std::make_pair(tag,&res);
+ }
+ void disconnect(Tag const &tag){
+ if(!this->pair || !this->tag_is_equal(tag)) throw resource_error();
+ this->pair=none;
+ }
+ Resource &get(Tag const &tag) const{
+ if(!this->pair || !this->tag_is_equal(tag)) throw resource_error();
+ BOOST_ASSERT(this->pair->second);
+ return *this->pair->second;
+ }
+ Resource &get(Tag const &tag,std::size_t &index) const{
+ if(!this->pair || !this->tag_is_equal(tag)) throw resource_error();
+ BOOST_ASSERT(this->pair->second);
+ index=0;
+ return *this->pair->second;
+ }
+ std::pair<iterator,iterator> range() const{
+ if(this->pair){
+ return std::pair<iterator,iterator>(&*this->pair,&*this->pair + 1);
+ }else{
+ return std::pair<iterator,iterator>(0,0);
+ }
+ }
+ bool empty() const{
+ return !this->pair;
+ }
+ std::size_t size() const{
+ return this->pair ? 1 : 0;
+ }
+
+ Tag const &tag() const{
+ BOOST_ASSERT(this->pair);
+ return this->pair->first;
+ }
+private:
+ bool tag_is_equal(Tag const &o){
+ return this->tag_is_equal(o,boost::is_empty<Tag>());
+ }
+ bool tag_is_equal(Tag const &,mpl::true_ empty){
+ return true;
+ }
+ bool tag_is_equal(Tag const &o,mpl::false_ empty){
+ BOOST_ASSERT(this->pair);
+ return this->pair->first == o;
+ }
+
+ optional<std::pair<Tag,Resource *> > pair;
+};
+
+template<class Transaction,class Resources>
+struct beginner{
+ beginner(Transaction *parent,Resources &ress) : parent(parent),ress(ress){}
+ template<class Tag,class Resource>
+ void operator()(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx){
+ BOOST_ASSERT(!tx);
+ if(this->parent) this->begin_nested(tag,res,tx,typename has_service<Resource,nested_transaction_service_tag>::type());
+ else tx=in_place(res.begin_transaction());
+ BOOST_ASSERT(tx);
+ }
+private:
+ template<class Tag,class Resource>
+ void begin_nested(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx,mpl::true_ nestedservice){
+ BOOST_ASSERT(this->parent);
+ typename Resource::transaction &parenttx=this->parent->resource_transaction(this->ress,tag);
+ tx=in_place(res.begin_nested_transaction(parenttx));
+ }
+ template<class Tag,class Resource>
+ void begin_nested(Tag const &,Resource &,optional<typename Resource::transaction> &,mpl::false_ nestedservice){
+ throw unsupported_operation();
+ }
+
+ Transaction *parent;
+ Resources &ress;
+};
+
+struct finisher{
+ template<class Tag,class Resource>
+ bool operator()(Tag const &,Resource &res,optional<typename Resource::transaction> &tx,bool repeat){
+ if(tx){
+ return this->finish(res,*tx,typename has_service<Resource,finish_transaction_service_tag>::type())
+ || repeat;
+ }else return repeat;
+ }
+private:
+ template<class Resource>
+ bool finish(Resource &res,typename Resource::transaction &tx,mpl::true_ finishservice){
+ return res.finish_transaction(tx);
+ }
+ template<class Resource>
+ bool finish(Resource &res,typename Resource::transaction &tx,mpl::false_ finishservice){
+ return false;
+ }
+};
+
+struct committer{
+ template<class Tag,class Resource>
+ void operator()(Tag const &,Resource &res,optional<typename Resource::transaction> &tx){
+ if(tx) res.commit_transaction(*tx);
+ }
+};
+struct rollbacker{
+ template<class Tag,class Resource>
+ void operator()(Tag const &,Resource &res,optional<typename Resource::transaction> &tx){
+ if(tx) res.rollback_transaction(*tx);
+ }
+};
+template<class Beginner>
+struct restarter{
+ explicit restarter(Beginner const &begin) : begin(begin){}
+ template<class Tag,class Resource>
+ void operator()(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx){
+ if(tx) this->restart(tag,res,tx,typename has_service<Resource,restart_transaction_service_tag>::type());
+ }
+private:
+ template<class Tag,class Resource>
+ void restart(Tag const &,Resource &res,optional<typename Resource::transaction> &tx,mpl::true_ service){
+ BOOST_ASSERT(tx);
+ res.restart_transaction(*tx);
+ }
+ template<class Tag,class Resource>
+ void restart(Tag const &tag,Resource &res,optional<typename Resource::transaction> &tx,mpl::false_ service){
+ BOOST_ASSERT(tx);
+ res.rollback_transaction(*tx);
+ tx=none;
+ this->begin(tag,res,tx);
+ }
+ Beginner begin;
+};
+
+
+
+}
+}
+}
+
+#endif

Modified: sandbox/transaction/boost/transact/exception.hpp
==============================================================================
--- sandbox/transaction/boost/transact/exception.hpp (original)
+++ sandbox/transaction/boost/transact/exception.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -9,14 +9,10 @@
 
 #include <exception>
 #include <boost/assert.hpp>
-#include <boost/mpl/pair.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/for_each.hpp>
-#include <boost/mpl/fold.hpp>
-#include <boost/mpl/vector.hpp>
-#include <boost/mpl/at.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/end.hpp>
 #include <boost/type_traits/is_same.hpp>
-#include <boost/optional/optional.hpp>
+#include <boost/transact/detail/algorithm.hpp>
 
 
 namespace boost{
@@ -48,19 +44,6 @@
 template<class ResMgr>
 struct resource_isolation_exception;
 
-namespace detail{
-
-template<class TxMgr>
-struct tag_types{
- typedef typename mpl::fold<
- typename TxMgr::resource_types,
- mpl::vector0<>,
- mpl::push_back<mpl::_1,mpl::first<mpl::_2> >
- >::type type;
-};
-
-}
-
 ///\brief Indicates that the operation conflicted with another transaction.
 ///
 ///\c isolation_exception is an abstract base class. The derived class
@@ -71,8 +54,8 @@
     ///\pre TxMgr::current_transaction() must be a rolled back transaction
     template<class TxMgr>
     void unwind() const{ //pseudo-virtual
- //TODO optimization: stop iteration when correct resource_isolation_exception is found
- mpl::for_each<typename detail::tag_types<TxMgr>::type>(unwinder<TxMgr>(*this));
+ typedef typename TxMgr::resource_types res_types;
+ BOOST_VERIFY(( ! detail::for_each_if<res_types>(unwinder<TxMgr>(*this)) ));
     }
     virtual ~isolation_exception() throw(){}
 protected:
@@ -81,13 +64,13 @@
     template<class TxMgr>
     struct unwinder{
         explicit unwinder(isolation_exception const &e) : e(e){}
- template<class Tag>
- void operator()(Tag){
- typedef typename mpl::at<typename TxMgr::resource_types,Tag>::type resource_type;
- typedef resource_isolation_exception<resource_type> der_type;
+ template<class Pair>
+ bool operator()() const{
+ typedef resource_isolation_exception<typename Pair::second> der_type;
             if(der_type const *der=dynamic_cast<der_type const *>(&this->e)){
                 der->template unwind<TxMgr>();
- }
+ return false;
+ }else return true;
         }
     private:
         isolation_exception const &e;
@@ -102,56 +85,74 @@
 template<class ResMgr>
 struct resource_isolation_exception : isolation_exception{
     ///\brief Constructs a resource_isolation_exception
- resource_isolation_exception(){}
+ resource_isolation_exception()
+ : res(0),tx(0){}
 
     ///\brief Constructs a resource_isolation_exception
     ///\param res The resource manager that is throwing the 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(ResMgr const &res,typename ResMgr::transaction const &retry)
- : retry(std::pair<ResMgr const &,typename ResMgr::transaction const &>(res,retry)){}
+ : res(&res),tx(&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
- //FIXME: does not work correctly with flat nested transaction emulation. possibly make TxMgr::restart_transaction throw accordingly?
- if(this->retry){
- //TODO optimization: stop iteration when correct resource manager is found
- mpl::for_each<typename detail::tag_types<TxMgr>::type>(is_current<TxMgr>(*this->retry));
+ if(this->res){
+ typedef typename TxMgr::resource_types res_types;
+ unwinder<TxMgr> unw(*this->res,*this->tx);
+ BOOST_VERIFY(( ! detail::for_each_if<res_types>(unw) ));
         }else throw;
     }
     virtual ~resource_isolation_exception() throw(){}
 private:
     template<class TxMgr>
- struct is_current{
- explicit is_current(std::pair<ResMgr const &,typename ResMgr::transaction const &> const &retry) : retry(retry){}
- template<class Tag>
- void operator()(Tag const &tag) const{
- typedef typename mpl::at<typename TxMgr::resource_types,Tag>::type resource_type;
- return this->operator()(tag,typename is_same<resource_type,ResMgr>::type());
+ struct unwinder{
+ unwinder(ResMgr const &res,typename ResMgr::transaction const &rtx) : res(res),rtx(rtx){}
+ template<class Pair>
+ bool operator()() const{
+ return this->operator()<typename Pair::first>(typename is_same<typename Pair::second,ResMgr>::type());
         }
     private:
         template<class Tag>
- void operator()(Tag const &,mpl::true_) const{
- typedef typename TxMgr::resource_iterator iterator;
+ bool operator()(mpl::true_) const{
+ typedef typename TxMgr::template resource_iterator<Tag>::type iterator;
             std::pair<iterator,iterator> range=TxMgr::template resources<Tag>();
             for(iterator it=range.first;it != range.second;++it){
- if(&it->second == &this->retry.first){
+ if(it->second == &this->res){
                     typename TxMgr::transaction *tx=TxMgr::current_transaction();
                     BOOST_ASSERT(tx);
- if(&TxMgr::resource_transaction(*tx,it->first) != &this->retry.second) throw;
+ typename ResMgr::transaction &foundrtx=TxMgr::resource_transaction(*tx,it->first);
+ if(&foundrtx != &this->rtx){
+ //the transaction that ought to be retried must be a parent of tx:
+ BOOST_ASSERT(TxMgr::parent_transaction(*tx));
+ throw;
+ }else{
+ //the following only works if the TM either uses flat nested txs for all RMs or for none:
+ typename TxMgr::transaction *parent=TxMgr::parent_transaction(*tx);
+ if(parent && &foundrtx == &TxMgr::resource_transaction(*parent,it->first)){
+ //the resource transaction in tx is the same resource transaction as in the parent of tx.
+ //this means the TM is using flat nested transactions. the outermost transaction using rtx must be repeated, not this one:
+ throw;
+ }
+ }
+ return false;
                 }
             }
+ return true;
         }
- template<class Tag>
- void operator()(Tag,mpl::false_) const{
- return false;
+ template<class Pair>
+ bool operator()(mpl::false_) const{
+ // Pair does correspond to another type of resource manager, continue iterating:
+ return true;
         }
- std::pair<ResMgr const &,typename ResMgr::transaction const &> retry;
+
+ ResMgr const &res;
+ typename ResMgr::transaction const &rtx;
     };
- optional<std::pair<ResMgr const &,typename ResMgr::transaction const &> > retry;
+ //always: bool(res) == bool(tx)
+ ResMgr const *res;
+ typename ResMgr::transaction const *tx;
 };
 
 }

Modified: sandbox/transaction/boost/transact/object_access.hpp
==============================================================================
--- sandbox/transaction/boost/transact/object_access.hpp (original)
+++ sandbox/transaction/boost/transact/object_access.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -8,15 +8,13 @@
 #define BOOST_TRANSACT_OBJECT_ACCESS_HPP
 
 #include <boost/serialization/is_bitwise_serializable.hpp>
+#include <boost/serialization/wrapper.hpp>
 #include <boost/type_traits/is_empty.hpp>
-#include <boost/type_traits/is_same.hpp>
 #include <boost/mpl/bool.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/assert.hpp>
-#include <boost/transact/char_archive.hpp>
 #include <boost/transact/detail/embedded_vector.hpp>
-#include <boost/transact/type_selection.hpp>
 #include <cstring>
 #include <algorithm>
 #include <iterator>
@@ -26,12 +24,10 @@
 
 #include <boost/serialization/serialization.hpp>
 #include <boost/serialization/version.hpp>
-#include <boost/archive/basic_binary_iarchive.hpp>
-#include <boost/archive/basic_binary_oarchive.hpp>
-#include <string>
 
 #endif
 
+
 namespace boost{
 namespace transact{
 
@@ -45,6 +41,8 @@
 struct construct_tag;
 template<class Archive,class T>
 void construct(Archive &,T *&,deep_tag);
+template<class UnaryFunction>
+class apply_archive;
 
 }
 
@@ -53,35 +51,38 @@
 public:
     template<class Archive,class T>
     static void save(Archive &ar,T const &t){
- object_access::save(ar,t,boost::is_empty<T>(),serialization::is_bitwise_serializable<T>());
+ object_access::save(ar,t,empty<T>(),serialization::is_bitwise_serializable<T>());
     }
     template<class Archive,class T>
     static void construct(Archive &ar,T *&t){
- object_access::construct(ar,t,boost::is_empty<T>(),serialization::is_bitwise_serializable<T>());
+ object_access::construct(ar,t,empty<T>(),serialization::is_bitwise_serializable<T>());
     }
 
     template<class Archive,class T>
     static void load(Archive &ar,T &t){
- object_access::load(ar,t,boost::is_empty<T>(),serialization::is_bitwise_serializable<T>());
+ object_access::load(ar,t,empty<T>(),serialization::is_bitwise_serializable<T>());
     }
 
     template<class T>
     static T *clone(T const &t){
- return object_access::clone(t,boost::is_empty<T>(),serialization::is_bitwise_serializable<T>());
+ return object_access::clone(t,empty<T>(),serialization::is_bitwise_serializable<T>());
     }
 
     template<class T>
     static bool equal(T const &t1,T const &t2){
- return object_access::equal(t1,t2,boost::is_empty<T>(),serialization::is_bitwise_serializable<T>());
+ return object_access::equal(t1,t2,empty<T>(),serialization::is_bitwise_serializable<T>());
     }
 
     template<class UnaryFunction,class T>
     static void apply(UnaryFunction const &f,T const &t){
- object_access::apply(f,t,mpl::bool_<boost::is_empty<T>::value || serialization::is_bitwise_serializable<T>::value>());
+ object_access::apply(f,t,empty<T>(),serialization::is_bitwise_serializable<T>());
     }
 private:
     template<class T>
- friend class detail::construct_tag;
+ struct empty : mpl::bool_<boost::is_empty<T>::value && !serialization::is_wrapper<T>::type::value>{};
+
+ template<class T>
+ friend struct detail::construct_tag;
     template<class Archive,class T>
     friend void detail::construct(Archive &,T *&,deep_tag);
 
@@ -95,18 +96,18 @@
         t.~T();
     }
 
- template<class UnaryFunction,class T>
- static void apply(UnaryFunction const &f,T const &t,mpl::true_ bitwise_or_empty){
+ template<class UnaryFunction,class T,bool Bitwise>
+ static void apply(UnaryFunction const &f,T const &t,mpl::true_ empty,mpl::bool_<Bitwise>){
         f(t);
     }
     template<class UnaryFunction,class T>
- static void apply(UnaryFunction const &f,T const &t,mpl::false_ bitwise_or_empty);
- template<class UnaryFunction,class T>
- static void apply(UnaryFunction const &f,T &t,mpl::true_ bitwise_or_empty){
+ static void apply(UnaryFunction const &f,T const &t,mpl::false_ empty,mpl::true_ bitwise){
         f(t);
     }
     template<class UnaryFunction,class T>
- static void apply(UnaryFunction const &f,T &t,mpl::false_ bitwise_or_empty);
+ static void apply(UnaryFunction const &f,T const &t,mpl::false_ empty,mpl::false_ bitwise);
+ template<class UnaryFunction,class T>
+ static void apply(detail::apply_archive<UnaryFunction> const &ar,T const &t,mpl::false_ empty,mpl::false_ bitwise);
 
     template<class Archive,class T,bool Bitwise>
     static void save(Archive &ar,T const &t,mpl::true_ empty,mpl::bool_<Bitwise>){}
@@ -168,380 +169,37 @@
     static bool equal(T const &t1,T const &t2,mpl::false_ empty,mpl::false_ bitwise);
 };
 
-namespace detail{
-
-#ifndef NO_BOOST_SERIALIZATION
-
-template<class UnaryFunction>
-class apply_archive
- : public archive::detail::common_oarchive<apply_archive<UnaryFunction> >{
-private:
- typedef archive::detail::common_oarchive<apply_archive> base_type;
-public:
- explicit apply_archive(UnaryFunction const &f)
- : base_type(archive::no_header | archive::no_codecvt)
- , f(f){}
- void save_binary(void const *,std::size_t){}
- void save_override(archive::class_id_optional_type const &,int){}
- void save_override(archive::version_type const &,int){}
- void save_override(archive::class_id_type const &,int){}
- void save_override(archive::class_id_reference_type const &,int){}
- void save_override(archive::object_id_type const &,int){}
- void save_override(archive::object_reference_type const &,int){}
- void save_override(archive::tracking_type const &,int){}
- void save_override(archive::class_name_type const &,int){}
- void save_override(serialization::collection_size_type const &,int){}
- template<class Sequence>
- void save_override(type_selection<Sequence> const &,int){}
-
- template<class T>
- void save_override(T const &t,int i){
- this->f(t);
- this->save_override(t,i,mpl::bool_<serialization::is_bitwise_serializable<T>::value || boost::is_empty<T>::value>());
- }
-private:
- template<class T>
- void save_override(T &,int,mpl::true_ bitwise_or_empty){}
- template<class T>
- void save_override(T &t,int i,mpl::false_ bitwise_or_empty){
- base_type::save_override(t,i);
- }
-
- friend class boost::archive::save_access;
- template<class T>
- void save(T const &){
- BOOST_STATIC_ASSERT(serialization::implementation_level<T>::value == serialization::primitive_type);
- }
- UnaryFunction f;
-};
-
-template<class BaseArchive>
-class serialization_oarchive : public archive::basic_binary_oarchive<serialization_oarchive<BaseArchive> >{
- typedef archive::basic_binary_oarchive<serialization_oarchive<BaseArchive> > base_type;
-public:
- explicit serialization_oarchive(BaseArchive &ar)
- : base_type(archive::no_header | archive::no_codecvt)
- , base(ar){}
- void save_binary(void const *data,std::size_t size){
- this->base.save_binary(data,size);
- }
- template<class T>
- void save_override(T const &t,int i){
- this->save_override(t,i,mpl::bool_<serialization::is_bitwise_serializable<T>::value || is_empty<T>::value>());
- }
- template<class Sequence>
- void save_override(type_selection<Sequence> const &type,int){
- this->base << type;
- }
-private:
- template<class T>
- void save_override(T const &t,int,mpl::true_ bitwise){
- this->base << t;
- }
- template<class T>
- void save_override(T const &t,int i,mpl::false_ bitwise){
- base_type::save_override(t,i);
- }
- friend class boost::archive::save_access;
- template<class T>
- void save(T const &){}
-
- BaseArchive &base;
-};
-
-template<class BaseArchive>
-class serialization_iarchive : public archive::basic_binary_iarchive<serialization_iarchive<BaseArchive> >{
- typedef archive::basic_binary_iarchive<serialization_iarchive<BaseArchive> > base_type;
-public:
- explicit serialization_iarchive(BaseArchive &ar)
- : base_type(archive::no_header | archive::no_codecvt)
- , base(ar){}
- void load_binary(void *data,std::size_t size){
- this->base.load_binary(data,size);
- }
- template<class T>
- void load_override(T &t,int i){
- this->load_override(t,i,mpl::bool_<serialization::is_bitwise_serializable<T>::value || is_empty<T>::value>());
- }
- template<class Sequence>
- void load_override(type_selection<Sequence> &type,int){
- this->base >> type;
- }
-private:
- template<class T>
- void load_override(T &t,int,mpl::true_ bitwise){
- this->base >> t;
- }
- template<class T>
- void load_override(T &t,int i,mpl::false_ bitwise){
- base_type::load_override(t,i);
- }
- friend class boost::archive::load_access;
- template<class T>
- void load(T const &){}
-
- BaseArchive &base;
-};
-
-#endif
-
-
-template<class BaseArchive>
-class save_archive{
-public:
- typedef mpl::true_ is_saving;
- typedef mpl::false_ is_loading;
- explicit save_archive(BaseArchive &ar) : base(ar){}
- template<class Size>
- void save_binary(void const *data,Size size){
- this->base.save_binary(data,size);
- }
- template<class T>
- save_archive &operator<<(T const &t){
- this->save(t,is_empty<T>(),serialization::is_bitwise_serializable<T>());
- return *this;
- }
- template<class T>
- save_archive &operator&(T const &t){
- return this->operator<<(t);
- }
-private:
- template<class T>
- void save(T const &t,mpl::false_,mpl::true_ bitwise){
- this->base << t;
- }
- template<class T>
- void save(T const &t,mpl::false_,mpl::false_ bitwise){
- transact::object_access::save(this->base,t);
- }
- template<class T,bool Bitwise>
- void save(T const &,mpl::true_ empty,mpl::bool_<Bitwise>){}
-
- template<class Sequence>
- void save(type_selection<Sequence> const &type,mpl::false_,mpl::false_){
- this->base << type;
- }
- void save(std::string const &s,mpl::false_,mpl::false_ bitwise){
- std::size_t const size=s.size();
- *this << size;
- this->save_binary(s.data(),size);
- }
- void save(std::wstring const &s,mpl::false_,mpl::false_ bitwise){
- std::size_t const size=s.size();
- *this << size;
- this->save_binary(s.data(),size * sizeof(wchar_t));
- }
- void save(char const *s,mpl::false_,mpl::false_ bitwise){
- std::size_t const size=std::strlen(s);
- *this << size;
- this->save_binary(s,size);
- }
- void save(wchar_t const *s,mpl::false_,mpl::false_ bitwise){
- std::size_t const size=std::wcslen(s);
- *this << size;
- this->save_binary(s,size*sizeof(wchar_t));
- }
-
- BaseArchive &base;
-};
-
-template<class BaseArchive>
-class load_archive{
-public:
- typedef mpl::false_ is_saving;
- typedef mpl::true_ is_loading;
- explicit load_archive(BaseArchive &ar) : base(ar){}
- template<class Size>
- void load_binary(void *data,Size size){
- this->base.load_binary(data,size);
- }
- template<class T>
- load_archive &operator>>(T &t){
- this->load(t,is_empty<T>(),serialization::is_bitwise_serializable<T>());
- return *this;
- }
- template<class T>
- load_archive &operator&(T &t){
- return this->operator>>(t);
- }
-private:
- template<class T>
- void load(T &t,mpl::false_,mpl::true_ bitwise){
- this->base >> t;
- }
- template<class T>
- void load(T &t,mpl::false_,mpl::false_ bitwise){
- transact::object_access::load(this->base,t);
- }
- template<class T,bool Bitwise>
- void load(T &,mpl::true_ empty,mpl::bool_<Bitwise>){}
-
- template<class Sequence>
- void load(type_selection<Sequence> &type,mpl::false_,mpl::false_){
- this->base >> type;
- }
- void load(std::string &s,mpl::false_,mpl::false_ bitwise){
- std::size_t size;
- *this >> size;
- s.resize(size);
- this->load_binary(&*s.begin(),size); //boost.serialization does the same thing
- }
- void load(std::wstring &s,mpl::false_,mpl::false_ bitwise){
- std::size_t size;
- *this >> size;
- s.resize(size);
- this->load_binary(const_cast<wchar_t *>(s.data()),size*sizeof(wchar_t)); //boost.serialization does the same thing
- }
- void load(char *s,mpl::false_,mpl::false_ bitwise){
- std::size_t size;
- *this >> size;
- this->load_binary(s,size);
- s[size]=0;
- }
- void load(wchar_t *s,mpl::false_,mpl::false_ bitwise){
- std::size_t size;
- *this >> size;
- this->load_binary(s,size*sizeof(wchar_t));
- s[size]=0;
- }
-
- BaseArchive &base;
-};
-
-template<class OutputIterator>
-class memory_oarchive : public char_oarchive<OutputIterator>{
- typedef char_oarchive<OutputIterator> base_type;
-public:
- explicit memory_oarchive(OutputIterator const &out) : base_type(out){}
- template<class Sequence>
- memory_oarchive &operator<<(type_selection<Sequence> const &type){
- unsigned char typenr=type.which();
- return *this << typenr;
- }
- template<class T>
- memory_oarchive &operator<<(T const &t){
- base_type::operator<<(t);
- return *this;
- }
- template<class T>
- memory_oarchive &operator&(T const &t){
- return this->operator<<(t);
- }
-};
-
-template<class InputIterator>
-class memory_iarchive : public char_iarchive<InputIterator>{
- typedef char_iarchive<InputIterator> base_type;
-public:
- explicit memory_iarchive(InputIterator const &begin,InputIterator const &end) : base_type(begin,end){}
- template<class Sequence>
- memory_iarchive &operator>>(type_selection<Sequence> &type){
- unsigned char typenr;
- *this >> typenr;
- type.reset(typenr);
- return *this;
- }
- template<class T>
- memory_iarchive &operator>>(T &t){
- base_type::operator>>(t);
- return *this;
- }
- template<class T>
- memory_iarchive &operator&(T const &t){
- return this->operator>>(t);
- }
-};
-
-template<class InputIterator>
-class compare_archive{
-public:
- typedef mpl::true_ is_saving;
- typedef mpl::false_ is_loading;
- explicit compare_archive(InputIterator const &begin,InputIterator const &end)
- : in(begin),end(end)
- , equal_(true){}
- template<class Size>
- void save_binary(void const *vdata,Size size){
- char const *data=static_cast<char const *>(vdata);
- this->save_binary(
- data,
- size,
- typename std::iterator_traits<InputIterator>::iterator_category(),
- typename continuous_values<InputIterator>::type()
- );
- }
- template<class T>
- compare_archive &operator<<(T const &t){
- BOOST_STATIC_ASSERT(serialization::is_bitwise_serializable<T>::value);
- this->save_binary(&t,mpl::size_t<sizeof(T)>());
- return *this;
- }
- template<class Sequence>
- compare_archive &operator<<(type_selection<Sequence> const &type){
- unsigned char typenr;
- if(this->in == this->end) this->unequal();
- else{
- typenr=*this->in++;
- if(typenr != type.which()) this->unequal();
- }
- return *this;
- }
- template<class T>
- compare_archive &operator&(T const &t){
- return this->operator<<(t);
- }
- bool equal() const{ return this->equal_; }
-private:
- BOOST_STATIC_ASSERT((is_same<typename std::iterator_traits<InputIterator>::value_type,char>::value));
- template<class Size>
- void save_binary(char const *data,Size size,std::random_access_iterator_tag,mpl::true_ contvals){
- if((this->in + size > this->end) || (std::memcmp(data,&*this->in,size) != 0)) this->unequal();
- else this->in+=size;
- }
- template<class Size>
- void save_binary(char const *data,Size size,std::random_access_iterator_tag,mpl::false_ contvals){
- if((this->in + size > this->end) || (!std::equal(data,data+size,this->in))) this->unequal();
- else this->in+=size;
- }
- template<class Size,class Category>
- void save_binary(char const *data,Size size,Category,mpl::false_ contvals){
- for(std::size_t c=0;c<size;++c){
- if((this->in == this->end) || (*data++ != *this->in++)){
- this->unequal();
- break;
- }
- }
- }
-
- void unequal(){
- this->equal_=false;
- this->in=this->end;
- }
-
- InputIterator in;
- InputIterator end;
- bool equal_;
-};
-
+}
+}
 
+#include <boost/transact/archive.hpp>
 
+namespace boost{
+namespace transact{
+namespace detail{
 
 template<class T>
-struct serialization_required;
+struct boost_serialization_required;
 
-template<class UnaryFunction,class T>
-void apply(UnaryFunction const &f,T const &t,deep_tag tag){
+template<class Archive,class T>
+void apply(Archive const &ar,T const &t,deep_tag){
 #ifdef NO_BOOST_SERIALIZATION
- sizeof(serialization_required<T>);
+ sizeof(boost_serialization_required<T>);
 #else
- detail::apply_archive<UnaryFunction> ar(f);
- serialization::serialize_adl(ar,const_cast<T &>(t),serialization::version<T>::value);
+ serialization::serialize_adl(const_cast<Archive &>(ar).serialization_archive(),const_cast<T &>(t),serialization::version<T>::value);
 #endif
 }
 
 template<class UnaryFunction,class T>
 void apply_(UnaryFunction const &f,T const &t,deep_tag tag){
+#if __GNUC__ && ((__GNUC__== 4 && __GNUC_MINOR__ <= 4) || __GNUC__ < 4)
+ //GCC <= 4.4 looks up ADL names in namespaces that are only used as template arguments,
+ //which causes a conflict with boost::mpl::apply.
+ //apply is an optimization only, ignore user-supplied apply functions and use serialization instead:
+ detail::apply(f,t,tag);
+#else
     apply(f,t,tag);
+#endif
 }
 template<class UnaryFunction,class T>
 void apply_adl(UnaryFunction const &f,T const &t){
@@ -582,11 +240,9 @@
 template<class Archive,class T>
 void serialize(Archive &ar,T &t,constructed_tag){
 #ifdef NO_BOOST_SERIALIZATION
- sizeof(serialization_required<T>);
+ sizeof(boost_serialization_required<T>);
 #else
- BOOST_STATIC_ASSERT(Archive::is_saving::value);
- detail::serialization_oarchive<Archive> serar(ar);
- serialization::serialize_adl(serar,t,serialization::version<T>::value);
+ serialization::serialize_adl(ar.serialization_archive(),t,serialization::version<T>::value);
 #endif
 }
 
@@ -597,15 +253,14 @@
 
 template<class Archive,class T>
 void serialize(Archive volatile &var,T &t,unconstructed_tag tag){
- Archive &ar=(Archive &)var;
 #ifdef NO_BOOST_SERIALIZATION
- sizeof(serialization_required<T>);
+ sizeof(boost_serialization_required<T>);
 #else
+ Archive &ar=(Archive &)var;
     BOOST_STATIC_ASSERT(Archive::is_loading::value);
- detail::serialization_iarchive<Archive> serar(ar);
- serialization::load_construct_data_adl(serar,&t,serialization::version<T>::value);
+ serialization::load_construct_data_adl(ar.serialization_archive(),&t,serialization::version<T>::value);
     tag.constructed()=true;
- serialization::serialize_adl(serar,t,serialization::version<T>::value);
+ serialization::serialize_adl(ar.serialization_archive(),t,serialization::version<T>::value);
 #endif
 }
 
@@ -749,27 +404,29 @@
 }
 
 template<class UnaryFunction,class T>
-void object_access::apply(UnaryFunction const &f,T const &t,mpl::false_ empty_or_bitwise){
- detail::apply_adl(f,t);
+void object_access::apply(UnaryFunction const &f,T const &t,mpl::false_ empty,mpl::false_ bitwise){
+ detail::apply_archive<UnaryFunction> ar(f);
+ detail::apply_adl(ar,t);
+}
+template<class UnaryFunction,class T>
+void object_access::apply(detail::apply_archive<UnaryFunction> const &ar,T const &t,mpl::false_ empty,mpl::false_ bitwise){
+ detail::apply_adl(ar,t);
 }
 
 template<class Archive,class T>
 void object_access::construct(Archive &ar,T *&t,mpl::false_ empty,mpl::false_ bitwise){
- detail::load_archive<Archive> loadar(ar);
- detail::construct_adl(loadar,t);
+ detail::construct_adl(ar,t);
 }
 
 
 template<class Archive,class T>
 void object_access::load(Archive &ar,T &t,mpl::false_ empty,mpl::false_ bitwise){
- detail::load_archive<Archive> loadar(ar);
- detail::load_adl(loadar,t);
+ detail::load_adl(ar,t);
 }
 
 template<class Archive,class T>
 void object_access::save(Archive &ar,T const &t,mpl::false_ empty,mpl::false_ bitwise){
- detail::save_archive<Archive> savear(ar);
- detail::save_adl(savear,t);
+ detail::save_adl(ar,t);
 }
 
 template<class T>

Modified: sandbox/transaction/boost/transact/resource_manager.hpp
==============================================================================
--- sandbox/transaction/boost/transact/resource_manager.hpp (original)
+++ sandbox/transaction/boost/transact/resource_manager.hpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -16,8 +16,11 @@
 namespace boost{
 namespace transact{
 
-struct transaction_restart_service_tag{};
+struct restart_transaction_service_tag{};
+struct finish_transaction_service_tag{};
 struct nested_transaction_service_tag{};
+struct distributed_transaction_service_tag{};
+
 
 namespace detail{
 

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-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -9,7 +9,6 @@
 #define BOOST_TRANSACT_SIMPLE_TRANSACTION_MANAGER_HEADER_HPP
 
 #include <boost/mpl/map.hpp>
-#include <boost/mpl/contains.hpp>
 #include <boost/mpl/bool.hpp>
 #include <boost/assert.hpp>
 #include <boost/static_assert.hpp>
@@ -21,11 +20,118 @@
 #include <boost/transact/exception.hpp>
 #include <boost/noncopyable.hpp>
 #include <boost/transact/detail/static_tss.hpp>
+#include <boost/transact/detail/transaction_manager.hpp>
 #include <boost/transact/resource_manager.hpp>
 
 namespace boost{
 namespace transact{
 
+template<class Resource,bool FlatNested=false,bool Threads=true,class ResourceTag=default_tag>
+class simple_transaction_manager;
+
+namespace detail{
+
+namespace simple_transaction_manager{
+
+template<class Resource>
+class resource_transactions : noncopyable{
+public:
+ resource_transactions() : rolled_back_(false){}
+ bool rolled_back() const{ return this->rolled_back_; }
+ void rolled_back(bool rb){ this->rolled_back_=rb; }
+ optional<typename Resource::transaction> &get(){
+ return this->tx;
+ }
+private:
+ optional<typename Resource::transaction> tx;
+ bool rolled_back_;
+};
+
+template<class Tag,class Resource>
+class transaction : noncopyable{
+public:
+ template<class T>
+ transaction(T const &c) : parent_(c.parent){
+ resources &ress=c.resources;
+ this->construct(ress,typename T::flat());
+ }
+private:
+ typedef detail::tag_resource_pair<Tag,Resource> resources;
+//public:
+ template<class,bool,bool,class> friend class transact::simple_transaction_manager;
+
+ typename Resource::transaction &resource_transaction(resources &ress,Tag const &tag){
+ Resource &res=ress.get(tag);
+ optional<typename Resource::transaction> &rtx=this->rtxs->get();
+ BOOST_ASSERT(rtx);
+ return *rtx;
+ }
+ void commit(resources &ress){
+ if(this->flat_nested()){
+ if(this->rtxs->rolled_back()) throw no_transaction();
+ return; // flat nested transaction commit is a no-op
+ }else{
+ if(!ress.empty()){
+ BOOST_ASSERT(this->rtxs_storage && this->rtxs == &*this->rtxs_storage);
+ finisher finish;
+ BOOST_VERIFY( ! finish(ress.tag(),ress.get(ress.tag()),this->rtxs_storage->get(),false));
+ committer commit;
+ commit(ress.tag(),ress.get(ress.tag()),this->rtxs_storage->get());
+ }
+ }
+ }
+
+ void rollback(resources &ress){
+ if(!this->rtxs->rolled_back()){ //a flat nested transaction might have rolled back before
+ this->rtxs->rolled_back(true);
+ rollbacker rollback; rollback(ress.tag(),ress.get(ress.tag()),this->rtxs->get());
+ }
+ }
+ void restart(resources &ress){
+ if(this->flat_nested()) throw unsupported_operation();
+ BOOST_ASSERT(this->rtxs_storage);
+ beginner<transaction,resources> begin(this->parent(),ress);
+ restarter<beginner<transaction,resources> > restart(begin);
+ restart(ress.tag(),ress.get(ress.tag()),this->rtxs_storage->get());
+ }
+
+ transaction *parent() const{ return this->parent_; }
+private:
+ void construct(resources &ress,mpl::true_ flat){
+ if(this->parent()){
+ this->rtxs=this->parent()->rtxs;
+ BOOST_ASSERT(this->rtxs);
+ if(this->rtxs->rolled_back()){
+ //user tried to begin a transaction in a closed transaction scope that was not restarted even though
+ //an open transaction inside it was rolled back:
+ throw no_transaction();
+ }
+ }else this->construct_closed(ress);
+ }
+ void construct(resources &ress,mpl::false_ flat){
+ this->construct_closed(ress);
+ }
+ void construct_closed(resources &ress){
+ this->rtxs_storage=in_place();
+ this->rtxs=&*this->rtxs_storage;
+ beginner<transaction,resources> begin(this->parent(),ress);
+ begin(ress.tag(),ress.get(ress.tag()),this->rtxs_storage->get());
+ }
+ bool flat_nested() const{
+ return this->parent() && this->parent()->rtxs == this->rtxs;
+ }
+
+ resource_transactions<Resource> *rtxs; // never 0. == *rtxs_storage for closed transactions, == *parent->parent->...->rtxs_storage for open transactions.
+ transaction *parent_;
+ optional<resource_transactions<Resource> > rtxs_storage;
+};
+
+}
+
+}
+
+
+
 /// Model of TransactionManager. Only members that are not part of that concept are documented here.
 ///
 /// Equivalent to <tt>basic_transaction_manager<mpl::vector<Resource>,Threads></tt>.
@@ -36,50 +142,31 @@
 /// \li \c Threads \c true if multiple threads are used to access this transaction manager.
 /// \li \c ResourceTag The tag that identifies the Resource
 // \brief A transaction manager that only supports one resource manager.
-template<class Resource,bool FlatNested=false,bool Threads=true,class ResourceTag=default_tag>
+template<class Resource,bool FlatNested,bool Threads,class ResourceTag>
 class simple_transaction_manager : noncopyable{
-public:
- class transaction;
     /// \cond
- friend class transaction;
 private:
- class transaction_construct_t{
- explicit transaction_construct_t(transaction *parent)
- : parent(parent){}
- friend class simple_transaction_manager;
- friend class transaction;
- transaction *parent;
+ struct detail{ //for QuickBook
+ typedef transact::detail::simple_transaction_manager::transaction<ResourceTag,Resource> transaction;
+ typedef transact::detail::tag_resource_pair<ResourceTag,Resource> resources_type;
+ class transaction_construct_t{
+ transaction_construct_t(resources_type &resources,transaction *parent)
+ : resources(resources),parent(parent){}
+ friend class simple_transaction_manager;
+ template<class,class> friend class transact::detail::simple_transaction_manager::transaction;
+ resources_type &resources;
+ transaction * const parent;
+ typedef mpl::bool_<FlatNested> flat; //TODO
+ };
     };
     struct currenttx_tag{};
     typedef transact::detail::static_thread_specific_ptr<
- transaction,
+ typename detail::transaction,
         currenttx_tag,
         Threads> currenttx;
-
- struct detail{ //for QuickBook
- typedef typename simple_transaction_manager::transaction_construct_t transaction_construct_t;
- typedef std::pair<ResourceTag,Resource &> *resource_iterator;
- };
-public:
- class transaction : noncopyable{
- public:
- explicit transaction(transaction_construct_t const &c)
- : rtx(0),rolled_back(false),parent(c.parent){
- simple_transaction_manager::begin_transaction(*this);
- }
- private:
- void reset(){
- this->rtx=0;
- this->rtx_storage=none;
- this->rolled_back=false;
- }
- friend class simple_transaction_manager;
- optional<typename Resource::transaction> rtx_storage;
- typename Resource::transaction *rtx; //if(FlatNested) == root transaction; else == &*rtx_storage
- bool rolled_back;
- transaction * const parent;
- };
     /// \endcond
+public:
+ typedef typename detail::transaction transaction;
     typedef mpl::map1<mpl::pair<ResourceTag,Resource> > resource_types;
 
     /// \brief Constructs a simple_transaction_manager
@@ -87,71 +174,48 @@
 
     /// TODO doc, not part of the concept
     static void connect_resource(Resource &newres,ResourceTag const &tag=ResourceTag()){
- if(res){
- if(tag_is_equal(tag)) throw resource_error();
- else throw unsupported_operation();
- }
- res=in_place(tag,boost::ref(newres));
+ resources_.connect(tag,newres);
     }
 
     /// TODO doc, not part of the concept
+ /// \pre No transactions must be active
     static void disconnect_resource(ResourceTag const &tag=ResourceTag()){
- if(res && tag_is_equal(tag)) res=none;
- else throw resource_error();
+ resources_.disconnect(tag);
     }
 
+ /// \pre A resource manager must be connected
     static Resource &resource(ResourceTag const &tag=ResourceTag()){
- if(res && tag_is_equal(tag)) return res->second;
- else throw resource_error();
+ return resources_.get(tag);
     }
 
- typedef typename detail::resource_iterator resource_iterator;
     template<class Tag>
- static std::pair<resource_iterator,resource_iterator> resources(){
- BOOST_STATIC_ASSERT((boost::is_same<Tag,ResourceTag>::value));
- if(res) return std::pair<resource_iterator,resource_iterator>(&*res,&*res + 1);
- else return std::pair<resource_iterator,resource_iterator>(0,0);
+ struct resource_iterator{
+ typedef typename detail::resources_type::template iterator<Tag>::type type;
+ };
+ template<class Tag>
+ static std::pair<typename resource_iterator<Tag>::type,typename resource_iterator<Tag>::type> resources(){
+ return resources_.template range<Tag>();
     }
 
     static typename Resource::transaction &
     resource_transaction(transaction &tx,ResourceTag const &tag=ResourceTag()){
- if(tx.rtx && tag_is_equal(tag)) return *tx.rtx;
- else throw resource_error();
+ return tx.resource_transaction(resources_,tag);
     }
 
+ /// \pre A resource manager must be connected
     static typename detail::transaction_construct_t begin_transaction(){
- return transaction_construct_t(currenttx::get());
+ return typename detail::transaction_construct_t(resources_,currenttx::get());
     }
-
     static void commit_transaction(transaction &tx){
         bind_transaction(tx);
- if(res){
- BOOST_ASSERT(tx.rtx);
- res->second.finish_transaction(*tx.rtx);
- res->second.commit_transaction(*tx.rtx);
- }
+ tx.commit(resources_);
     }
-
     static void rollback_transaction(transaction &tx){
- bind_transaction(tx);
- if(res){
- BOOST_ASSERT(tx.rtx);
- BOOST_ASSERT(FlatNested || !tx.rolled_back);
- if(!FlatNested || !tx.rolled_back){
- mark_rolled_back(tx);
- res->second.rollback_transaction(*tx.rtx);
- }
- }
+ tx.rollback(resources_);
     }
-
     static void restart_transaction(transaction &tx){
- if(res){
- BOOST_ASSERT(tx.rtx);
- if(FlatNested && tx.rtx != &*tx.rtx_storage) throw unsupported_operation();
- restart_transaction(tx,typename mpl::contains<typename Resource::services,transaction_restart_service_tag>::type());
- }
+ tx.restart(resources_);
     }
-
     static void bind_transaction(transaction &tx){
         currenttx::reset(&tx);
     }
@@ -161,65 +225,19 @@
     static transaction *current_transaction(){
         return currenttx::get();
     }
+ static transaction *parent_transaction(transaction &tx){
+ return tx.parent();
+ }
     /// \cond
 private:
- static void begin_transaction(transaction &tx){
- if(res){
- if(tx.parent){
- begin_nested_transaction(tx,mpl::bool_<FlatNested>(),typename has_service<Resource,nested_transaction_service_tag>::type());
- }else{
- tx.rtx_storage=in_place(res->second.begin_transaction());
- tx.rtx=&*tx.rtx_storage;
- }
- }
- }
- template<bool Service>
- static void begin_nested_transaction(transaction &tx,mpl::true_ flatnested,mpl::bool_<Service>){
- if(tx.parent->rtx) tx.rtx=tx.parent->rtx;
- else throw no_transaction();
- }
- static void begin_nested_transaction(transaction &tx,mpl::false_ flatnested,mpl::true_ service){
- BOOST_ASSERT(tx.parent->rtx);
- tx.rtx_storage=in_place(res->second.begin_nested_transaction(*tx.parent->rtx));
- tx.rtx=&*tx.rtx_storage;
- }
- static void begin_nested(transaction &,mpl::false_ flatnested,mpl::false_ service){
- throw unsupported_operation();
- }
-
- static void mark_rolled_back(transaction &tx){
- tx.rolled_back=true;
- if(FlatNested){
- for(transaction *current=tx.parent;current;current=current->parent){
- current->rolled_back=true;
- }
- }
- }
- static void restart_transaction(transaction &tx,mpl::true_ service){
- BOOST_ASSERT(res);
- res->second.restart_transaction(*tx.rtx);
- }
- static void restart_transaction(transaction &tx,mpl::false_ service){
- tx.reset();
- begin_transaction(tx);
- }
- static bool tag_is_equal(ResourceTag const &o){
- return tag_is_equal(o,boost::is_empty<ResourceTag>());
- }
- static bool tag_is_equal(ResourceTag const &,true_type empty){
- return true;
- }
- static bool tag_is_equal(ResourceTag const &o,false_type empty){
- BOOST_ASSERT(res);
- return res->first == o;
- }
-
- static optional<std::pair<ResourceTag,Resource &> > res;
+ typedef typename detail::resources_type resources_type;
+ static resources_type resources_;
     /// \endcond
 };
 
 template<class Resource,bool FlatNested,bool Threads,class ResourceTag>
-optional<std::pair<ResourceTag,Resource &> > simple_transaction_manager<Resource,FlatNested,Threads,ResourceTag>::res;
+typename simple_transaction_manager<Resource,FlatNested,Threads,ResourceTag>::resources_type
+simple_transaction_manager<Resource,FlatNested,Threads,ResourceTag>::resources_;
 
 
 }

Modified: sandbox/transaction/libs/transact/test/transaction_stack_unwind.cpp
==============================================================================
--- sandbox/transaction/libs/transact/test/transaction_stack_unwind.cpp (original)
+++ sandbox/transaction/libs/transact/test/transaction_stack_unwind.cpp 2010-05-30 20:44:15 EDT (Sun, 30 May 2010)
@@ -10,7 +10,7 @@
 #endif
 
 #include <boost/transact/simple_transaction_manager.hpp>
-#include <boost/mpl/empty_sequence.hpp>
+#include <boost/mpl/vector.hpp>
 #include <boost/test/minimal.hpp>
 
 using namespace boost;
@@ -18,12 +18,10 @@
 
 struct my_rm{
     typedef int transaction;
- typedef mpl::empty_sequence services;
- struct tag{};
- transaction begin_root_transaction(){ return 0; }
+ typedef mpl::vector<nested_transaction_service_tag> services;
+ transaction begin_transaction(){ return 0; }
     transaction begin_nested_transaction(transaction){ return 0; }
     void commit_transaction(transaction){}
- bool finish_transaction(transaction){ return false; }
     void rollback_transaction(transaction){}
 };
 
@@ -37,17 +35,17 @@
 int test(int contextnr){
     my_tm::transaction *txs[5];
     begin_transaction{
- txs[0]=&my_tm::current_transaction();
+ txs[0]=my_tm::current_transaction();
         begin_transaction{
- txs[1]=&my_tm::current_transaction();
+ txs[1]=my_tm::current_transaction();
             begin_transaction{
- txs[2]=&my_tm::current_transaction();
+ txs[2]=my_tm::current_transaction();
                 begin_transaction{
- txs[3]=&my_tm::current_transaction();
+ txs[3]=my_tm::current_transaction();
                     begin_transaction{
- txs[4]=&my_tm::current_transaction();
+ txs[4]=my_tm::current_transaction();
                         my_rm::transaction &rtx=my_tm::resource_transaction(*txs[contextnr]);
- throw resource_isolation_exception<my_rm>(rtx);
+ throw resource_isolation_exception<my_rm>(my_tm::resource(),rtx);
                     }retry{
                         return 4;
                     }end_retry;


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk