$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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 ¤ttx=TxMgr::resource_transaction(TxMgr::current_transaction(),typename ResMgr::tag());
-            if(this->retry != ¤ttx) 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 ¤t_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