Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61877 - in sandbox/transaction/boost/transact: . detail
From: strasser_at_[hidden]
Date: 2010-05-09 09:55:38


Author: stefans
Date: 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
New Revision: 61877
URL: http://svn.boost.org/trac/boost/changeset/61877

Log:
 - removed TM::default_resource interface
 - object_access initial code
 - NestedTransactionService

only for simple_transaction_manager, TODO for basic_transaction_manager:
 - support for NestedTransactionService
 - flat nested transaction emulation
 - added TM::resources interface to iterate RMs
 - support for stateful tags
Added:
   sandbox/transaction/boost/transact/array_extension.hpp (contents, props changed)
   sandbox/transaction/boost/transact/char_archive.hpp (contents, props changed)
   sandbox/transaction/boost/transact/default_tag.hpp (contents, props changed)
   sandbox/transaction/boost/transact/object_access.hpp (contents, props changed)
   sandbox/transaction/boost/transact/type_selection.hpp (contents, props changed)
Text files modified:
   sandbox/transaction/boost/transact/basic_transaction.hpp | 27 +++---
   sandbox/transaction/boost/transact/basic_transaction_manager.hpp | 26 +----
   sandbox/transaction/boost/transact/detail/aligning_file.hpp | 12 +-
   sandbox/transaction/boost/transact/detail/buffering_file.hpp | 16 +--
   sandbox/transaction/boost/transact/detail/embedded_vector.hpp | 19 ++++
   sandbox/transaction/boost/transact/detail/filebuf_file.hpp | 18 +---
   sandbox/transaction/boost/transact/detail/sectorizing_file.hpp | 26 ++----
   sandbox/transaction/boost/transact/detail/syncing_file.hpp | 18 +---
   sandbox/transaction/boost/transact/exception.hpp | 103 +++++++++++++++++---------
   sandbox/transaction/boost/transact/log.hpp | 1
   sandbox/transaction/boost/transact/resource_manager.hpp | 31 ++++++++
   sandbox/transaction/boost/transact/simple_transaction_manager.hpp | 153 ++++++++++++++++++++++++++-------------
   12 files changed, 271 insertions(+), 179 deletions(-)

Added: sandbox/transaction/boost/transact/array_extension.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/array_extension.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -0,0 +1,75 @@
+// 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_ARRAY_EXTENSION_HPP
+#define BOOST_TRANSACT_ARRAY_EXTENSION_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <iterator>
+
+namespace boost{
+namespace transact{
+
+template<class T>
+struct array_extension : mpl::false_{};
+
+template<class T>
+struct continuous_values : mpl::false_{};
+
+template<class T>
+struct continuous_values<T *> : mpl::true_{};
+
+
+template<typename Vector>
+class vector_back_insert_iterator
+ : public std::iterator<std::output_iterator_tag,void,void,void,void>{
+public:
+ typedef Vector container_type;
+ explicit vector_back_insert_iterator(Vector &vec) : vec(vec){}
+ vector_back_insert_iterator &operator=(typename Vector::const_reference v){
+ this->vec.push_back(v);
+ return *this;
+ }
+ template<class Size>
+ vector_back_insert_iterator &assign(typename Vector::const_pointer data,Size size){
+ this->assign(data,size,typename array_extension<Vector>::type(),typename is_pod<typename Vector::value_type>::type());
+ return *this;
+ }
+ vector_back_insert_iterator &operator*(){ return *this; }
+ vector_back_insert_iterator &operator++(){ return *this; }
+ vector_back_insert_iterator operator++(int){ return *this; }
+private:
+ template<class Size,bool Pod>
+ void assign(typename Vector::const_pointer data,Size size,mpl::true_ array,mpl::bool_<Pod>){
+ this->vec.push_back(data,size);
+ }
+ template<class Size>
+ void assign(typename Vector::const_pointer data,Size size,mpl::false_ array,mpl::true_ pod){
+ std::size_t const oldsize=this->vec.size();
+ this->vec.resize(oldsize + size);
+ std::memcpy(&this->vec[oldsize],data,size * sizeof(typename Vector::value_type));
+ }
+ template<class Size>
+ void assign(typename Vector::const_pointer data,Size size,mpl::false_ array,mpl::false_ pod){
+ std::size_t const oldsize=this->vec.size();
+ this->vec.resize(oldsize + size);
+ std::copy(data,data+size,this->vec.begin()+oldsize);
+ }
+
+ Vector &vec;
+};
+
+
+template<class Vector>
+struct array_extension<vector_back_insert_iterator<Vector> > : mpl::true_{};
+
+
+
+}
+}
+
+
+
+#endif

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -33,7 +33,7 @@
     /// thrown by resource managers beginning local transactions.
     /// \brief Constructs a basic_transaction, beginning a new transaction scope
     explicit basic_transaction()
- : parent(TxMgr::has_current_transaction() ? &TxMgr::current_transaction() : 0)
+ : parent(TxMgr::current_transaction())
         , tx(TxMgr::begin_transaction())
         , done(false){
         TxMgr::bind_transaction(this->tx);
@@ -62,7 +62,7 @@
         else TxMgr::unbind_transaction();
     }
 
- /// Throws: \c isolation_exception, \c io_failure, \c thread_resource_error,
+ /// Throws: \c no_transaction_manager, \c isolation_exception, \c io_failure, \c thread_resource_error,
     /// resource-specific exceptions thrown by resource managers committing local
     /// transactions.
     /// \brief Commits the transaction.
@@ -71,7 +71,7 @@
         TxMgr::commit_transaction(this->tx);
     }
 
- /// Throws: \c io_failure, \c thread_resource_error, resource-specific exceptions
+ /// Throws: \c no_transaction_manager, \c io_failure, \c thread_resource_error, resource-specific exceptions
     /// thrown by resource managers rolling back transactions.
     /// \brief Unwinds all changes made during this transaction.
     void rollback(){
@@ -79,6 +79,15 @@
         TxMgr::rollback_transaction(this->tx);
     }
 
+ /// Equivalent to rolling back the transaction and beginning a new one.
+ /// Throws: \c no_transaction_manager, \c io_failure, \c thread_resource_error,
+ /// resource-specific exceptions thrown by resource managers restarting transactions.
+ /// \brief Restarts the transactions
+ void restart(){
+ TxMgr::restart_transaction(this->tx);
+ this->done=false;
+ }
+
     /// Throws: thread_resource_error
     /// \brief Binds the current thread to this transaction
     void bind(){
@@ -93,11 +102,6 @@
             TxMgr::unbind_transaction();
         }
     }
-
- void restart(){
- TxMgr::restart_transaction(this->tx);
- }
-
     /// \cond
 private:
     typename TxMgr::transaction *parent;
@@ -152,6 +156,7 @@
                 break; \
             }catch(boost::transact::isolation_exception &___i){ \
                 ___i.unwind<TXMGR>(); \
+ ___tx.restart(); \
                 do{ \
                     ___control=1; \
                     if(false);else
@@ -160,9 +165,8 @@
                     ___control=0; \
                     break; \
                 }while((___control=2),false); \
+ BOOST_ASSERT(___control == 0); \
             } \
- BOOST_ASSERT(___control == 0); \
- ___tx.restart(); \
         }; \
         BOOST_ASSERT(___control == 0); \
     }void()
@@ -171,9 +175,8 @@
                     ___control=0; \
                     break; \
                 }while((___control=2),false); \
+ if(___control != 0) break; \
             } \
- if(___control != 0) break; \
- ___tx.restart(); \
         }; \
         if(___control != 0){ \
             if(___control==1) break; \

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -23,16 +23,17 @@
 #include <boost/mpl/contains.hpp>
 #include <boost/mpl/insert.hpp>
 #include <boost/mpl/empty.hpp>
-#include <boost/fusion/include/mpl.hpp>
-#include <boost/fusion/include/at.hpp>
-#include <boost/fusion/include/pair.hpp>
-#include <boost/fusion/include/as_map.hpp>
-#include <boost/fusion/include/at_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/transact/detail/mutex.hpp>
 #include <boost/transact/exception.hpp>
 #include <boost/transact/detail/static_tss.hpp>
 #include <boost/transact/resource_manager.hpp>
 
+//TODO: TransactionManager::resources, nested transaction emulation, stateful tags
 
 namespace boost{
 namespace transact{
@@ -45,7 +46,7 @@
 };
 
 template<class State,class F>
-struct runtime_folder{
+struct runtime_folder{ //TODO mit fusion::fold austauschen
     explicit runtime_folder(State &state,F &f)
         : state(state),f(f){}
     template<class U>
@@ -133,15 +134,6 @@
         struct resource_type{
             typedef typename basic_transaction_manager::template resource_type<Tag>::type type;
         };
- template<class ServiceTag>
- struct default_resource{
- typedef typename mpl::deref<
- typename mpl::find_if<
- Resources,
- mpl::contains<get_services<mpl::_1>,ServiceTag>
- >::type
- >::type::tag type;
- };
     };
 
     /// \endcond
@@ -179,10 +171,6 @@
     /// \endcond
     };
     typedef Resources resource_types;
- template<class ServiceTag>
- struct default_resource{
- typedef typename detail::template default_resource<ServiceTag>::type type;
- };
 
     /// A basic_transaction_manager constructed using this constructor
     /// is not able to commit transactions that involve two or more persistent

Added: sandbox/transaction/boost/transact/char_archive.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/char_archive.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -0,0 +1,116 @@
+// 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_CHAR_ARCHIVE_HPP
+#define BOOST_TRANSACT_CHAR_ARCHIVE_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/size_t.hpp>
+#include <boost/serialization/is_bitwise_serializable.hpp>
+#include <boost/archive/archive_exception.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/transact/array_extension.hpp>
+#include <algorithm>
+#include <iterator>
+#include <typeinfo>
+#include <cstring>
+
+namespace boost{
+namespace transact{
+
+template<class OutputIterator>
+class char_oarchive{
+public:
+ typedef mpl::true_ is_saving;
+ typedef mpl::false_ is_loading;
+ explicit 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());
+ }
+ template<class T>
+ char_oarchive &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 T>
+ char_oarchive &operator&(T const &t){
+ return this->operator<<(t);
+ }
+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 InputIterator>
+class char_iarchive{
+public:
+ typedef mpl::false_ is_saving;
+ typedef mpl::true_ is_loading;
+ //TODO optimization: array extract extension
+ char_iarchive(InputIterator const &begin,InputIterator const &end)
+ : in(begin), end(end){}
+ 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()
+ );
+ }
+ template<class T>
+ char_iarchive &operator >>(T &t){
+ BOOST_STATIC_ASSERT(serialization::is_bitwise_serializable<T>::value);
+ this->load_binary(&t,mpl::size_t<sizeof(T)>());
+ return *this;
+ }
+ template<class T>
+ char_iarchive &operator &(T &t){
+ return this->operator>>(t);
+ }
+private:
+ BOOST_STATIC_ASSERT((is_same<typename std::iterator_traits<InputIterator>::value_type,char>::value));
+ template<class Size>
+ void load_binary(char *data,Size size,std::random_access_iterator_tag,mpl::true_ contvals){
+ if(this->in + size > this->end) 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(this->in + size > this->end) 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;
+};
+
+
+}
+}
+
+
+#endif

Added: sandbox/transaction/boost/transact/default_tag.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/default_tag.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -0,0 +1,19 @@
+// Copyright Stefan Strasser 2010.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_TRANSACT_DEFAULT_TAG_HPP
+#define BOOST_TRANSACT_DEFAULT_TAG_HPP
+
+namespace boost{
+namespace transact{
+
+struct default_tag{};
+
+}
+}
+
+
+#endif

Modified: sandbox/transaction/boost/transact/detail/aligning_file.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/aligning_file.hpp (original)
+++ sandbox/transaction/boost/transact/detail/aligning_file.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -41,11 +41,11 @@
     explicit aligning_seq_ofile(std::string const &name)
         : base(name)
         , sectors(0){}
- void save_binary(void const *data,mpl::size_t<sector_size> size){
+ void write(void const *data,mpl::size_t<sector_size> size){
         if(this->sectors < max_sectors){
             std::memcpy(this->buffer + this->sectors * sector_size,data,size);
             ++this->sectors;
- }else this->save_overflow(data);
+ }else this->write_overflow(data);
     }
     size_type position() const{
         if(this->sectors <= max_sectors) return this->base.position() + this->sectors * sector_size;
@@ -74,19 +74,19 @@
         }
     }
 private:
- void save_overflow(void const *data){
+ void write_overflow(void const *data){
         BOOST_ASSERT(this->sectors >= max_sectors);
         if(this->sectors == max_sectors){
             this->align(max_alignment);
             this->flush_buffer();
             this->sectors=max_sectors+1;
         }
- this->base.save_binary(data,sector_size);
+ this->base.write(data,sector_size);
     }
 
     void flush_buffer(){
         if(this->sectors > 0 && this->sectors <= max_sectors){
- this->base.save_binary(this->buffer,this->sectors * sector_size);
+ this->base.write(this->buffer,this->sectors * sector_size);
         }
     }
     void align(std::size_t alignment){
@@ -95,7 +95,7 @@
         if(mod != 0){
             std::size_t write=alignment - mod;
             BOOST_ASSERT(write <= empty_sectors_t::size && write % sector_size == 0);
- this->base.save_binary(empty_sectors.data,write);
+ this->base.write(empty_sectors.data,write);
             this->base.flush();
             //this sync is unnecessary from a data-consistency viewpoint.
             //but it is required to keep linux is sequential writing.

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -24,15 +24,11 @@
         : base(name)
         , size(0){}
     template<class Size>
- void save_binary(void const *data,Size s){
+ void write(void const *data,Size s){
         if(this->size + s <= Capacity){
             std::memcpy(this->buffer+this->size,data,s);
             this->size+=s;
- }else this->save_overflow(data,s);
- }
- template<class T>
- void save(T const &t){
- this->save_binary(&t,mpl::size_t<sizeof(T)>());
+ }else this->write_overflow(data,s);
     }
     size_type position() const{
         return this->base.position() + this->size;
@@ -55,21 +51,21 @@
         }
     }
 private:
- void save_overflow(void const *data,std::size_t s){
+ void write_overflow(void const *data,std::size_t s){
         BOOST_ASSERT(this->size + s > Capacity);
         if(this->size == 0){
- this->base.save_binary(data,s);
+ this->base.write(data,s);
         }else{
             std::size_t write=Capacity - this->size;
             std::memcpy(this->buffer+this->size,data,write);
             this->size=Capacity;
             this->flush_buffer();
- this->save_binary(static_cast<char const *>(data)+write,s-write);
+ this->write(static_cast<char const *>(data)+write,s-write);
         }
     }
     void flush_buffer(){
         if(this->size > 0){
- this->base.save_binary(this->buffer,this->size);
+ this->base.write(this->buffer,this->size);
             this->size=0;
         }
     }

Modified: sandbox/transaction/boost/transact/detail/embedded_vector.hpp
==============================================================================
--- sandbox/transaction/boost/transact/detail/embedded_vector.hpp (original)
+++ sandbox/transaction/boost/transact/detail/embedded_vector.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -1,3 +1,9 @@
+// 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_EMBEDDED_VECTOR_HEADER_HPP
 #define BOOST_TRANSACT_DETAIL_EMBEDDED_VECTOR_HEADER_HPP
 
@@ -6,6 +12,11 @@
 #include <cstring>
 #include <boost/utility/in_place_factory.hpp>
 #include <boost/type_traits/is_pod.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/size_t.hpp>
+#include <boost/assert.hpp>
+#include <boost/transact/array_extension.hpp>
+
 
 namespace boost{
 namespace transact{
@@ -16,7 +27,7 @@
 public:
     typedef T &reference;
     typedef T const &const_reference;
- typedef T *iterator;
+ typedef T *iterator; //continuous values
     typedef T const *const_iterator;
     typedef std::size_t size_type;
     typedef std::ptrdiff_t difference_type;
@@ -43,9 +54,7 @@
             }
         }else BOOST_ASSERT(this->begin() == this->emb_data());
     }
-
     embedded_vector &operator=(embedded_vector const &);
-
     iterator begin(){ return this->begin_; }
     const_iterator begin() const{ return this->begin_; }
     iterator end(){ return this->end_; }
@@ -232,6 +241,10 @@
 
 
 }
+
+template<class T,std::size_t EmbeddedSize,bool Expand>
+struct array_extension<detail::embedded_vector<T,EmbeddedSize,Expand> > : mpl::true_{};
+
 }
 }
 

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -23,23 +23,19 @@
 
 class filebuf_seq_ofile{
 public:
- typedef unsigned long long size_type;
+ typedef unsigned int size_type;
     explicit filebuf_seq_ofile(std::string const &name) : pos(0){
         if(!this->buf.open(name.c_str(),std::ios::out | std::ios::binary)) throw io_failure();
     }
- void save_binary(void const *data,mpl::size_t<1>){
+ void write(void const *data,mpl::size_t<1>){
         if(this->buf.sputc(*static_cast<char const *>(data)) == EOF) throw io_failure();
         ++this->pos;
     }
- void save_binary(void const *data,std::size_t size){
+ void write(void const *data,std::size_t size){
         std::streamsize ret=this->buf.sputn(static_cast<char const *>(data),std::streamsize(size));
         this->pos+=ret;
         if(ret != std::streamsize(size)) throw io_failure();
     }
- template<class T>
- void save(T const &t){
- this->save_binary(&t,mpl::size_t<sizeof(T)>());
- }
     size_type position() const{ return this->pos; }
     void flush(){
         if(this->buf.pubsync() != 0) throw io_failure();
@@ -58,14 +54,14 @@
     explicit filebuf_seq_ifile(std::string const &name) : pos(0){
         if(!this->buf.open(name.c_str(),std::ios::in | std::ios::binary)) throw io_failure();
     }
- void load_binary(void *dataptr,mpl::size_t<1>){
+ void read(void *dataptr,mpl::size_t<1>){
         char &data=*static_cast<char *>(dataptr);
         int ret=this->buf.sbumpc();
         if(ret == EOF) throw eof_exception();
         ++this->pos;
         data=ret;
     }
- void load_binary(void *data,std::size_t size){
+ void read(void *data,std::size_t size){
         std::streamsize ret=this->buf.sgetn(static_cast<char *>(data),std::streamsize(size));
         this->pos+=ret;
         if(ret != std::streamsize(size)){
@@ -73,10 +69,6 @@
             else throw io_failure();
         }
     }
- template<class T>
- void load(T &t){
- this->load_binary(&t,mpl::size_t<sizeof(T)>());
- }
     size_type position() const{ return this->pos; }
 private:
     std::filebuf buf;

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -24,15 +24,11 @@
         : base(name)
         , size(0){}
     template<class Size>
- void save_binary(void const *data,Size s){
+ void write(void const *data,Size s){
         if(this->size + s <= max_size){
             std::memcpy(this->buffer(this->size),data,s);
             this->size+=s;
- }else this->save_overflow(data,s);
- }
- template<class T>
- void save(T const &t){
- this->save_binary(&t,mpl::size_t<sizeof(T)>());
+ }else this->write_overflow(data,s);
     }
     size_type position() const{
         return this->base.position() + this->size + 1;
@@ -57,7 +53,7 @@
     static std::size_t const sector_size=512;
     static std::size_t const max_size=sector_size-2;
 
- void save_overflow(void const *data,std::size_t s){
+ void write_overflow(void const *data,std::size_t s){
         BOOST_ASSERT(this->size + s > max_size);
 
         std::size_t write=max_size-this->size;
@@ -78,7 +74,7 @@
             BOOST_ASSERT(this->size <= max_size);
             this->buffer_[0]=this->size | 0x80;
             this->buffer_[sector_size-1]=(this->size >> 7) | 0x80;
- this->base.save_binary(this->buffer_,mpl::size_t<sector_size>());
+ this->base.write(this->buffer_,mpl::size_t<sector_size>());
             this->size=0;
         }
     }
@@ -100,8 +96,8 @@
         , pos(0)
         , size(0){}
     template<class Size>
- void load_binary(void *data,Size s){
- if(this->size == 0 || this->pos == this->size) this->load_sector();
+ void read(void *data,Size s){
+ if(this->size == 0 || this->pos == this->size) this->read_sector();
         if(this->pos + s <= this->size){
             std::memcpy(data,this->buffer(this->pos),s);
             this->pos+=s;
@@ -113,7 +109,7 @@
                 std::size_t left=s - read;
                 char *cdata=static_cast<char *>(data)+read;
                 while(left > 0){
- this->load_sector();
+ this->read_sector();
                     if(left <= this->size) read=left; else read=this->size;
                     std::memcpy(cdata,this->buffer(this->pos),read); this->pos+=read;
                     left-=read; cdata+=read;
@@ -124,16 +120,12 @@
             }
         }
     }
- template<class T>
- void load(T &t){
- this->load_binary(&t,mpl::size_t<sizeof(T)>());
- }
     size_type position() const;
 private:
- void load_sector(){
+ void read_sector(){
         BOOST_ASSERT(this->pos == this->size);
         do{
- this->base.load_binary(this->buffer_,mpl::size_t<sector_size>());
+ this->base.read(this->buffer_,mpl::size_t<sector_size>());
             if(this->buffer_[0] == 0 || this->buffer_[sector_size-1] == 0) throw eof_exception();
             this->size=((this->buffer_[sector_size-1] & 0x7f) << 7) | (this->buffer_[0] & 0x7f);
             if(this->size > max_size) throw io_failure();

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -28,10 +28,6 @@
 #error no POSIX synchronized IO available
 #endif
 
-#ifndef _LARGEFILE64_SOURCE
-#error need POSIX Large File Support extension
-#endif
-
 #endif
 
 
@@ -41,13 +37,9 @@
 
 class syncing_seq_ofile{
 public:
- typedef unsigned long long size_type;
+ typedef unsigned int size_type;
     explicit syncing_seq_ofile(std::string const &name);
- void save_binary(void const *data,std::size_t size);
- template<class T>
- void save(T const &t){
- this->save_binary(&t,mpl::size_t<sizeof(T)>());
- }
+ void write(void const *data,std::size_t size);
     size_type position() const{ return this->pos; }
     void flush();
     void sync();
@@ -63,7 +55,7 @@
     void write_ahead(size_type const &s){
         BOOST_ASSERT(s % write_ahead_size == 0);
         if(this->pos != s){
- if(::lseek64(this->filedes,s,SEEK_SET) != off64_t(s)) throw io_failure();
+ if(::lseek(this->filedes,s,SEEK_SET) != off_t(s)) throw io_failure();
         }
         char data[write_page_size]; memset(data,0,write_page_size);
         BOOST_STATIC_ASSERT(write_ahead_size % write_page_size == 0);
@@ -71,7 +63,7 @@
             if(::write(this->filedes,data,write_page_size) != ssize_t(write_page_size)) throw io_failure();
         }
         if(::fsync(this->filedes) != 0) throw io_failure();
- if(::lseek64(this->filedes,this->pos,SEEK_SET) != off64_t(this->pos)) throw io_failure();
+ if(::lseek(this->filedes,this->pos,SEEK_SET) != off_t(this->pos)) throw io_failure();
     }
     void write_ahead(size_type const &start,size_type const &end){
         BOOST_ASSERT(start % write_ahead_size == 0);
@@ -109,7 +101,7 @@
     this->write_ahead(0);
 }
 
-void syncing_seq_ofile::save_binary(void const *data,std::size_t size){
+void syncing_seq_ofile::write(void const *data,std::size_t size){
     size_type const s=this->pos % write_ahead_size;
     if(s + size >= write_ahead_size){ //there must be at least one 0 at the and, so also write ahead if this is equal.
         size_type start=this->pos - s + write_ahead_size;

Modified: sandbox/transaction/boost/transact/exception.hpp
==============================================================================
--- sandbox/transaction/boost/transact/exception.hpp (original)
+++ sandbox/transaction/boost/transact/exception.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -8,11 +8,15 @@
 #define BOOST_TRANSACT_EXCEPTION_HEADER_HPP
 
 #include <exception>
-#include <boost/mpl/begin.hpp>
-#include <boost/mpl/end.hpp>
-#include <boost/mpl/next.hpp>
-#include <boost/mpl/deref.hpp>
 #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/type_traits/is_same.hpp>
+#include <boost/optional/optional.hpp>
 
 
 namespace boost{
@@ -46,30 +50,13 @@
 
 namespace detail{
 
-//this used so that resource managers can throw isolation exceptions
-//without knowing the type of the transaction manager. as a result,
-//the type of the transaction manager is only known to isolation_exception::unwind(),
-//which makes it a function template, i.e. not a virtual function. to still be able to call
-//the correct unwind() function of the derived class the resource managers are iterated.
-
-template<class TxMgr,class Iterator>
-struct isolation_unwind_visitor{
- void operator()(isolation_exception const &iso){
- typedef typename mpl::deref<Iterator>::type resource_type;
- if(resource_isolation_exception<resource_type> const *viso=dynamic_cast<resource_isolation_exception<resource_type> const *>(&iso)){
- viso->template unwind<TxMgr>();
- }else{
- isolation_unwind_visitor<TxMgr,typename mpl::next<Iterator>::type> visit;
- visit(iso);
- }
- }
-};
-
 template<class TxMgr>
-struct isolation_unwind_visitor<TxMgr,typename mpl::end<typename TxMgr::resource_types>::type>{
- void operator()(isolation_exception const &){
- BOOST_ASSERT(false);
- }
+struct tag_types{
+ typedef typename mpl::fold<
+ typename TxMgr::resource_types,
+ mpl::vector0<>,
+ mpl::push_back<mpl::_1,mpl::first<mpl::_2> >
+ >::type type;
 };
 
 }
@@ -84,11 +71,27 @@
     ///\pre TxMgr::current_transaction() must be a rolled back transaction
     template<class TxMgr>
     void unwind() const{ //pseudo-virtual
- detail::isolation_unwind_visitor<TxMgr,typename mpl::begin<typename TxMgr::resource_types>::type> visit;
- visit(*this);
+ //TODO optimization: stop iteration when correct resource_isolation_exception is found
+ mpl::for_each<typename detail::tag_types<TxMgr>::type>(unwinder<TxMgr>(*this));
     }
+ virtual ~isolation_exception() throw(){}
 protected:
     isolation_exception(){}
+private:
+ 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;
+ if(der_type const *der=dynamic_cast<der_type const *>(&this->e)){
+ der->template unwind<TxMgr>();
+ }
+ }
+ private:
+ isolation_exception const &e;
+ };
 };
 
 
@@ -99,26 +102,56 @@
 template<class ResMgr>
 struct resource_isolation_exception : isolation_exception{
     ///\brief Constructs a resource_isolation_exception
- resource_isolation_exception() : retry(0){}
+ resource_isolation_exception(){}
 
     ///\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(typename ResMgr::transaction &retry)
- : retry(&retry){}
+ explicit resource_isolation_exception(ResMgr const &res,typename ResMgr::transaction const &retry)
+ : retry(std::pair<ResMgr const &,typename ResMgr::transaction const &>(res,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){
- typename ResMgr::transaction &currenttx=TxMgr::resource_transaction(TxMgr::current_transaction(),typename ResMgr::tag());
- if(this->retry != &currenttx) throw;
+ //TODO optimization: stop iteration when correct resource manager is found
+ mpl::for_each<typename detail::tag_types<TxMgr>::type>(is_current<TxMgr>(*this->retry));
         }else throw;
     }
+ virtual ~resource_isolation_exception() throw(){}
 private:
- typename ResMgr::transaction *retry;
+ 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());
+ }
+ private:
+ template<class Tag>
+ void operator()(Tag const &,mpl::true_) const{
+ typedef typename TxMgr::resource_iterator 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){
+ typename TxMgr::transaction *tx=TxMgr::current_transaction();
+ BOOST_ASSERT(tx);
+ if(&TxMgr::resource_transaction(*tx,it->first) != &this->retry.second) throw;
+ }
+ }
+ }
+ template<class Tag>
+ void operator()(Tag,mpl::false_) const{
+ return false;
+ }
+ std::pair<ResMgr const &,typename ResMgr::transaction const &> retry;
+ };
+ optional<std::pair<ResMgr const &,typename ResMgr::transaction const &> > retry;
 };
 
 }

Modified: sandbox/transaction/boost/transact/log.hpp
==============================================================================
--- sandbox/transaction/boost/transact/log.hpp (original)
+++ sandbox/transaction/boost/transact/log.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -107,7 +107,6 @@
             && (this->file->position() > this->max_log_size + this->header_size);
     }
 
-
     bool rolling() const{ return this->rolling_; }
     template<class Header>
     void begin_roll(Header header){

Added: sandbox/transaction/boost/transact/object_access.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/object_access.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -0,0 +1,789 @@
+// 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_OBJECT_ACCESS_HPP
+#define BOOST_TRANSACT_OBJECT_ACCESS_HPP
+
+#include <boost/serialization/is_bitwise_serializable.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>
+
+
+#ifndef NO_BOOST_SERIALIZATION
+
+#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{
+
+
+
+struct deep_tag{};
+
+namespace detail{
+
+template<class T>
+struct construct_tag;
+template<class Archive,class T>
+void construct(Archive &,T *&,deep_tag);
+
+}
+
+
+class object_access{
+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>());
+ }
+ 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>());
+ }
+
+ 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>());
+ }
+
+ template<class T>
+ static T *clone(T const &t){
+ return object_access::clone(t,boost::is_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>());
+ }
+
+ 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>());
+ }
+private:
+ template<class T>
+ friend class detail::construct_tag;
+ template<class Archive,class T>
+ friend void detail::construct(Archive &,T *&,deep_tag);
+
+ template<class T>
+ static void construct(T &t){
+ new (&t) T();
+ }
+
+ template<class T>
+ static void destruct(T &t){
+ t.~T();
+ }
+
+ template<class UnaryFunction,class T>
+ static void apply(UnaryFunction const &f,T const &t,mpl::true_ bitwise_or_empty){
+ 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){
+ f(t);
+ }
+ template<class UnaryFunction,class T>
+ static void apply(UnaryFunction const &f,T &t,mpl::false_ bitwise_or_empty);
+
+ template<class Archive,class T,bool Bitwise>
+ static void save(Archive &ar,T const &t,mpl::true_ empty,mpl::bool_<Bitwise>){}
+ template<class Archive,class T>
+ static void save(Archive &ar,T const &t,mpl::false_ empty,mpl::true_ bitwise){
+ ar.save_binary(&t,mpl::size_t<sizeof(T)>());
+ }
+ template<class Archive,class T>
+ static void save(Archive &ar,T const &t,mpl::false_ empty,mpl::false_ bitwise);
+
+ template<class Archive,class T,bool Bitwise>
+ static void load(Archive &ar,T &t,mpl::true_ empty,mpl::bool_<Bitwise>){}
+ template<class Archive,class T>
+ static void load(Archive &ar,T &t,mpl::false_ empty,mpl::true_ bitwise){
+ ar.load_binary(&t,mpl::size_t<sizeof(T)>());
+ }
+ template<class Archive,class T>
+ static void load(Archive &ar,T &t,mpl::false_ empty,mpl::false_ bitwise);
+
+ template<class Archive,class T,bool Bitwise>
+ static void construct(Archive &ar,T *&t,mpl::true_ empty,mpl::bool_<Bitwise>){
+ t=static_cast<T *>( ::operator new(sizeof(T)));
+ }
+ template<class Archive,class T>
+ static void construct(Archive &ar,T *&t,mpl::false_ empty,mpl::true_ bitwise){
+ t=static_cast<T *>( ::operator new(sizeof(T)));
+ try{
+ ar.load_binary(t,mpl::size_t<sizeof(T)>());
+ }catch(...){
+ ::operator delete(t);
+ throw;
+ }
+ }
+ template<class Archive,class T>
+ static void construct(Archive &ar,T *&t,mpl::false_ empty,mpl::false_ bitwise);
+
+ template<class T,bool Bitwise>
+ static T *clone(T const &t,mpl::true_ empty,mpl::bool_<Bitwise>){
+ return static_cast<T *>( ::operator new(sizeof(T)));
+ }
+ template<class T>
+ static T *clone(T const &t,mpl::false_ empty,mpl::true_ bitwise){
+ T *tmp=static_cast<T *>( ::operator new(sizeof(T)));
+ std::memcpy(tmp,&t,sizeof(T));
+ return tmp;
+ }
+ template<class T>
+ static T *clone(T const &t,mpl::false_ empty,mpl::false_ bitwise);
+
+ template<class T,bool Bitwise>
+ static bool equal(T const &,T const &,mpl::true_ empty,mpl::bool_<Bitwise>){
+ return true;
+ }
+ template<class T>
+ static bool equal(T const &t1,T const &t2,mpl::false_ empty,mpl::true_ bitwise){
+ return std::memcmp(&t1,&t2,sizeof(T)) == 0;
+ }
+ template<class T>
+ 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_;
+};
+
+
+
+
+template<class T>
+struct serialization_required;
+
+template<class UnaryFunction,class T>
+void apply(UnaryFunction const &f,T const &t,deep_tag tag){
+#ifdef NO_BOOST_SERIALIZATION
+ sizeof(serialization_required<T>);
+#else
+ detail::apply_archive<UnaryFunction> ar(f);
+ serialization::serialize_adl(ar,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){
+ apply(f,t,tag);
+}
+template<class UnaryFunction,class T>
+void apply_adl(UnaryFunction const &f,T const &t){
+ apply_(f,t,deep_tag());
+}
+
+
+struct constructed_tag{
+ constructed_tag(deep_tag){}
+};
+
+struct unconstructed_tag{
+public:
+ explicit unconstructed_tag(bool &constr) : constructed_(constr){
+ BOOST_ASSERT(!this->constructed());
+ }
+ bool &constructed() const{ return this->constructed_; }
+private:
+ bool &constructed_;
+};
+
+template<class T>
+struct construct_tag{
+ construct_tag(T &t,bool &constructed) : t(t),constructed(constructed){}
+ operator deep_tag() const{
+ //a user-supplied load-function is called. construct:
+ transact::object_access::construct(this->t);
+ this->constructed=true;
+ return deep_tag();
+ }
+ operator unconstructed_tag() const{ return unconstructed_tag(this->constructed); }
+private:
+ T &t;
+ bool &constructed;
+};
+
+
+template<class Archive,class T>
+void serialize(Archive &ar,T &t,constructed_tag){
+#ifdef NO_BOOST_SERIALIZATION
+ sizeof(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);
+#endif
+}
+
+template<class Archive,class T>
+void serialize_(Archive &ar,T &t,constructed_tag){
+ serialize(ar,t,deep_tag());
+}
+
+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>);
+#else
+ BOOST_STATIC_ASSERT(Archive::is_loading::value);
+ detail::serialization_iarchive<Archive> serar(ar);
+ serialization::load_construct_data_adl(serar,&t,serialization::version<T>::value);
+ tag.constructed()=true;
+ serialization::serialize_adl(serar,t,serialization::version<T>::value);
+#endif
+}
+
+template<class Archive,class T>
+void serialize_(Archive volatile &ar,T &t,unconstructed_tag tag){
+ serialize((Archive &)ar,t,construct_tag<T>(t,tag.constructed()));
+}
+
+
+template<class Archive,class T>
+void serialize_adl(Archive &ar,T &t){
+ serialize_(ar,t,deep_tag());
+}
+
+
+template<class Archive,class T>
+void load(Archive &ar,T &t,constructed_tag){
+ BOOST_STATIC_ASSERT(Archive::is_loading::value);
+ serialize_adl(ar,t);
+}
+
+template<class Archive,class T>
+void load_(Archive &ar,T &t,constructed_tag){
+ load(ar,t,deep_tag());
+}
+
+template<class Archive,class T>
+void load(Archive volatile &ar,T &t,unconstructed_tag tag){
+ serialize_((Archive &)ar,t,construct_tag<T>(t,tag.constructed()));
+}
+
+template<class Archive,class T>
+void load_(Archive volatile &ar,T &t,unconstructed_tag tag){
+ load((Archive &)ar,t,construct_tag<T>(t,tag.constructed()));
+}
+
+template<class Archive,class T>
+void load_adl(Archive &ar,T &t){
+ load_(ar,t,deep_tag());
+}
+
+
+template<class Archive,class T>
+void construct(Archive &ar,T *&t,deep_tag tag){
+ void *data=::operator new(sizeof(T));
+ T &tmp=*static_cast<T *>(data);
+ bool constructed=false;
+ try{
+ load_(ar,tmp,construct_tag<T>(tmp,constructed));
+ }catch(...){
+ if(constructed) transact::object_access::destruct(tmp);
+ ::operator delete(data);
+ throw;
+ }
+ t=&tmp;
+}
+
+template<class Archive,class T>
+void construct_(Archive &ar,T *&t,deep_tag tag){
+ construct(ar,t,tag);
+}
+
+template<class Archive,class T>
+void construct_adl(Archive &ar,T *&t){
+ construct_(ar,t,deep_tag());
+}
+
+
+template<class Archive,class T>
+void save(Archive &ar,T const &t,deep_tag){
+ BOOST_STATIC_ASSERT(Archive::is_saving::value);
+ detail::serialize_adl(ar,const_cast<T &>(t));
+}
+
+template<class Archive,class T>
+void save_(Archive &ar,T const &t,deep_tag){
+ save(ar,t,deep_tag());
+}
+
+template<class Archive,class T>
+void save_adl(Archive &ar,T const &t){
+ save_(ar,t,deep_tag());
+}
+
+template<class T>
+T *clone(T const &t,deep_tag){
+ typedef detail::embedded_vector<char,256,true> buffer_type;
+ buffer_type buffer;
+ {
+ typedef vector_back_insert_iterator<buffer_type> iterator;
+ iterator it(buffer);
+ detail::memory_oarchive<iterator> ar(it);
+ object_access::save(ar,t);
+ }
+ {
+ detail::memory_iarchive<buffer_type::iterator> ar(buffer.begin(),buffer.end());
+ T *tmp=0;
+ object_access::construct(ar,tmp);
+ BOOST_ASSERT(tmp);
+ return tmp;
+ }
+}
+
+template<class T>
+T *clone_(T const &t,deep_tag){
+ return clone(t,deep_tag());
+}
+
+template<class T>
+T *clone_adl(T const &t){
+ return clone_(t,deep_tag());
+}
+
+template<class T>
+bool equal(T const &t1,T const &t2,deep_tag){
+ typedef detail::embedded_vector<char,256,true> buffer_type;
+ buffer_type buffer;
+ {
+ typedef vector_back_insert_iterator<buffer_type> iterator;
+ iterator it(buffer);
+ detail::memory_oarchive<iterator> ar(it);
+ object_access::save(ar,t1);
+ }
+ {
+ detail::compare_archive<buffer_type::iterator> ar(buffer.begin(),buffer.end());
+ object_access::save(ar,t2);
+ return ar.equal();
+ }
+}
+
+template<class T>
+bool equal_(T const &t1,T const &t2,deep_tag){
+ return equal(t1,t2,deep_tag());
+}
+
+template<class T>
+bool equal_adl(T const &t1,T const &t2){
+ return equal_(t1,t2,deep_tag());
+}
+
+}
+
+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);
+}
+
+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);
+}
+
+
+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);
+}
+
+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);
+}
+
+template<class T>
+T *object_access::clone(T const &t,mpl::false_ empty,mpl::false_ bitwise){
+ return detail::clone_adl(t);
+}
+
+template<class T>
+bool object_access::equal(T const &t1,T const &t2,mpl::false_ empty,mpl::false_ bitwise){
+ return detail::equal_adl(t1,t2);
+}
+
+}
+}
+
+
+#endif

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -7,10 +7,41 @@
 #ifndef BOOST_TRANSACT_RESOURCE_MANAGER_HPP
 #define BOOST_TRANSACT_RESOURCE_MANAGER_HPP
 
+#include <boost/transact/default_tag.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/set.hpp>
+#include <boost/mpl/has_key.hpp>
+
 namespace boost{
 namespace transact{
 
 struct transaction_restart_service_tag{};
+struct nested_transaction_service_tag{};
+
+namespace detail{
+
+template<class Tag>
+struct has_service_impl{
+ template<class Resource,class Service>
+ struct apply{
+ typedef typename mpl::contains<typename Resource::services,Service>::type type;
+ };
+};
+
+template<>
+struct has_service_impl<mpl::sequence_tag<mpl::set0<> >::type>{
+ template<class Resource,class Service>
+ struct apply{
+ typedef typename mpl::has_key<typename Resource::services,Service>::type type;
+ };
+};
+
+}
+
+template<class Resource,class Service>
+struct has_service
+ : detail::has_service_impl<typename mpl::sequence_tag<typename Resource::services>::type>::template apply<Resource,Service>{};
 
 }
 }

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-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -8,9 +8,14 @@
 #ifndef BOOST_TRANSACT_SIMPLE_TRANSACTION_MANAGER_HEADER_HPP
 #define BOOST_TRANSACT_SIMPLE_TRANSACTION_MANAGER_HEADER_HPP
 
-#include <boost/mpl/vector.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>
+#include <boost/ref.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/type_traits/is_same.hpp>
 #include <boost/utility/in_place_factory.hpp>
 #include <boost/optional/optional.hpp>
 #include <boost/transact/exception.hpp>
@@ -27,12 +32,16 @@
 ///
 /// Template parameters:
 /// \li \c Resource The type of the resource manager used.
+/// \li \c FlatNested Use emulated flat nested transactions instead of the NestedTransactionService offered by the ResourceManager.
 /// \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 Threads=true>
+template<class Resource,bool FlatNested=false,bool Threads=true,class ResourceTag=default_tag>
 class simple_transaction_manager : noncopyable{
 public:
     class transaction;
+ /// \cond
+ friend class transaction;
 private:
     class transaction_construct_t{
         explicit transaction_construct_t(transaction *parent)
@@ -49,59 +58,64 @@
 
     struct detail{ //for QuickBook
         typedef typename simple_transaction_manager::transaction_construct_t transaction_construct_t;
+ typedef std::pair<ResourceTag,Resource &> *resource_iterator;
     };
- /// \endcond
 public:
     class transaction : noncopyable{
- /// \cond
     public:
         explicit transaction(transaction_construct_t const &c)
- : parent(c.parent){
- if(res){
- if(this->parent){
- BOOST_ASSERT(this->parent->rtx);
- this->rtx=in_place(res->begin_nested_transaction(*this->parent->rtx));
- }else{
- this->rtx=in_place(res->begin_root_transaction());
- }
- }
+ : 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;
+ optional<typename Resource::transaction> rtx_storage;
+ typename Resource::transaction *rtx; //if(FlatNested) == root transaction; else == &*rtx_storage
+ bool rolled_back;
         transaction * const parent;
- /// \endcond
- };
- typedef mpl::vector1<Resource> resource_types;
- template<class ServiceTag>
- struct default_resource{
- typedef typename Resource::tag type;
     };
+ /// \endcond
+ typedef mpl::map1<mpl::pair<ResourceTag,Resource> > resource_types;
 
- typedef typename Resource::tag resource_tag_t;
-
     /// \brief Constructs a simple_transaction_manager
     simple_transaction_manager(){}
 
     /// TODO doc, not part of the concept
- static void connect_resource(Resource &newres){
- if(res) throw resource_error();
- res=&newres;
+ 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));
     }
 
     /// TODO doc, not part of the concept
- static void disconnect_resource(resource_tag_t tag= resource_tag_t()){
- res=0;
+ static void disconnect_resource(ResourceTag const &tag=ResourceTag()){
+ if(res && tag_is_equal(tag)) res=none;
+ else throw resource_error();
     }
 
- static Resource &resource(resource_tag_t tag= resource_tag_t()){
- if(res) return *res;
+ static Resource &resource(ResourceTag const &tag=ResourceTag()){
+ if(res && tag_is_equal(tag)) return res->second;
         else throw resource_error();
     }
 
+ 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);
+ }
+
     static typename Resource::transaction &
- resource_transaction(transaction &tx,resource_tag_t tag= resource_tag_t()){
- if(tx.rtx) return *tx.rtx;
+ resource_transaction(transaction &tx,ResourceTag const &tag=ResourceTag()){
+ if(tx.rtx && tag_is_equal(tag)) return *tx.rtx;
         else throw resource_error();
     }
 
@@ -113,8 +127,8 @@
         bind_transaction(tx);
         if(res){
             BOOST_ASSERT(tx.rtx);
- res->finish_transaction(*tx.rtx);
- res->commit_transaction(*tx.rtx);
+ res->second.finish_transaction(*tx.rtx);
+ res->second.commit_transaction(*tx.rtx);
         }
     }
 
@@ -122,13 +136,18 @@
         bind_transaction(tx);
         if(res){
             BOOST_ASSERT(tx.rtx);
- res->rollback_transaction(*tx.rtx);
+ BOOST_ASSERT(FlatNested || !tx.rolled_back);
+ if(!FlatNested || !tx.rolled_back){
+ mark_rolled_back(tx);
+ res->second.rollback_transaction(*tx.rtx);
+ }
         }
     }
 
     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());
         }
     }
@@ -139,34 +158,68 @@
     static void unbind_transaction(){
         currenttx::reset(0);
     }
- static transaction &current_transaction(){
- if(transaction *tx=currenttx::get()) return *tx;
+ static transaction *current_transaction(){
+ return currenttx::get();
+ }
+ /// \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 bool has_current_transaction(){
- return currenttx::get() ? true : false;
+ 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();
     }
 
- /// \cond
-private:
+ 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){
- res->restart_transaction(*tx.rtx);
+ BOOST_ASSERT(res);
+ res->second.restart_transaction(*tx.rtx);
     }
     static void restart_transaction(transaction &tx,mpl::false_ service){
- if(tx.parent){
- BOOST_ASSERT(tx.parent->rtx);
- tx.rtx=in_place(res->begin_nested_transaction(*tx.parent->rtx));
- }else{
- tx.rtx=in_place(res->begin_root_transaction());
- }
+ 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 Resource *res;
+ static optional<std::pair<ResourceTag,Resource &> > res;
     /// \endcond
 };
 
-template<class Res,bool Thr>
-Res *simple_transaction_manager<Res,Thr>::res=0;
+template<class Resource,bool FlatNested,bool Threads,class ResourceTag>
+optional<std::pair<ResourceTag,Resource &> > simple_transaction_manager<Resource,FlatNested,Threads,ResourceTag>::res;
 
 
 }

Added: sandbox/transaction/boost/transact/type_selection.hpp
==============================================================================
--- (empty file)
+++ sandbox/transaction/boost/transact/type_selection.hpp 2010-05-09 09:55:35 EDT (Sun, 09 May 2010)
@@ -0,0 +1,59 @@
+// 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_TYPE_SELECTION_HPP
+#define BOOST_TRANSACT_TYPE_SELECTION_HPP
+
+#include <boost/assert.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/at.hpp>
+
+namespace boost{
+namespace transact{
+
+template<class Sequence>
+class type_selection{
+public:
+ explicit type_selection(unsigned int wh) : which_(wh){
+ BOOST_ASSERT(wh < (unsigned int)(mpl::size<Sequence>::value));
+ }
+ void reset(unsigned int wh){
+ BOOST_ASSERT(wh < (unsigned int)(mpl::size<Sequence>::value));
+ this->which_=wh;
+ }
+ template<class Visitor>
+ typename Visitor::result_type apply_visitor(Visitor const &v) const{
+ return this->apply_visitor<0>(v);
+ //detail::type_selection_visitor<Sequence,0,mpl::size<Sequence>::value> visit;
+ //visit(v,this->which_);
+ }
+ unsigned int which() const{ return this->which_; }
+private:
+ template<std::size_t N,class Visitor>
+ typename Visitor::result_type apply_visitor(Visitor const &v) const{
+ return this->apply_visitor<N>(v,mpl::bool_<N == std::size_t(mpl::size<Sequence>::value)>());
+ }
+ template<std::size_t N,class Visitor>
+ typename Visitor::result_type apply_visitor(Visitor const &v,mpl::false_) const{
+ if(this->which_ == N){
+ return v.template operator()<typename mpl::at_c<Sequence,N>::type>();
+ }else return this->apply_visitor<N+1>(v);
+ }
+ template<std::size_t N,class Visitor>
+ typename Visitor::result_type apply_visitor(Visitor const &,mpl::true_) const{
+ BOOST_ASSERT(false);
+ }
+
+ unsigned int which_;
+};
+
+
+
+}
+}
+
+
+#endif
\ No newline at end of file


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