Boost logo

Boost-Commit :

From: igaztanaga_at_[hidden]
Date: 2008-04-27 11:03:16


Author: igaztanaga
Date: 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
New Revision: 44819
URL: http://svn.boost.org/trac/boost/changeset/44819

Log:
Intrusive:

* Added `linear<>` and `cache_last<>` options to singly linked lists.
* Added `optimize_multikey<>` option to unordered container hooks.
* Optimized unordered containers when `store_hash` option is used in the hook.
* Implementation changed to be exception agnostic so that it can be used
   in environments without exceptions.
* Added `container_from_iterator` function to tree-based containers.

Interprocess:

* Added anonymous shared memory for UNIX systems.
* Fixed file lock compilation errors
Added:
   trunk/boost/intrusive/pointer_plus_bits.hpp (contents, props changed)
   trunk/libs/interprocess/example/doc_anonymous_shared_memory.cpp (contents, props changed)
   trunk/libs/interprocess/example/doc_multi_index.cpp (contents, props changed)
   trunk/libs/interprocess/example/doc_unordered_map.cpp (contents, props changed)
   trunk/libs/interprocess/proj/to-do.txt (contents, props changed)
   trunk/libs/interprocess/proj/vc7ide/anonymous_shared_memory_test.vcproj (contents, props changed)
   trunk/libs/interprocess/proj/vc7ide/doc_anonymous_shared_memory.vcproj (contents, props changed)
   trunk/libs/interprocess/proj/vc7ide/doc_multi_index.vcproj (contents, props changed)
   trunk/libs/interprocess/proj/vc7ide/doc_unordered_map.vcproj (contents, props changed)
   trunk/libs/interprocess/proj/vc7ide/file_lock_test.vcproj (contents, props changed)
   trunk/libs/interprocess/proj/vc7ide/multi_index_test.vcproj (contents, props changed)
   trunk/libs/interprocess/proj/vc7ide/unordered_test.vcproj (contents, props changed)
   trunk/libs/interprocess/test/anonymous_shared_memory_test.cpp (contents, props changed)
   trunk/libs/interprocess/test/file_lock_test.cpp (contents, props changed)
   trunk/libs/interprocess/test/multi_index_test.cpp (contents, props changed)
   trunk/libs/interprocess/test/unordered_test.cpp (contents, props changed)
   trunk/libs/intrusive/proj/vc7ide/to-do.txt (contents, props changed)
Removed:
   trunk/boost/intrusive/detail/no_exceptions_support.hpp
   trunk/boost/intrusive/pointer_plus_2_bits.hpp
   trunk/boost/intrusive/pointer_plus_bit.hpp
Text files modified:
   trunk/boost/interprocess/allocators/adaptive_pool.hpp | 162 +++
   trunk/boost/interprocess/allocators/allocator.hpp | 11
   trunk/boost/interprocess/allocators/cached_adaptive_pool.hpp | 8
   trunk/boost/interprocess/allocators/cached_node_allocator.hpp | 14
   trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp | 26
   trunk/boost/interprocess/allocators/detail/allocator_common.hpp | 52 +
   trunk/boost/interprocess/allocators/detail/node_pool.hpp | 2
   trunk/boost/interprocess/allocators/node_allocator.hpp | 75 +
   trunk/boost/interprocess/allocators/private_adaptive_pool.hpp | 22
   trunk/boost/interprocess/allocators/private_node_allocator.hpp | 226 -----
   trunk/boost/interprocess/containers/deque.hpp | 24
   trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp | 6
   trunk/boost/interprocess/containers/string.hpp | 2
   trunk/boost/interprocess/containers/vector.hpp | 79 -
   trunk/boost/interprocess/detail/algorithms.hpp | 4
   trunk/boost/interprocess/detail/config_begin.hpp | 1
   trunk/boost/interprocess/detail/move.hpp | 2
   trunk/boost/interprocess/detail/mpl.hpp | 20
   trunk/boost/interprocess/detail/named_proxy.hpp | 20
   trunk/boost/interprocess/detail/utilities.hpp | 15
   trunk/boost/interprocess/ipc/message_queue.hpp | 14
   trunk/boost/interprocess/mapped_region.hpp | 7
   trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp | 97 ++
   trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp | 2
   trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp | 34
   trunk/boost/interprocess/offset_ptr.hpp | 72 -
   trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp | 27
   trunk/boost/interprocess/sync/file_lock.hpp | 69 -
   trunk/boost/interprocess/sync/named_condition.hpp | 4
   trunk/boost/interprocess/windows_shared_memory.hpp | 2
   trunk/boost/intrusive/avl_set.hpp | 70 +
   trunk/boost/intrusive/avltree.hpp | 31
   trunk/boost/intrusive/avltree_algorithms.hpp | 11
   trunk/boost/intrusive/circular_list_algorithms.hpp | 4
   trunk/boost/intrusive/circular_slist_algorithms.hpp | 12
   trunk/boost/intrusive/detail/avltree_node.hpp | 10
   trunk/boost/intrusive/detail/common_slist_algorithms.hpp | 2
   trunk/boost/intrusive/detail/ebo_functor_holder.hpp | 31
   trunk/boost/intrusive/detail/hashtable_node.hpp | 44
   trunk/boost/intrusive/detail/list_node.hpp | 5
   trunk/boost/intrusive/detail/mpl.hpp | 20
   trunk/boost/intrusive/detail/rbtree_node.hpp | 16
   trunk/boost/intrusive/detail/slist_node.hpp | 2
   trunk/boost/intrusive/detail/tree_algorithms.hpp | 175 ++-
   trunk/boost/intrusive/detail/tree_node.hpp | 5
   trunk/boost/intrusive/detail/utilities.hpp | 85 +
   trunk/boost/intrusive/hashtable.hpp | 1528 ++++++++++++++++++++++++++++-----------
   trunk/boost/intrusive/intrusive_fwd.hpp | 6
   trunk/boost/intrusive/linear_slist_algorithms.hpp | 14
   trunk/boost/intrusive/list.hpp | 18
   trunk/boost/intrusive/options.hpp | 35
   trunk/boost/intrusive/rbtree.hpp | 62 +
   trunk/boost/intrusive/rbtree_algorithms.hpp | 11
   trunk/boost/intrusive/set.hpp | 85 ++
   trunk/boost/intrusive/sg_set.hpp | 68 +
   trunk/boost/intrusive/sgtree.hpp | 25
   trunk/boost/intrusive/sgtree_algorithms.hpp | 11
   trunk/boost/intrusive/slist.hpp | 58
   trunk/boost/intrusive/splay_set.hpp | 68 +
   trunk/boost/intrusive/splaytree.hpp | 25
   trunk/boost/intrusive/splaytree_algorithms.hpp | 64 +
   trunk/boost/intrusive/unordered_set.hpp | 58
   trunk/boost/intrusive/unordered_set_hook.hpp | 126 ++
   trunk/libs/interprocess/doc/interprocess.qbk | 92 +
   trunk/libs/interprocess/proj/vc7ide/Interprocess.sln | 56 +
   trunk/libs/interprocess/proj/vc7ide/interprocesslib.vcproj | 3
   trunk/libs/interprocess/test/adaptive_node_pool_test.cpp | 2
   trunk/libs/interprocess/test/adaptive_pool_test.cpp | 1
   trunk/libs/interprocess/test/allocator_v1.hpp | 8
   trunk/libs/interprocess/test/dummy_test_allocator.hpp | 8
   trunk/libs/interprocess/test/expand_bwd_test_allocator.hpp | 8
   trunk/libs/interprocess/test/expand_bwd_test_template.hpp | 145 ++-
   trunk/libs/interprocess/test/list_test.cpp | 6
   trunk/libs/interprocess/test/shared_memory_mapping_test.cpp | 23
   trunk/libs/interprocess/test/tree_test.cpp | 2
   trunk/libs/interprocess/test/vector_test.cpp | 15
   trunk/libs/interprocess/test/windows_shared_memory_mapping_test.cpp | 143 +-
   trunk/libs/interprocess/test/windows_shared_memory_test.cpp | 1
   trunk/libs/intrusive/doc/intrusive.qbk | 174 +++
   trunk/libs/intrusive/index.html | 2
   trunk/libs/intrusive/perf/perf_list.cpp | 2
   trunk/libs/intrusive/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj | 8
   trunk/libs/intrusive/test/avl_set_test.cpp | 1
   trunk/libs/intrusive/test/generic_assoc_test.hpp | 31
   trunk/libs/intrusive/test/generic_set_test.hpp | 1
   trunk/libs/intrusive/test/itestvalue.hpp | 61 +
   trunk/libs/intrusive/test/smart_ptr.hpp | 56 -
   trunk/libs/intrusive/test/unordered_multiset_test.cpp | 241 ++++-
   trunk/libs/intrusive/test/unordered_set_test.cpp | 48
   89 files changed, 3456 insertions(+), 1566 deletions(-)

Modified: trunk/boost/interprocess/allocators/adaptive_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/adaptive_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/adaptive_pool.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -26,6 +26,7 @@
 #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
 #include <boost/interprocess/exceptions.hpp>
 #include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
 #include <memory>
 #include <algorithm>
 #include <cstddef>
@@ -39,7 +40,7 @@
 /// @cond
 
 namespace detail{
-
+/*
 template < unsigned int Version
          , class T
          , class SegmentManager
@@ -61,8 +62,9 @@
    typedef SegmentManager segment_manager;
    typedef adaptive_pool_base
       <Version, T, SegmentManager, NodesPerChunk, MaxFreeChunks, OverheadPercent> self_t;
+ static const std::size_t SizeOfT = sizeof(detail::if_c<detail::is_same<T, void>::value, int, T>::type);
    typedef detail::shared_adaptive_node_pool
- < SegmentManager, sizeof(T), NodesPerChunk, MaxFreeChunks, OverheadPercent> node_pool_t;
+ < SegmentManager, SizeOfT, NodesPerChunk, MaxFreeChunks, OverheadPercent> node_pool_t;
    typedef typename detail::
       pointer_to_other<void_pointer, node_pool_t>::type node_pool_ptr;
 
@@ -157,19 +159,153 @@
    node_pool_ptr mp_node_pool;
    /// @endcond
 };
+*/
+
+template < unsigned int Version
+ , class T
+ , class SegmentManager
+ , std::size_t NodesPerChunk
+ , std::size_t MaxFreeChunks
+ , unsigned char OverheadPercent
+ >
+class adaptive_pool_base
+ : public node_pool_allocation_impl
+ < adaptive_pool_base
+ < Version, T, SegmentManager, NodesPerChunk, MaxFreeChunks, OverheadPercent>
+ , Version
+ , T
+ , SegmentManager
+ >
+{
+ public:
+ typedef typename SegmentManager::void_pointer void_pointer;
+ typedef SegmentManager segment_manager;
+ typedef adaptive_pool_base
+ <Version, T, SegmentManager, NodesPerChunk, MaxFreeChunks, OverheadPercent> self_t;
+
+ /// @cond
+
+ template <int dummy>
+ struct node_pool
+ {
+ typedef detail::shared_adaptive_node_pool
+ < SegmentManager, sizeof(T), NodesPerChunk, MaxFreeChunks, OverheadPercent> type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+ /// @endcond
+
+ BOOST_STATIC_ASSERT((Version <=2));
+
+ public:
+ //-------
+ typedef typename detail::
+ pointer_to_other<void_pointer, T>::type pointer;
+ typedef typename detail::
+ pointer_to_other<void_pointer, const T>::type const_pointer;
+ typedef T value_type;
+ typedef typename detail::add_reference
+ <value_type>::type reference;
+ typedef typename detail::add_reference
+ <const value_type>::type const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef detail::version_type<adaptive_pool_base, Version> version;
+ typedef transform_iterator
+ < typename SegmentManager::
+ multiallocation_iterator
+ , detail::cast_functor <T> > multiallocation_iterator;
+ typedef typename SegmentManager::
+ multiallocation_chain multiallocation_chain;
+
+ //!Obtains adaptive_pool_base from
+ //!adaptive_pool_base
+ template<class T2>
+ struct rebind
+ {
+ typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerChunk, MaxFreeChunks, OverheadPercent> other;
+ };
+
+ /// @cond
+ private:
+ //!Not assignable from related adaptive_pool_base
+ template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2>
+ adaptive_pool_base& operator=
+ (const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
+
+ /// @endcond
+
+ public:
+ //!Constructor from a segment manager. If not present, constructs a node
+ //!pool. Increments the reference count of the associated node pool.
+ //!Can throw boost::interprocess::bad_alloc
+ adaptive_pool_base(segment_manager *segment_mngr)
+ : mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
+
+ //!Copy constructor from other adaptive_pool_base. Increments the reference
+ //!count of the associated node pool. Never throws
+ adaptive_pool_base(const adaptive_pool_base &other)
+ : mp_node_pool(other.get_node_pool())
+ {
+ node_pool<0>::get(detail::get_pointer(mp_node_pool))->inc_ref_count();
+ }
+
+ //!Assignment from other adaptive_pool_base
+ adaptive_pool_base& operator=(const adaptive_pool_base &other)
+ {
+ adaptive_pool_base c(other);
+ swap(*this, c);
+ return *this;
+ }
+
+ //!Copy constructor from related adaptive_pool_base. If not present, constructs
+ //!a node pool. Increments the reference count of the associated node pool.
+ //!Can throw boost::interprocess::bad_alloc
+ template<class T2>
+ adaptive_pool_base
+ (const adaptive_pool_base<Version, T2, SegmentManager, NodesPerChunk, MaxFreeChunks, OverheadPercent> &other)
+ : mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
+
+ //!Destructor, removes node_pool_t from memory
+ //!if its reference count reaches to zero. Never throws
+ ~adaptive_pool_base()
+ { detail::destroy_node_pool_if_last_link(node_pool<0>::get(detail::get_pointer(mp_node_pool))); }
+
+ //!Returns a pointer to the node pool.
+ //!Never throws
+ void* get_node_pool() const
+ { return detail::get_pointer(mp_node_pool); }
+
+ //!Returns the segment manager.
+ //!Never throws
+ segment_manager* get_segment_manager()const
+ { return node_pool<0>::get(detail::get_pointer(mp_node_pool))->get_segment_manager(); }
+
+ //!Swaps allocators. Does not throw. If each allocator is placed in a
+ //!different memory segment, the result is undefined.
+ friend void swap(self_t &alloc1, self_t &alloc2)
+ { detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
+
+ /// @cond
+ private:
+ void_pointer mp_node_pool;
+ /// @endcond
+};
 
 //!Equality test for same type
 //!of adaptive_pool_base
-template<unsigned int V, class T, class S, std::size_t NodesPerChunk, std::size_t F, unsigned char OP> inline
-bool operator==(const adaptive_pool_base<V, T, S, NodesPerChunk, F, OP> &alloc1,
- const adaptive_pool_base<V, T, S, NodesPerChunk, F, OP> &alloc2)
+template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
+bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
+ const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
    { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
 
 //!Inequality test for same type
 //!of adaptive_pool_base
-template<unsigned int V, class T, class S, std::size_t NodesPerChunk, std::size_t F, unsigned char OP> inline
-bool operator!=(const adaptive_pool_base<V, T, S, NodesPerChunk, F, OP> &alloc1,
- const adaptive_pool_base<V, T, S, NodesPerChunk, F, OP> &alloc2)
+template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
+bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
+ const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
    { return alloc1.get_node_pool() != alloc2.get_node_pool(); }
 
 template < class T
@@ -299,7 +435,7 @@
 
    //!Not assignable from
    //!other adaptive_pool
- adaptive_pool& operator=(const adaptive_pool&);
+ //adaptive_pool& operator=(const adaptive_pool&);
 
    public:
    //!Constructor from a segment manager. If not present, constructs a node
@@ -324,7 +460,7 @@
 
    //!Returns a pointer to the node pool.
    //!Never throws
- node_pool_t* get_node_pool() const;
+ void* get_node_pool() const;
 
    //!Returns the segment manager.
    //!Never throws
@@ -358,9 +494,9 @@
    //!Never throws
    const_pointer address(const_reference value) const;
 
- //!Default construct an object.
- //!Throws if T's default constructor throws
- void construct(const pointer &ptr);
+ //!Copy construct an object.
+ //!Throws if T's copy constructor throws
+ void construct(const pointer &ptr, const_reference v);
 
    //!Destroys object. Throws if object's
    //!destructor throws

Modified: trunk/boost/interprocess/allocators/allocator.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/allocator.hpp (original)
+++ trunk/boost/interprocess/allocators/allocator.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -106,8 +106,6 @@
       <typename SegmentManager::
          multiallocation_chain
       , T> multiallocation_chain;
-// typedef typename SegmentManager::
-// multiallocation_chain multiallocation_chain;
 
    /// @endcond
 
@@ -153,7 +151,7 @@
    //!Deallocates memory previously allocated.
    //!Never throws
    void deallocate(const pointer &ptr, size_type)
- { mp_mngr->deallocate(detail::get_pointer(ptr)); }
+ { mp_mngr->deallocate((void*)detail::get_pointer(ptr)); }
 
    //!Returns the number of elements that could be allocated.
    //!Never throws
@@ -253,10 +251,15 @@
    const_pointer address(const_reference value) const
    { return const_pointer(boost::addressof(value)); }
 
+ //!Copy construct an object
+ //!Throws if T's copy constructor throws
+ void construct(const pointer &ptr, const_reference v)
+ { new((void*)detail::get_pointer(ptr)) value_type(v); }
+
    //!Default construct an object.
    //!Throws if T's default constructor throws
    void construct(const pointer &ptr)
- { new(detail::get_pointer(ptr)) value_type; }
+ { new((void*)detail::get_pointer(ptr)) value_type; }
 
    //!Destroys object. Throws if object's
    //!destructor throws

Modified: trunk/boost/interprocess/allocators/cached_adaptive_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/cached_adaptive_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/cached_adaptive_pool.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -119,7 +119,7 @@
          < T
          , detail::shared_adaptive_node_pool
             < SegmentManager
- , sizeof(T)
+ , sizeof(typename detail::if_c<detail::is_same<T, void>::value, int, T>::type)
             , NodesPerChunk
             , MaxFreeChunks
             , OverheadPercent
@@ -252,9 +252,9 @@
    //!Never throws
    const_pointer address(const_reference value) const;
 
- //!Default construct an object.
- //!Throws if T's default constructor throws
- void construct(const pointer &ptr);
+ //!Copy construct an object.
+ //!Throws if T's copy constructor throws
+ void construct(const pointer &ptr, const_reference v);
 
    //!Destroys object. Throws if object's
    //!destructor throws

Modified: trunk/boost/interprocess/allocators/cached_node_allocator.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/cached_node_allocator.hpp (original)
+++ trunk/boost/interprocess/allocators/cached_node_allocator.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -225,7 +225,7 @@
 
    //!Default construct an object.
    //!Throws if T's default constructor throws
- void construct(const pointer &ptr);
+ void construct(const pointer &ptr, const_reference v);
 
    //!Destroys object. Throws if object's
    //!destructor throws
@@ -302,15 +302,15 @@
 
 //!Equality test for same type
 //!of cached_node_allocator
-template<class T, class S, std::size_t NodesPerChunk> inline
-bool operator==(const cached_node_allocator<T, S, NodesPerChunk> &alloc1,
- const cached_node_allocator<T, S, NodesPerChunk> &alloc2);
+template<class T, class S, std::size_t NPC> inline
+bool operator==(const cached_node_allocator<T, S, NPC> &alloc1,
+ const cached_node_allocator<T, S, NPC> &alloc2);
 
 //!Inequality test for same type
 //!of cached_node_allocator
-template<class T, class S, std::size_t NodesPerChunk> inline
-bool operator!=(const cached_node_allocator<T, S, NodesPerChunk> &alloc1,
- const cached_node_allocator<T, S, NodesPerChunk> &alloc2);
+template<class T, class S, std::size_t NPC> inline
+bool operator!=(const cached_node_allocator<T, S, NPC> &alloc1,
+ const cached_node_allocator<T, S, NPC> &alloc2);
 
 #endif
 

Modified: trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -49,7 +49,7 @@
    private_adaptive_node_pool_impl &operator=(const private_adaptive_node_pool_impl &);
 
    typedef typename SegmentManagerBase::void_pointer void_pointer;
-
+ static const std::size_t PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
    public:
    typedef typename node_slist<void_pointer>::node_t node_t;
    typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
@@ -106,9 +106,11 @@
       std::size_t candidate_power_of_2 =
          upper_power_of_2(elements_per_subchunk*real_node_size + HdrOffsetSize);
       bool overhead_satisfied = false;
+ //Now calculate the wors-case overhead for a subchunk
+ const std::size_t max_subchunk_overhead = HdrSize + PayloadPerAllocation;
       while(!overhead_satisfied){
- elements_per_subchunk = (candidate_power_of_2 - HdrOffsetSize)/real_node_size;
- std::size_t overhead_size = candidate_power_of_2 - elements_per_subchunk*real_node_size;
+ elements_per_subchunk = (candidate_power_of_2 - max_subchunk_overhead)/real_node_size;
+ const std::size_t overhead_size = candidate_power_of_2 - elements_per_subchunk*real_node_size;
          if(overhead_size*100/candidate_power_of_2 < overhead_percent){
             overhead_satisfied = true;
          }
@@ -121,14 +123,26 @@
 
    static void calculate_num_subchunks
       (std::size_t alignment, std::size_t real_node_size, std::size_t elements_per_chunk
- ,std::size_t &num_subchunks, std::size_t &real_num_node)
+ ,std::size_t &num_subchunks, std::size_t &real_num_node, std::size_t overhead_percent)
    {
       std::size_t elements_per_subchunk = (alignment - HdrOffsetSize)/real_node_size;
       std::size_t possible_num_subchunk = (elements_per_chunk - 1)/elements_per_subchunk + 1;
- std::size_t hdr_subchunk_elements = (alignment - HdrSize - SegmentManagerBase::PayloadPerAllocation)/real_node_size;
+ std::size_t hdr_subchunk_elements = (alignment - HdrSize - PayloadPerAllocation)/real_node_size;
       while(((possible_num_subchunk-1)*elements_per_subchunk + hdr_subchunk_elements) < elements_per_chunk){
          ++possible_num_subchunk;
       }
+ elements_per_subchunk = (alignment - HdrOffsetSize)/real_node_size;
+ bool overhead_satisfied = false;
+ while(!overhead_satisfied){
+ const std::size_t total_data = (elements_per_subchunk*(possible_num_subchunk-1) + hdr_subchunk_elements)*real_node_size;
+ const std::size_t total_size = alignment*possible_num_subchunk;
+ if((total_size - total_data)*100/total_size < overhead_percent){
+ overhead_satisfied = true;
+ }
+ else{
+ ++possible_num_subchunk;
+ }
+ }
       num_subchunks = possible_num_subchunk;
       real_num_node = (possible_num_subchunk-1)*elements_per_subchunk + hdr_subchunk_elements;
    }
@@ -157,7 +171,7 @@
    , m_chunk_multiset()
    , m_totally_free_chunks(0)
    {
- calculate_num_subchunks(m_real_chunk_alignment, m_real_node_size, nodes_per_chunk, m_num_subchunks, m_real_num_node);
+ calculate_num_subchunks(m_real_chunk_alignment, m_real_node_size, nodes_per_chunk, m_num_subchunks, m_real_num_node, overhead_percent);
    }
 
    //!Destructor. Deallocates all allocated chunks. Never throws

Modified: trunk/boost/interprocess/allocators/detail/allocator_common.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/detail/allocator_common.hpp (original)
+++ trunk/boost/interprocess/allocators/detail/allocator_common.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -342,7 +342,12 @@
    //!Default construct an object.
    //!Throws if T's default constructor throws
    void construct(const pointer &ptr)
- { new(detail::get_pointer(ptr)) value_type; }
+ { new((void*)detail::get_pointer(ptr)) value_type; }
+
+ //!Copy construct an object
+ //!Throws if T's copy constructor throws
+ void construct(const pointer &ptr, const_reference v)
+ { new((void*)detail::get_pointer(ptr)) value_type(v); }
 
    //!Destroys object. Throws if object's
    //!destructor throws
@@ -386,36 +391,53 @@
    typedef typename SegmentManager::
       multiallocation_chain multiallocation_chain;
 
+ template <int Dummy>
+ struct node_pool
+ {
+ typedef typename Derived::template node_pool<0>::type type;
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+
    public:
    //!Allocate memory for an array of count elements.
    //!Throws boost::interprocess::bad_alloc if there is no enough memory
    pointer allocate(size_type count, cvoid_pointer hint = 0)
    {
       (void)hint;
+ typedef typename node_pool<0>::type node_pool_t;
+ node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
       if(count > this->max_size())
          throw bad_alloc();
       else if(Version == 1 && count == 1)
- return pointer(static_cast<value_type*>(this->derived()->get_node_pool()->allocate_node()));
+ return pointer(static_cast<value_type*>
+ (pool->allocate_node()));
       else
          return pointer(static_cast<value_type*>
- (this->derived()->get_node_pool()->get_segment_manager()->allocate(sizeof(T)*count)));
+ (pool->get_segment_manager()->allocate(sizeof(T)*count)));
    }
 
    //!Deallocate allocated memory. Never throws
    void deallocate(const pointer &ptr, size_type count)
    {
       (void)count;
+ typedef typename node_pool<0>::type node_pool_t;
+ node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
       if(Version == 1 && count == 1)
- this->derived()->get_node_pool()->deallocate_node(detail::get_pointer(ptr));
+ pool->deallocate_node(detail::get_pointer(ptr));
       else
- this->derived()->get_node_pool()->get_segment_manager()->deallocate(detail::get_pointer(ptr));
+ pool->get_segment_manager()->deallocate((void*)detail::get_pointer(ptr));
    }
 
    //!Allocates just one object. Memory allocated with this function
    //!must be deallocated only with deallocate_one().
    //!Throws boost::interprocess::bad_alloc if there is no enough memory
    pointer allocate_one()
- { return pointer(static_cast<value_type*>(this->derived()->get_node_pool()->allocate_node())); }
+ {
+ typedef typename node_pool<0>::type node_pool_t;
+ node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+ return pointer(static_cast<value_type*>(pool->allocate_node()));
+ }
 
    //!Allocates many elements of size == 1 in a contiguous chunk
    //!of memory. The minimum number to be allocated is min_elements,
@@ -424,13 +446,21 @@
    //!will be assigned to received_size. Memory allocated with this function
    //!must be deallocated only with deallocate_one().
    multiallocation_iterator allocate_individual(std::size_t num_elements)
- { return multiallocation_iterator(this->derived()->get_node_pool()->allocate_nodes(num_elements)); }
+ {
+ typedef typename node_pool<0>::type node_pool_t;
+ node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+ return multiallocation_iterator(pool->allocate_nodes(num_elements));
+ }
 
    //!Deallocates memory previously allocated with allocate_one().
    //!You should never use deallocate_one to deallocate memory allocated
    //!with other functions different from allocate_one(). Never throws
    void deallocate_one(const pointer &p)
- { this->derived()->get_node_pool()->deallocate_node(detail::get_pointer(p)); }
+ {
+ typedef typename node_pool<0>::type node_pool_t;
+ node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+ pool->deallocate_node(detail::get_pointer(p));
+ }
 
    //!Allocates many elements of size == 1 in a contiguous chunk
    //!of memory. The minimum number to be allocated is min_elements,
@@ -439,11 +469,11 @@
    //!will be assigned to received_size. Memory allocated with this function
    //!must be deallocated only with deallocate_one().
    void deallocate_individual(multiallocation_iterator it)
- { this->derived()->get_node_pool()->deallocate_nodes(it.base()); }
+ { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes(it.base()); }
 
    //!Deallocates all free chunks of the pool
    void deallocate_free_chunks()
- { this->derived()->get_node_pool()->deallocate_free_chunks(); }
+ { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_chunks(); }
 };
 
 template<class T, class NodePool, unsigned int Version>
@@ -536,7 +566,7 @@
          m_cache.cached_deallocation(detail::get_pointer(ptr));
       }
       else{
- this->get_segment_manager()->deallocate(detail::get_pointer(ptr));
+ this->get_segment_manager()->deallocate((void*)detail::get_pointer(ptr));
       }
    }
 

Modified: trunk/boost/interprocess/allocators/detail/node_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/detail/node_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/detail/node_pool.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -253,7 +253,7 @@
       while(!m_chunklist.empty()){
          void *addr = get_chunk_from_hook(&m_chunklist.front(), blocksize);
          m_chunklist.pop_front();
- mp_segment_mngr_base->deallocate(addr);
+ mp_segment_mngr_base->deallocate((void*)addr);
       }
       //Just clear free node list
       m_freelist.clear();

Modified: trunk/boost/interprocess/allocators/node_allocator.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/node_allocator.hpp (original)
+++ trunk/boost/interprocess/allocators/node_allocator.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -59,10 +59,19 @@
    typedef SegmentManager segment_manager;
    typedef node_allocator_base
       <Version, T, SegmentManager, NodesPerChunk> self_t;
- typedef detail::shared_node_pool
- < SegmentManager, sizeof(T), NodesPerChunk> node_pool_t;
- typedef typename detail::
- pointer_to_other<void_pointer, node_pool_t>::type node_pool_ptr;
+
+ /// @cond
+
+ template <int dummy>
+ struct node_pool
+ {
+ typedef detail::shared_node_pool
+ < SegmentManager, sizeof(T), NodesPerChunk> type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+ /// @endcond
 
    BOOST_STATIC_ASSERT((Version <=2));
 
@@ -104,7 +113,7 @@
       (const node_allocator_base<Version2, T2, SegmentManager2, N2>&);
 
    //!Not assignable from other node_allocator_base
- node_allocator_base& operator=(const node_allocator_base&);
+ //node_allocator_base& operator=(const node_allocator_base&);
    /// @endcond
 
    public:
@@ -112,14 +121,14 @@
    //!pool. Increments the reference count of the associated node pool.
    //!Can throw boost::interprocess::bad_alloc
    node_allocator_base(segment_manager *segment_mngr)
- : mp_node_pool(detail::get_or_create_node_pool<node_pool_t>(segment_mngr)) { }
+ : mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
 
    //!Copy constructor from other node_allocator_base. Increments the reference
    //!count of the associated node pool. Never throws
    node_allocator_base(const node_allocator_base &other)
       : mp_node_pool(other.get_node_pool())
    {
- mp_node_pool->inc_ref_count();
+ node_pool<0>::get(detail::get_pointer(mp_node_pool))->inc_ref_count();
    }
 
    //!Copy constructor from related node_allocator_base. If not present, constructs
@@ -128,22 +137,30 @@
    template<class T2>
    node_allocator_base
       (const node_allocator_base<Version, T2, SegmentManager, NodesPerChunk> &other)
- : mp_node_pool(detail::get_or_create_node_pool<node_pool_t>(other.get_segment_manager())) { }
+ : mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
+
+ //!Assignment from other node_allocator_base
+ node_allocator_base& operator=(const node_allocator_base &other)
+ {
+ node_allocator_base c(other);
+ swap(*this, c);
+ return *this;
+ }
 
    //!Destructor, removes node_pool_t from memory
    //!if its reference count reaches to zero. Never throws
    ~node_allocator_base()
- { detail::destroy_node_pool_if_last_link(detail::get_pointer(mp_node_pool)); }
+ { detail::destroy_node_pool_if_last_link(node_pool<0>::get(detail::get_pointer(mp_node_pool))); }
 
    //!Returns a pointer to the node pool.
    //!Never throws
- node_pool_t* get_node_pool() const
+ void* get_node_pool() const
    { return detail::get_pointer(mp_node_pool); }
 
    //!Returns the segment manager.
    //!Never throws
    segment_manager* get_segment_manager()const
- { return mp_node_pool->get_segment_manager(); }
+ { return node_pool<0>::get(detail::get_pointer(mp_node_pool))->get_segment_manager(); }
 
    //!Swaps allocators. Does not throw. If each allocator is placed in a
    //!different memory segment, the result is undefined.
@@ -152,22 +169,22 @@
 
    /// @cond
    private:
- node_pool_ptr mp_node_pool;
+ void_pointer mp_node_pool;
    /// @endcond
 };
 
 //!Equality test for same type
 //!of node_allocator_base
-template<unsigned int V, class T, class S, std::size_t NodesPerChunk> inline
-bool operator==(const node_allocator_base<V, T, S, NodesPerChunk> &alloc1,
- const node_allocator_base<V, T, S, NodesPerChunk> &alloc2)
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator==(const node_allocator_base<V, T, S, NPC> &alloc1,
+ const node_allocator_base<V, T, S, NPC> &alloc2)
    { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
 
 //!Inequality test for same type
 //!of node_allocator_base
-template<unsigned int V, class T, class S, std::size_t NodesPerChunk, std::size_t F, unsigned char OP> inline
-bool operator!=(const node_allocator_base<V, T, S, NodesPerChunk> &alloc1,
- const node_allocator_base<V, T, S, NodesPerChunk> &alloc2)
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator!=(const node_allocator_base<V, T, S, NPC> &alloc1,
+ const node_allocator_base<V, T, S, NPC> &alloc2)
    { return alloc1.get_node_pool() != alloc2.get_node_pool(); }
 
 template < class T
@@ -283,7 +300,7 @@
 
    //!Not assignable from
    //!other node_allocator
- node_allocator& operator=(const node_allocator&);
+ //node_allocator& operator=(const node_allocator&);
 
    public:
    //!Constructor from a segment manager. If not present, constructs a node
@@ -308,7 +325,7 @@
 
    //!Returns a pointer to the node pool.
    //!Never throws
- node_pool_t* get_node_pool() const;
+ void* get_node_pool() const;
 
    //!Returns the segment manager.
    //!Never throws
@@ -342,9 +359,9 @@
    //!Never throws
    const_pointer address(const_reference value) const;
 
- //!Default construct an object.
- //!Throws if T's default constructor throws
- void construct(const pointer &ptr);
+ //!Copy construct an object.
+ //!Throws if T's copy constructor throws
+ void construct(const pointer &ptr, const_reference v);
 
    //!Destroys object. Throws if object's
    //!destructor throws
@@ -414,15 +431,15 @@
 
 //!Equality test for same type
 //!of node_allocator
-template<class T, class S, std::size_t NodesPerChunk, std::size_t F, unsigned char OP> inline
-bool operator==(const node_allocator<T, S, NodesPerChunk, F, OP> &alloc1,
- const node_allocator<T, S, NodesPerChunk, F, OP> &alloc2);
+template<class T, class S, std::size_t NPC> inline
+bool operator==(const node_allocator<T, S, NPC> &alloc1,
+ const node_allocator<T, S, NPC> &alloc2);
 
 //!Inequality test for same type
 //!of node_allocator
-template<class T, class S, std::size_t NodesPerChunk, std::size_t F, unsigned char OP> inline
-bool operator!=(const node_allocator<T, S, NodesPerChunk, F, OP> &alloc1,
- const node_allocator<T, S, NodesPerChunk, F, OP> &alloc2);
+template<class T, class S, std::size_t NPC> inline
+bool operator!=(const node_allocator<T, S, NPC> &alloc1,
+ const node_allocator<T, S, NPC> &alloc2);
 
 #endif
 

Modified: trunk/boost/interprocess/allocators/private_adaptive_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/private_adaptive_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/private_adaptive_pool.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -104,6 +104,22 @@
    };
 
    /// @cond
+
+ template <int dummy>
+ struct node_pool
+ {
+ typedef detail::private_adaptive_node_pool
+ <SegmentManager
+ , sizeof(T)
+ , NodesPerChunk
+ , MaxFreeChunks
+ , OverheadPercent
+ > type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+
    private:
    //!Not assignable from related private_adaptive_pool_base
    template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2, std::size_t F2, unsigned char OP2>
@@ -355,9 +371,9 @@
    //!Never throws
    const_pointer address(const_reference value) const;
 
- //!Default construct an object.
- //!Throws if T's default constructor throws
- void construct(const pointer &ptr);
+ //!Copy construct an object.
+ //!Throws if T's copy constructor throws
+ void construct(const pointer &ptr, const_reference v);
 
    //!Destroys object. Throws if object's
    //!destructor throws

Modified: trunk/boost/interprocess/allocators/private_node_allocator.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/private_node_allocator.hpp (original)
+++ trunk/boost/interprocess/allocators/private_node_allocator.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -7,201 +7,6 @@
 // See http://www.boost.org/libs/interprocess for documentation.
 //
 //////////////////////////////////////////////////////////////////////////////
-/*
-#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
-#define BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
-
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif
-
-#include <boost/interprocess/detail/config_begin.hpp>
-#include <boost/interprocess/detail/workaround.hpp>
-
-#include <boost/interprocess/interprocess_fwd.hpp>
-#include <boost/assert.hpp>
-#include <boost/utility/addressof.hpp>
-#include <boost/interprocess/allocators/detail/node_pool.hpp>
-#include <boost/interprocess/exceptions.hpp>
-#include <boost/interprocess/detail/utilities.hpp>
-#include <boost/interprocess/detail/workaround.hpp>
-#include <memory>
-#include <algorithm>
-#include <cstddef>
-
-//!\file
-//!Describes private_node_allocator pooled shared memory STL compatible allocator
-
-namespace boost {
-namespace interprocess {
-
-//!An STL node allocator that uses a segment manager as memory
-//!source. The internal pointer type will of the same type (raw, smart) as
-//!"typename SegmentManager::void_pointer" type. This allows
-//!placing the allocator in shared memory, memory mapped-files, etc...
-//!This allocator has its own node pool. NodesPerChunk is the number of nodes allocated
-//!at once when the allocator needs runs out of nodes
-template<class T, class SegmentManager, std::size_t NodesPerChunk>
-class private_node_allocator
-{
- /// @cond
- private:
- typedef typename SegmentManager::void_pointer void_pointer;
- typedef typename detail::
- pointer_to_other<void_pointer, const void>::type cvoid_pointer;
- typedef SegmentManager segment_manager;
- typedef typename detail::pointer_to_other
- <void_pointer, segment_manager>::type segment_mngr_ptr_t;
- typedef private_node_allocator
- <T, SegmentManager, NodesPerChunk> self_t;
- typedef detail::private_node_pool
- <SegmentManager, sizeof(T), NodesPerChunk> priv_node_pool_t;
- /// @endcond
-
- public:
- //-------
- typedef typename detail::
- pointer_to_other<void_pointer, T>::type pointer;
- typedef typename detail::
- pointer_to_other<void_pointer, const T>::type const_pointer;
- typedef T value_type;
- typedef typename detail::add_reference
- <value_type>::type reference;
- typedef typename detail::add_reference
- <const value_type>::type const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- //!Obtains node_allocator from other node_allocator
- template<class T2>
- struct rebind
- {
- typedef private_node_allocator<T2, SegmentManager, NodesPerChunk> other;
- };
-
- /// @cond
- private:
- //!Not assignable from related private_node_allocator
- template<class T2, class MemoryAlgorithm2, std::size_t N2>
- private_node_allocator& operator=
- (const private_node_allocator<T2, MemoryAlgorithm2, N2>&);
-
- //!Not assignable from other private_node_allocator
- private_node_allocator& operator=(const private_node_allocator&);
- /// @endcond
-
- public:
-
- //!Constructor from a segment manager
- private_node_allocator(segment_manager *segment_mngr)
- : m_node_pool(segment_mngr){}
-
- //!Copy constructor from other private_node_allocator. Never throws
- private_node_allocator(const private_node_allocator &other)
- : m_node_pool(other.get_segment_manager()){}
-
- //!Copy constructor from related private_node_allocator. Never throws.
- template<class T2>
- private_node_allocator
- (const private_node_allocator<T2, SegmentManager, NodesPerChunk> &other)
- : m_node_pool(other.get_segment_manager())
- {}
-
- //!Destructor, frees all used memory. Never throws
- ~private_node_allocator()
- {}
-
- //!Returns the segment manager. Never throws
- segment_manager* get_segment_manager()const
- { return m_node_pool.get_segment_manager(); }
-
- //!Returns the number of elements that could be allocated. Never throws
- size_type max_size() const
- { return this->get_segment_manager()->get_size()/sizeof(value_type); }
-
- //!Allocate memory for an array of count elements.
- //!Throws boost::interprocess::bad_alloc if there is no enough memory
- pointer allocate(size_type count, cvoid_pointer hint = 0)
- {
- (void)hint;
- if(count > this->max_size())
- throw bad_alloc();
- else if(count == 1)
- return pointer(static_cast<value_type*>(m_node_pool.allocate_node()));
- else
- return pointer(static_cast<value_type*>
- (m_node_pool.get_segment_manager()->allocate(sizeof(T)*count)));
- }
-
- //!Deallocate allocated memory. Never throws
- void deallocate(const pointer &ptr, size_type count)
- {
- if(count == 1)
- m_node_pool.deallocate_node(detail::get_pointer(ptr));
- else
- m_node_pool.get_segment_manager()->deallocate(detail::get_pointer(ptr));
- }
-
- //!Deallocates all free chunks of the pool
- void deallocate_free_chunks()
- { m_node_pool.deallocate_free_chunks(); }
-
- //!Swaps allocators. Does not throw. If each allocator is placed in a
- //!different shared memory segments, the result is undefined.
- friend void swap(self_t &alloc1,self_t &alloc2)
- { alloc1.m_node_pool.swap(alloc2.m_node_pool); }
-
- //These functions are obsolete. These are here to conserve
- //backwards compatibility with containers using them...
-
- //!Returns address of mutable object.
- //!Never throws
- pointer address(reference value) const
- { return pointer(boost::addressof(value)); }
-
- //!Returns address of non mutable object.
- //!Never throws
- const_pointer address(const_reference value) const
- { return const_pointer(boost::addressof(value)); }
-
- //!Default construct an object.
- //!Throws if T's default constructor throws
- void construct(const pointer &ptr)
- { new(detail::get_pointer(ptr)) value_type; }
-
- //!Destroys object. Throws if object's
- //!destructor throws
- void destroy(const pointer &ptr)
- { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); }
-
- /// @cond
- private:
- priv_node_pool_t m_node_pool;
- /// @endcond
-};
-
-//!Equality test for same type of private_node_allocator
-template<class T, class S, std::size_t NodesPerChunk> inline
-bool operator==(const private_node_allocator<T, S, NodesPerChunk> &alloc1,
- const private_node_allocator<T, S, NodesPerChunk> &alloc2)
-{ return &alloc1 == &alloc2; }
-
-//!Inequality test for same type of private_node_allocator
-template<class T, class S, std::size_t NodesPerChunk> inline
-bool operator!=(const private_node_allocator<T, S, NodesPerChunk> &alloc1,
- const private_node_allocator<T, S, NodesPerChunk> &alloc2)
-{
- return &alloc1 != &alloc2;
-}
-
-} //namespace interprocess {
-} //namespace boost {
-
-#include <boost/interprocess/detail/config_end.hpp>
-
-#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
-
-*/
 
 //////////////////////////////////////////////////////////////////////////////
 //
@@ -303,6 +108,19 @@
    };
 
    /// @cond
+ template <int dummy>
+ struct node_pool
+ {
+ typedef detail::private_node_pool
+ <SegmentManager
+ , sizeof(T)
+ , NodesPerChunk
+ > type;
+
+ static type *get(void *p)
+ { return static_cast<type*>(p); }
+ };
+
    private:
    //!Not assignable from related private_node_allocator_base
    template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2>
@@ -356,15 +174,15 @@
 };
 
 //!Equality test for same type of private_node_allocator_base
-template<unsigned int V, class T, class S, std::size_t NodesPerChunk> inline
-bool operator==(const private_node_allocator_base<V, T, S, NodesPerChunk> &alloc1,
- const private_node_allocator_base<V, T, S, NodesPerChunk> &alloc2)
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator==(const private_node_allocator_base<V, T, S, NPC> &alloc1,
+ const private_node_allocator_base<V, T, S, NPC> &alloc2)
 { return &alloc1 == &alloc2; }
 
 //!Inequality test for same type of private_node_allocator_base
-template<unsigned int V, class T, class S, std::size_t NodesPerChunk> inline
-bool operator!=(const private_node_allocator_base<V, T, S, NodesPerChunk> &alloc1,
- const private_node_allocator_base<V, T, S, NodesPerChunk> &alloc2)
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator!=(const private_node_allocator_base<V, T, S, NPC> &alloc1,
+ const private_node_allocator_base<V, T, S, NPC> &alloc2)
 { return &alloc1 != &alloc2; }
 
 template < class T
@@ -539,9 +357,9 @@
    //!Never throws
    const_pointer address(const_reference value) const;
 
- //!Default construct an object.
- //!Throws if T's default constructor throws
- void construct(const pointer &ptr);
+ //!Copy construct an object.
+ //!Throws if T's copy constructor throws
+ void construct(const pointer &ptr, const_reference v);
 
    //!Destroys object. Throws if object's
    //!destructor throws

Modified: trunk/boost/interprocess/containers/deque.hpp
==============================================================================
--- trunk/boost/interprocess/containers/deque.hpp (original)
+++ trunk/boost/interprocess/containers/deque.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -658,7 +658,7 @@
    void push_back(const value_type& t)
    {
       if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) {
- new(detail::get_pointer(this->members_.m_finish.m_cur))value_type(t);
+ new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(t);
          ++this->members_.m_finish.m_cur;
       }
       else
@@ -669,7 +669,7 @@
    void push_back(const detail::moved_object<value_type> &mt)
    {
       if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) {
- new(detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt);
+ new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt);
          ++this->members_.m_finish.m_cur;
       }
       else
@@ -679,7 +679,7 @@
    void push_back(value_type &&mt)
    {
       if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) {
- new(detail::get_pointer(this->members_.m_finish.m_cur))value_type(move(mt));
+ new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(move(mt));
          ++this->members_.m_finish.m_cur;
       }
       else
@@ -690,7 +690,7 @@
    void push_front(const value_type& t)
    {
       if (this->members_.m_start.m_cur != this->members_.m_start.m_first) {
- new(detail::get_pointer(this->members_.m_start.m_cur)- 1)value_type(t);
+ new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(t);
          --this->members_.m_start.m_cur;
       }
       else
@@ -701,7 +701,7 @@
    void push_front(const detail::moved_object<value_type> &mt)
    {
       if (this->members_.m_start.m_cur != this->members_.m_start.m_first) {
- new(detail::get_pointer(this->members_.m_start.m_cur)- 1)value_type(mt);
+ new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(mt);
          --this->members_.m_start.m_cur;
       }
       else
@@ -711,7 +711,7 @@
    void push_front(value_type &&mt)
    {
       if (this->members_.m_start.m_cur != this->members_.m_start.m_first) {
- new(detail::get_pointer(this->members_.m_start.m_cur)- 1)value_type(move(mt));
+ new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(move(mt));
          --this->members_.m_start.m_cur;
       }
       else
@@ -1217,7 +1217,7 @@
       this->priv_reserve_map_at_back();
       *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node();
       BOOST_TRY {
- new(detail::get_pointer(this->members_.m_finish.m_cur))value_type(t);
+ new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(t);
          this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1);
          this->members_.m_finish.m_cur = this->members_.m_finish.m_first;
       }
@@ -1235,7 +1235,7 @@
       this->priv_reserve_map_at_back();
       *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node();
       BOOST_TRY {
- new(detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt);
+ new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt);
          this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1);
          this->members_.m_finish.m_cur = this->members_.m_finish.m_first;
       }
@@ -1251,7 +1251,7 @@
       this->priv_reserve_map_at_back();
       *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node();
       BOOST_TRY {
- new(detail::get_pointer(this->members_.m_finish.m_cur))value_type(move(mt));
+ new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(move(mt));
          this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1);
          this->members_.m_finish.m_cur = this->members_.m_finish.m_first;
       }
@@ -1271,7 +1271,7 @@
       BOOST_TRY {
          this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1);
          this->members_.m_start.m_cur = this->members_.m_start.m_last - 1;
- new(detail::get_pointer(this->members_.m_start.m_cur))value_type(t);
+ new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(t);
       }
       BOOST_CATCH(...){
          ++this->members_.m_start;
@@ -1289,7 +1289,7 @@
       BOOST_TRY {
          this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1);
          this->members_.m_start.m_cur = this->members_.m_start.m_last - 1;
- new(detail::get_pointer(this->members_.m_start.m_cur))value_type(mt);
+ new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(mt);
       }
       BOOST_CATCH(...){
          ++this->members_.m_start;
@@ -1306,7 +1306,7 @@
       BOOST_TRY {
          this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1);
          this->members_.m_start.m_cur = this->members_.m_start.m_last - 1;
- new(detail::get_pointer(this->members_.m_start.m_cur))value_type(move(mt));
+ new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(move(mt));
       }
       BOOST_CATCH(...){
          ++this->members_.m_start;

Modified: trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp
==============================================================================
--- trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp (original)
+++ trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -145,15 +145,15 @@
    #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
    template<class Convertible>
    static void construct(const NodePtr &ptr, const Convertible &value)
- { new(detail::get_pointer(ptr)) Node(value); }
+ { new((void*)detail::get_pointer(ptr)) Node(value); }
    #else
    template<class Convertible>
    static void construct(const NodePtr &ptr, Convertible &&value)
- { new(detail::get_pointer(ptr)) Node(forward<Convertible>(value)); }
+ { new((void*)detail::get_pointer(ptr)) Node(forward<Convertible>(value)); }
    #endif
 
    static void construct(const NodePtr &ptr)
- { new(detail::get_pointer(ptr)) Node(); }
+ { new((void*)detail::get_pointer(ptr)) Node(); }
 
    #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
    template<class Convertible1, class Convertible2>

Modified: trunk/boost/interprocess/containers/string.hpp
==============================================================================
--- trunk/boost/interprocess/containers/string.hpp (original)
+++ trunk/boost/interprocess/containers/string.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -308,7 +308,7 @@
    }
 
    void construct(pointer p, const value_type &value = value_type())
- { new(detail::get_pointer(p)) value_type(value); }
+ { new((void*)detail::get_pointer(p)) value_type(value); }
 
    void destroy(pointer p, size_type n)
    {

Modified: trunk/boost/interprocess/containers/vector.hpp
==============================================================================
--- trunk/boost/interprocess/containers/vector.hpp (original)
+++ trunk/boost/interprocess/containers/vector.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -301,8 +301,8 @@
                          const pointer &reuse,
                          allocator_v2)
    {
- return this->alloc().allocation_command(command, limit_size, preferred_size,
- received_size, reuse);
+ return this->alloc().allocation_command
+ (command, limit_size, preferred_size, received_size, reuse);
    }
 
    size_type next_capacity(size_type additional_objects) const
@@ -434,7 +434,7 @@
    //This is the optimized move iterator for copy constructors
    //so that std::copy and similar can use memcpy
    typedef typename detail::if_c
- <base_t::trivial_copy
+ <base_t::trivial_copy || !is_movable<value_type>::value
       ,T*
       ,detail::move_iterator<T*>
>::type copy_move_it;
@@ -442,7 +442,7 @@
    //This is the optimized move iterator for assignments
    //so that std::uninitialized_copy and similar can use memcpy
    typedef typename detail::if_c
- <base_t::trivial_assign
+ <base_t::trivial_assign || !is_movable<value_type>::value
       ,T*
       ,detail::move_iterator<T*>
>::type assign_move_it;
@@ -859,7 +859,7 @@
    {
       if (this->members_.m_size < this->members_.m_capacity){
          //There is more memory, just construct a new object at the end
- new(detail::get_pointer(this->members_.m_start) + this->members_.m_size)value_type(x);
+ new((void*)(detail::get_pointer(this->members_.m_start) + this->members_.m_size))value_type(x);
          ++this->members_.m_size;
       }
       else{
@@ -878,7 +878,7 @@
    {
       if (this->members_.m_size < this->members_.m_capacity){
          //There is more memory, just construct a new object at the end
- new(detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(mx);
+ new((void*)detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(mx);
          ++this->members_.m_size;
       }
       else{
@@ -890,7 +890,7 @@
    {
       if (this->members_.m_size < this->members_.m_capacity){
          //There is more memory, just construct a new object at the end
- new(detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(move(mx));
+ new((void*)detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(move(mx));
          ++this->members_.m_size;
       }
       else{
@@ -1101,7 +1101,7 @@
          T *ptr = detail::get_pointer(this->members_.m_start + this->members_.m_size);
          while(n--){
             //Default construct
- new(ptr++)T();
+ new((void*)ptr++)T();
             ++this->members_.m_size;
          }
       }
@@ -1241,9 +1241,9 @@
          std::uninitialized_copy(copy_move_it(old_finish - n), copy_move_it(old_finish), old_finish);
          this->members_.m_size += n;
          //Copy previous to last objects to the initialized end
- std::copy_backward(assign_move_it(detail::get_pointer(pos)), assign_move_it(old_finish - n), old_finish);
+ std::copy_backward(assign_move_it(pos), assign_move_it(old_finish - n), old_finish);
          //Insert new objects in the pos
- std::copy(first, last, detail::get_pointer(pos));
+ std::copy(first, last, pos);
       }
       else {
          //The new elements don't fit in the [pos, end()) range. Copy
@@ -1254,12 +1254,12 @@
          this->members_.m_size += n - elems_after;
          //Copy old [pos, end()) elements to the uninitialized memory
          std::uninitialized_copy
- ( copy_move_it(detail::get_pointer(pos))
+ ( copy_move_it(pos)
             , copy_move_it(old_finish)
             , detail::get_pointer(this->members_.m_start) + this->members_.m_size);
          this->members_.m_size += elems_after;
          //Copy first new elements in pos
- std::copy(first, mid, detail::get_pointer(pos));
+ std::copy(first, mid, pos);
       }
    }
 
@@ -1277,7 +1277,7 @@
       //the start of the new buffer
       new_finish = std::uninitialized_copy
          ( copy_move_it(detail::get_pointer(this->members_.m_start))
- , copy_move_it(detail::get_pointer(pos))
+ , copy_move_it(pos)
          , old_finish = new_finish);
       construted_values_destroyer.increment_size(new_finish - old_finish);
       //Initialize new objects, starting from previous point
@@ -1287,9 +1287,9 @@
       //Initialize from the rest of the old buffer,
       //starting from previous point
       new_finish = std::uninitialized_copy
- ( copy_move_it(detail::get_pointer(pos))
+ ( copy_move_it(pos)
          , copy_move_it(detail::get_pointer(this->members_.m_start) + this->members_.m_size)
- , detail::get_pointer(new_finish));
+ , new_finish);
 
       //All construction successful, disable rollbacks
       construted_values_destroyer.release();
@@ -1345,13 +1345,11 @@
          //Copy first old values before pos, after that the
          //new objects
          boost::interprocess::uninitialized_copy_copy
- (copy_move_it(old_start), copy_move_it(detail::get_pointer(pos)), first, last, detail::get_pointer(new_start));
+ (copy_move_it(old_start), copy_move_it(pos), first, last, new_start);
          UCopiedArrayDestructor new_values_destroyer(new_start, elemsbefore);
          //Now initialize the rest of memory with the last old values
          std::uninitialized_copy
- ( copy_move_it(detail::get_pointer(pos))
- , copy_move_it(old_finish)
- , detail::get_pointer(new_start) + elemsbefore + n);
+ (copy_move_it(pos), copy_move_it(old_finish), new_start + elemsbefore + n);
          //All new elements correctly constructed, avoid new element destruction
          new_values_destroyer.release();
          this->members_.m_size = old_size + n;
@@ -1376,17 +1374,13 @@
          //Copy first old values before pos, after that the
          //new objects
          boost::interprocess::uninitialized_copy_copy
- ( copy_move_it(old_start)
- , copy_move_it(detail::get_pointer(pos))
- , first, last, detail::get_pointer(new_start));
+ (copy_move_it(old_start), copy_move_it(pos), first, last, new_start);
          UCopiedArrayDestructor new_values_destroyer(new_start, elemsbefore);
          size_type raw_gap = s_before - (elemsbefore + n);
          //Now initialize the rest of s_before memory with the
          //first of elements after new values
          std::uninitialized_copy
- ( copy_move_it(detail::get_pointer(pos))
- , copy_move_it(detail::get_pointer(pos) + raw_gap)
- , detail::get_pointer(new_start) + elemsbefore + n);
+ (copy_move_it(pos), copy_move_it(pos + raw_gap), new_start + elemsbefore + n);
          //All new elements correctly constructed, avoid new element destruction
          new_values_destroyer.release();
          //All new elements correctly constructed, avoid old element destruction
@@ -1394,7 +1388,7 @@
          //Update size since we have a contiguous buffer
          this->members_.m_size = old_size + s_before;
          //Now copy remaining last objects in the old buffer begin
- T *to_destroy = std::copy(assign_move_it(detail::get_pointer(pos) + raw_gap), assign_move_it(old_finish), old_start);
+ T *to_destroy = std::copy(assign_move_it(pos + raw_gap), assign_move_it(old_finish), old_start);
          //Now destroy redundant elements except if they were moved and
          //they have trivial destructor after move
          size_type n_destroy = old_finish - to_destroy;
@@ -1460,24 +1454,22 @@
             //Copy the first part of old_begin to raw_mem
             T *start_n = old_start + difference_type(s_before);
             std::uninitialized_copy
- ( copy_move_it(old_start)
- , copy_move_it(start_n)
- , detail::get_pointer(new_start));
+ (copy_move_it(old_start), copy_move_it(start_n), new_start);
             //The buffer is all constructed until old_end,
             //release destroyer and update size
             old_values_destroyer.release();
             this->members_.m_size = old_size + s_before;
             //Now copy the second part of old_begin overwriting himself
- T* next = std::copy(assign_move_it(start_n), assign_move_it(detail::get_pointer(pos)), old_start);
+ T* next = std::copy(assign_move_it(start_n), assign_move_it(pos), old_start);
             if(do_after){
                //Now copy the new_beg elements
- std::copy(first, before_end, detail::get_pointer(next));
+ std::copy(first, before_end, next);
             }
             else{
                //Now copy the all the new elements
- T* move_start = std::copy(first, last, detail::get_pointer(next));
+ T* move_start = std::copy(first, last, next);
                //Now displace old_end elements
- T* move_end = std::copy(assign_move_it(detail::get_pointer(pos)), assign_move_it(old_finish), detail::get_pointer(move_start));
+ T* move_end = std::copy(assign_move_it(pos), assign_move_it(old_finish), move_start);
                //Destroy remaining moved elements from old_end except if
                //they have trivial destructor after being moved
                difference_type n_destroy = s_before - n;
@@ -1513,9 +1505,7 @@
             size_type n_new_init = difference_type(s_before) - elemsbefore;
             std::advance(mid, n_new_init);
             boost::interprocess::uninitialized_copy_copy
- ( copy_move_it(old_start)
- , copy_move_it(detail::get_pointer(pos))
- , first, mid, detail::get_pointer(new_start));
+ (copy_move_it(old_start), copy_move_it(pos), first, mid, new_start);
             //The buffer is all constructed until old_end,
             //release destroyer and update size
             old_values_destroyer.release();
@@ -1529,7 +1519,7 @@
                //Copy all new elements
                T* move_start = std::copy(mid, last, old_start);
                //Displace old_end
- T* move_end = std::copy(copy_move_it(detail::get_pointer(pos)), copy_move_it(old_finish), detail::get_pointer(move_start));
+ T* move_end = std::copy(copy_move_it(pos), copy_move_it(old_finish), move_start);
                //Destroy remaining moved elements from old_end except if they
                //have trivial destructor after being moved
                difference_type n_destroy = s_before - n;
@@ -1584,14 +1574,12 @@
                //First copy the part of old_end raw_mem
                T* finish_n = old_finish - difference_type(n_after);
                std::uninitialized_copy
- ( copy_move_it(detail::get_pointer(finish_n))
- , copy_move_it(old_finish)
- , old_finish);
+ (copy_move_it(finish_n), copy_move_it(old_finish), old_finish);
                this->members_.m_size += n_after;
                //Displace the rest of old_end to the new position
- std::copy_backward(assign_move_it(detail::get_pointer(pos)), assign_move_it(detail::get_pointer(finish_n)), old_finish);
+ std::copy_backward(assign_move_it(pos), assign_move_it(finish_n), old_finish);
                //Now overwrite with new_end
- std::copy(first, last, detail::get_pointer(pos));
+ std::copy(first, last, pos);
             }
             else {
                //The raw_mem from end will divide new_end part
@@ -1610,13 +1598,10 @@
                std::advance(mid, elemsafter);
                //First initialize data in raw memory
                boost::interprocess::uninitialized_copy_copy
- ( mid, last
- , copy_move_it(detail::get_pointer(pos))
- , copy_move_it(old_finish)
- , old_finish);
+ ( mid, last, copy_move_it(pos), copy_move_it(old_finish), old_finish);
                this->members_.m_size += n_after;
                //Now copy the part of new_end over constructed elements
- std::copy(first, mid, detail::get_pointer(pos));
+ std::copy(first, mid, pos);
             }
          }
       }

Modified: trunk/boost/interprocess/detail/algorithms.hpp
==============================================================================
--- trunk/boost/interprocess/detail/algorithms.hpp (original)
+++ trunk/boost/interprocess/detail/algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -43,7 +43,7 @@
 template<class T, class InpIt>
 inline void construct_in_place_impl(T* dest, const InpIt &source, detail::false_)
 {
- new(dest)T(*source);
+ new((void*)dest)T(*source);
 }
 
 } //namespace detail {
@@ -58,7 +58,7 @@
 template<class T, class U, class D>
 inline void construct_in_place(T *dest, default_construct_iterator<U, D>)
 {
- new(dest)T();
+ new((void*)dest)T();
 }
 
 template<class InIt, class OutIt>

Modified: trunk/boost/interprocess/detail/config_begin.hpp
==============================================================================
--- trunk/boost/interprocess/detail/config_begin.hpp (original)
+++ trunk/boost/interprocess/detail/config_begin.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -30,4 +30,5 @@
    #pragma warning (disable : 4711) // function selected for automatic inline expansion
    #pragma warning (disable : 4786) // identifier truncated in debug info
    #pragma warning (disable : 4996) // 'function': was declared deprecated
+ #pragma warning (disable : 4197) // top-level volatile in cast is ignored
 #endif

Modified: trunk/boost/interprocess/detail/move.hpp
==============================================================================
--- trunk/boost/interprocess/detail/move.hpp (original)
+++ trunk/boost/interprocess/detail/move.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -79,7 +79,7 @@
    public:
    typedef T type;
 
- move_return(T& returned)
+ move_return(const T& returned)
       : m_moved(moved_object<T>(returned))
    {}
 

Modified: trunk/boost/interprocess/detail/mpl.hpp
==============================================================================
--- trunk/boost/interprocess/detail/mpl.hpp (original)
+++ trunk/boost/interprocess/detail/mpl.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -17,7 +17,7 @@
 # pragma once
 #endif
 
-//#include <functional>
+#include <cstddef>
 
 namespace boost {
 namespace interprocess {
@@ -121,6 +121,24 @@
    { return x; }
 };
 
+template<std::size_t S>
+struct ls_zeros
+{
+ static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
+};
+
+template<>
+struct ls_zeros<0>
+{
+ static const std::size_t value = 0;
+};
+
+template<>
+struct ls_zeros<1>
+{
+ static const std::size_t value = 0;
+};
+
 } //namespace detail {
 } //namespace interprocess {
 } //namespace boost {

Modified: trunk/boost/interprocess/detail/named_proxy.hpp
==============================================================================
--- trunk/boost/interprocess/detail/named_proxy.hpp (original)
+++ trunk/boost/interprocess/detail/named_proxy.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -48,13 +48,13 @@
    self_t operator++(int) { return *this; }
 
    void construct(void *mem)
- { new(mem)T; }
+ { new((void*)mem)T; }
 
    virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
    {
- T* memory = static_cast<T*>(mem);
+ T* memory = (T*)(mem);
       for(constructed = 0; constructed < num; ++constructed)
- new(memory++)T;
+ new((void*)memory++)T;
    }
 };
 
@@ -88,13 +88,13 @@
 // : p1((P1 &)p_1), p2((P2 &)p_2) {}
 //
 // void construct(void *mem)
-// { new(object)T(m_p1, m_p2); }
+// { new((void*)object)T(m_p1, m_p2); }
 //
 // virtual void construct_n(void *mem
 // , std::size_t num
 // , std::size_t &constructed)
 // {
-// T* memory = static_cast<T*>(mem);
+// T* memory = (T*)(mem);
 // for(constructed = 0; constructed < num; ++constructed){
 // this->construct(memory++, IsIterator());
 // this->do_increment(IsIterator());
@@ -103,10 +103,10 @@
 //
 // private:
 // void construct(void *mem, detail::true_)
-// { new(mem)T(*m_p1, *m_p2); }
+// { new((void*)mem)T(*m_p1, *m_p2); }
 //
 // void construct(void *mem, detail::false_)
-// { new(mem)T(m_p1, m_p2); }
+// { new((void*)mem)T(m_p1, m_p2); }
 //
 // P1 &m_p1; P2 &m_p2;
 // };
@@ -163,7 +163,7 @@
                         , std::size_t num \
                         , std::size_t &constructed) \
       { \
- T* memory = static_cast<T*>(mem); \
+ T* memory = (T*)(mem); \
          for(constructed = 0; constructed < num; ++constructed){ \
             this->construct(memory++, IsIterator()); \
             this->do_increment(IsIterator()); \
@@ -172,10 +172,10 @@
                                                                            \
       private: \
       void construct(void *mem, detail::true_) \
- { new(mem)T(BOOST_PP_ENUM_PARAMS(n, *m_p)); } \
+ { new((void*)mem)T(BOOST_PP_ENUM_PARAMS(n, *m_p)); } \
                                                                            \
       void construct(void *mem, detail::false_) \
- { new(mem)T(BOOST_PP_ENUM_PARAMS(n, m_p)); } \
+ { new((void*)mem)T(BOOST_PP_ENUM_PARAMS(n, m_p)); } \
                                                                            \
       BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \
    }; \

Modified: trunk/boost/interprocess/detail/utilities.hpp
==============================================================================
--- trunk/boost/interprocess/detail/utilities.hpp (original)
+++ trunk/boost/interprocess/detail/utilities.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -373,11 +373,24 @@
    return ((orig_size-1)/round_to+1)*round_to;
 }
 
+//Truncates "orig_size" to a multiple of "multiple" bytes.
 inline std::size_t get_truncated_size(std::size_t orig_size, std::size_t multiple)
 {
    return orig_size/multiple*multiple;
 }
-
+
+//Rounds "orig_size" by excess to round_to bytes. round_to must be power of two
+inline std::size_t get_rounded_size_po2(std::size_t orig_size, std::size_t round_to)
+{
+ return ((orig_size-1)&(~(round_to-1))) + round_to;
+}
+
+//Truncates "orig_size" to a multiple of "multiple" bytes. multiple must be power of two
+inline std::size_t get_truncated_size_po2(std::size_t orig_size, std::size_t multiple)
+{
+ return (orig_size & (~(multiple-1)));
+}
+
 template <std::size_t OrigSize, std::size_t RoundTo>
 struct ct_rounded_size
 {

Modified: trunk/boost/interprocess/ipc/message_queue.hpp
==============================================================================
--- trunk/boost/interprocess/ipc/message_queue.hpp (original)
+++ trunk/boost/interprocess/ipc/message_queue.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -98,7 +98,7 @@
 
    //!Sends a message stored in buffer "buffer" with size "buffer_size" in the
    //!message queue with priority "priority". If the message queue is full
- //!the sender is retries until time "abs_time" is reached. Returns true if
+ //!the sender retries until time "abs_time" is reached. Returns true if
    //!the message has been successfully sent. Returns false if timeout is reached.
    //!Throws interprocess_error on error.
    bool timed_send (const void *buffer, std::size_t buffer_size,
@@ -106,23 +106,23 @@
 
    //!Receives a message from the message queue. The message is stored in buffer
    //!"buffer", which has size "buffer_size". The received message has size
- //!"recvd_size" and priority "priority". If the message queue is full
- //!the sender is blocked. Throws interprocess_error on error.
+ //!"recvd_size" and priority "priority". If the message queue is empty
+ //!the receiver is blocked. Throws interprocess_error on error.
    void receive (void *buffer, std::size_t buffer_size,
                  std::size_t &recvd_size,unsigned int &priority);
 
    //!Receives a message from the message queue. The message is stored in buffer
    //!"buffer", which has size "buffer_size". The received message has size
- //!"recvd_size" and priority "priority". If the message queue is full
- //!the sender is not blocked and returns false, otherwise returns true.
+ //!"recvd_size" and priority "priority". If the message queue is empty
+ //!the receiver is not blocked and returns false, otherwise returns true.
    //!Throws interprocess_error on error.
    bool try_receive (void *buffer, std::size_t buffer_size,
                      std::size_t &recvd_size,unsigned int &priority);
 
    //!Receives a message from the message queue. The message is stored in buffer
    //!"buffer", which has size "buffer_size". The received message has size
- //!"recvd_size" and priority "priority". If the message queue is full
- //!the sender is retries until time "abs_time" is reached. Returns true if
+ //!"recvd_size" and priority "priority". If the message queue is empty
+ //!the receiver retries until time "abs_time" is reached. Returns true if
    //!the message has been successfully sent. Returns false if timeout is reached.
    //!Throws interprocess_error on error.
    bool timed_receive (void *buffer, std::size_t buffer_size,

Modified: trunk/boost/interprocess/mapped_region.hpp
==============================================================================
--- trunk/boost/interprocess/mapped_region.hpp (original)
+++ trunk/boost/interprocess/mapped_region.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -45,6 +45,8 @@
 
 /// @cond
 namespace detail{ class interprocess_tester; }
+namespace detail{ class raw_mapped_region_creator; }
+
 /// @endcond
 
 //!The mapped_region class represents a portion or region created from a
@@ -140,6 +142,7 @@
    #endif
 
    friend class detail::interprocess_tester;
+ friend class detail::raw_mapped_region_creator;
    void dont_close_on_destruction();
    /// @endcond
 };
@@ -362,9 +365,9 @@
       m_base = 0;
    }
    #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
- if(m_file_mapping_hnd){
+ if(m_file_mapping_hnd != detail::invalid_file()){
          winapi::close_handle(m_file_mapping_hnd);
- m_file_mapping_hnd = 0;
+ m_file_mapping_hnd = detail::invalid_file();
       }
    #endif
 }

Modified: trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp (original)
+++ trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -23,6 +23,8 @@
 #include <boost/interprocess/detail/utilities.hpp>
 #include <boost/interprocess/detail/type_traits.hpp>
 #include <boost/interprocess/detail/iterators.hpp>
+#include <boost/interprocess/detail/math_functions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
 #include <boost/assert.hpp>
 #include <boost/static_assert.hpp>
 
@@ -281,6 +283,101 @@
       return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0);
    }
 
+ static bool calculate_lcm_and_needs_backwards_lcmed
+ (std::size_t backwards_multiple, std::size_t received_size, std::size_t size_to_achieve,
+ std::size_t &lcm_out, std::size_t &needs_backwards_lcmed_out)
+ {
+ // Now calculate lcm
+ std::size_t max = backwards_multiple;
+ std::size_t min = Alignment;
+ std::size_t needs_backwards;
+ std::size_t needs_backwards_lcmed;
+ std::size_t lcm;
+ std::size_t current_forward;
+ //Swap if necessary
+ if(max < min){
+ std::size_t tmp = min;
+ min = max;
+ max = tmp;
+ }
+ //Check if it's power of two
+ if((backwards_multiple & (backwards_multiple-1)) == 0){
+ if(0 != (size_to_achieve & ((backwards_multiple-1)))){
+ return false;
+ }
+
+ lcm = max;
+ //If we want to use minbytes data to get a buffer between maxbytes
+ //and minbytes if maxbytes can't be achieved, calculate the
+ //biggest of all possibilities
+ current_forward = detail::get_truncated_size_po2(received_size, backwards_multiple);
+ needs_backwards = size_to_achieve - current_forward;
+ assert((needs_backwards % backwards_multiple) == 0);
+ needs_backwards_lcmed = detail::get_rounded_size_po2(needs_backwards, lcm);
+ lcm_out = lcm;
+ needs_backwards_lcmed_out = needs_backwards_lcmed;
+ return true;
+ }
+ //Check if it's multiple of alignment
+ else if((backwards_multiple & (Alignment - 1u)) == 0){
+ lcm = backwards_multiple;
+ current_forward = detail::get_truncated_size(received_size, backwards_multiple);
+ //No need to round needs_backwards because backwards_multiple == lcm
+ needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward;
+ assert((needs_backwards_lcmed & (Alignment - 1u)) == 0);
+ lcm_out = lcm;
+ needs_backwards_lcmed_out = needs_backwards_lcmed;
+ return true;
+ }
+ //Check if it's multiple of the half of the alignmment
+ else if((backwards_multiple & ((Alignment/2u) - 1u)) == 0){
+ lcm = backwards_multiple*2u;
+ current_forward = detail::get_truncated_size(received_size, backwards_multiple);
+ needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward;
+ if(0 != (needs_backwards_lcmed & (Alignment-1)))
+ //while(0 != (needs_backwards_lcmed & (Alignment-1)))
+ needs_backwards_lcmed += backwards_multiple;
+ assert((needs_backwards_lcmed % lcm) == 0);
+ lcm_out = lcm;
+ needs_backwards_lcmed_out = needs_backwards_lcmed;
+ return true;
+ }
+ //Check if it's multiple of the half of the alignmment
+ else if((backwards_multiple & ((Alignment/4u) - 1u)) == 0){
+ std::size_t remainder;
+ lcm = backwards_multiple*4u;
+ current_forward = detail::get_truncated_size(received_size, backwards_multiple);
+ needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward;
+ //while(0 != (needs_backwards_lcmed & (Alignment-1)))
+ //needs_backwards_lcmed += backwards_multiple;
+ if(0 != (remainder = ((needs_backwards_lcmed & (Alignment-1))>>(Alignment/8u)))){
+ if(backwards_multiple & Alignment/2u){
+ needs_backwards_lcmed += (remainder)*backwards_multiple;
+ }
+ else{
+ needs_backwards_lcmed += (4-remainder)*backwards_multiple;
+ }
+ }
+ assert((needs_backwards_lcmed % lcm) == 0);
+ lcm_out = lcm;
+ needs_backwards_lcmed_out = needs_backwards_lcmed;
+ return true;
+ }
+ else{
+ lcm = detail::lcm(max, min);
+ }
+ //If we want to use minbytes data to get a buffer between maxbytes
+ //and minbytes if maxbytes can't be achieved, calculate the
+ //biggest of all possibilities
+ current_forward = detail::get_truncated_size(received_size, backwards_multiple);
+ needs_backwards = size_to_achieve - current_forward;
+ assert((needs_backwards % backwards_multiple) == 0);
+ needs_backwards_lcmed = detail::get_rounded_size(needs_backwards, lcm);
+ lcm_out = lcm;
+ needs_backwards_lcmed_out = needs_backwards_lcmed;
+ return true;
+ }
+
    static multiallocation_iterator allocate_many
       ( MemoryAlgorithm *memory_algo
       , const std::size_t *elem_sizes

Modified: trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp (original)
+++ trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -564,7 +564,7 @@
                         T *reuse_ptr)
 {
    std::pair<void*, bool> ret = priv_allocation_command
- (command, limit_size, preferred_size, received_size, reuse_ptr, sizeof(T));
+ (command, limit_size, preferred_size, received_size, (void*)reuse_ptr, sizeof(T));
 
    BOOST_ASSERT(0 == ((std::size_t)ret.first % detail::alignment_of<T>::value));
    return std::pair<T *, bool>(static_cast<T*>(ret.first), ret.second);

Modified: trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp (original)
+++ trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -651,7 +651,7 @@
                         T *reuse_ptr)
 {
    std::pair<void*, bool> ret = priv_allocation_command
- (command, limit_size, preferred_size, received_size, reuse_ptr, sizeof(T));
+ (command, limit_size, preferred_size, received_size, (void*)reuse_ptr, sizeof(T));
 
    BOOST_ASSERT(0 == ((std::size_t)ret.first % detail::alignment_of<T>::value));
    return std::pair<T *, bool>(static_cast<T*>(ret.first), ret.second);
@@ -776,26 +776,16 @@
       assert(prev_block->m_size == reuse->m_prev_size);
       algo_impl_t::assert_alignment(prev_block);
 
- //Let's calculate the number of extra bytes of data before the current
- //block's begin. The value is a multiple of backwards_multiple
- std::size_t needs_backwards = preferred_size -
- detail::get_truncated_size(received_size, backwards_multiple);
-
- const std::size_t lcm = detail::lcm(max_value(backwards_multiple, (std::size_t)Alignment)
- ,min_value(backwards_multiple, (std::size_t)Alignment));
-
- //If we want to use min_size data to get a buffer between preferred_size
- //and min_size if preferred_size can't be achieved, calculate the
- //biggest of all possibilities
- if(!only_preferred_backwards){
- needs_backwards = min_size - detail::get_truncated_size(received_size, backwards_multiple);
+ std::size_t needs_backwards_aligned;
+ std::size_t lcm;
+ if(!algo_impl_t::calculate_lcm_and_needs_backwards_lcmed
+ ( backwards_multiple
+ , received_size
+ , only_preferred_backwards ? preferred_size : min_size
+ , lcm, needs_backwards_aligned)){
+ return 0;
       }
 
- assert((needs_backwards % backwards_multiple) == 0);
-
- const std::size_t needs_backwards_aligned =
- detail::get_rounded_size(needs_backwards, lcm);
-
       //Check if previous block has enough size
       if(std::size_t(prev_block->m_size*Alignment) >= needs_backwards_aligned){
          //Now take all next space. This will succeed
@@ -857,10 +847,8 @@
             m_header.m_imultiset.erase(Imultiset::s_iterator_to(*prev_block));
 
             //Just merge the whole previous block
- needs_backwards = detail::get_truncated_size
- (prev_block->m_size*Alignment, backwards_multiple);
- //received_size = received_size/backwards_multiple*backwards_multiple + needs_backwards;
- received_size = received_size + needs_backwards;
+ //prev_block->m_size*Alignment is multiple of lcm (and backwards_multiple)
+ received_size = received_size + prev_block->m_size*Alignment;
 
             m_header.m_allocated += prev_block->m_size*Alignment;
             //Now update sizes

Modified: trunk/boost/interprocess/offset_ptr.hpp
==============================================================================
--- trunk/boost/interprocess/offset_ptr.hpp (original)
+++ trunk/boost/interprocess/offset_ptr.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -53,9 +53,6 @@
 {
    /// @cond
    typedef offset_ptr<PointedType> self_t;
- typedef const PointedType * const_pointer_t;
- typedef typename detail::add_reference
- <const PointedType>::type const_reference_t;
 
    void unspecified_bool_type_func() const {}
    typedef void (self_t::*unspecified_bool_type)() const;
@@ -64,6 +61,9 @@
    __declspec(noinline) //this workaround is needed for msvc-8.0 and msvc-9.0
    #endif
    void set_offset(const volatile void *ptr)
+ { set_offset((const void*)ptr); }
+
+ void set_offset(const void *ptr)
    {
       const char *p = static_cast<const char*>(const_cast<const void*>(ptr));
       //offset == 1 && ptr != 0 is not legal for this pointer
@@ -402,68 +402,44 @@
 
 //Predeclaration to avoid including header
 template<class VoidPointer, std::size_t N>
-struct has_pointer_plus_bit;
+struct max_pointer_plus_bits;
 
-template<std::size_t N>
-struct has_pointer_plus_bit<boost::interprocess::offset_ptr<void>, N>
+template<std::size_t Alignment>
+struct max_pointer_plus_bits<boost::interprocess::offset_ptr<void>, Alignment>
 {
- static const bool value = (N % 4u == 0);
+ //The offset ptr can embed one bit less than the alignment since it
+ //uses offset == 1 to store the null pointer.
+ static const std::size_t value = ::boost::interprocess::detail::ls_zeros<Alignment>::value - 1;
 };
 
 //Predeclaration
-template<class Pointer>
-struct pointer_plus_bit;
+template<class Pointer, std::size_t NumBits>
+struct pointer_plus_bits;
 
-//Specialization
-template<class T>
-struct pointer_plus_bit<boost::interprocess::offset_ptr<T> >
+template<class T, std::size_t NumBits>
+struct pointer_plus_bits<boost::interprocess::offset_ptr<T>, NumBits>
 {
    typedef boost::interprocess::offset_ptr<T> pointer;
+ //Bits are stored in the lower bits of the pointer except the LSB,
+ //because this bit is used to represent the null pointer.
+ static const std::size_t Mask = ((std::size_t(1) << NumBits)-1)<<1u;
 
    static pointer get_pointer(const pointer &n)
- { return (T*)(std::size_t(n.get()) & ~std::size_t(2u)); }
+ { return (T*)(std::size_t(n.get()) & ~std::size_t(Mask)); }
 
    static void set_pointer(pointer &n, pointer p)
- { n = (T*)(std::size_t(p.get()) | (std::size_t(n.get()) & std::size_t(2u))); }
-
- static bool get_bit(const pointer &n)
- { return 0 != (std::size_t(n.get()) & std::size_t(2u)); }
-
- static void set_bit(pointer &n, bool c)
- { n = (T*)(std::size_t(get_pointer(n).get()) | (std::size_t(c) << 1u)); }
-};
-
-//Predeclaration to avoid including header
-template<class VoidPointer, std::size_t N>
-struct has_pointer_plus_2_bits;
-
-template<std::size_t N>
-struct has_pointer_plus_2_bits<boost::interprocess::offset_ptr<void>, N>
-{
- static const bool value = (N % 8u == 0);
-};
-
-//Predeclaration
-template<class Pointer>
-struct pointer_plus_2_bits;
-
-template<class T>
-struct pointer_plus_2_bits<boost::interprocess::offset_ptr<T> >
-{
- typedef boost::interprocess::offset_ptr<T> pointer;
-
- static pointer get_pointer(const pointer &n)
- { return (T*)(std::size_t(n.get()) & ~std::size_t(6u)); }
-
- static void set_pointer(pointer &n, pointer p)
- { n = (T*)(std::size_t(p.get()) | (std::size_t(n.get()) & std::size_t(6u))); }
+ {
+ std::size_t pint = std::size_t(p.get());
+ assert(0 == (std::size_t(pint) & Mask));
+ n = (T*)(pint | (std::size_t(n.get()) & std::size_t(Mask)));
+ }
 
    static std::size_t get_bits(const pointer &n)
- { return(std::size_t(n.get()) & std::size_t(6u)) >> 1u; }
+ { return(std::size_t(n.get()) & std::size_t(Mask)) >> 1u; }
 
    static void set_bits(pointer &n, std::size_t b)
    {
- assert(b < 4);
+ assert(b < (std::size_t(1) << NumBits));
       n = (T*)(std::size_t(get_pointer(n).get()) | (b << 1u));
    }
 };

Modified: trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp (original)
+++ trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -86,11 +86,23 @@
       if(now >= abs_time) return false;
    }
 
+ typedef boost::interprocess::scoped_lock<interprocess_mutex> InternalLock;
    //The enter interprocess_mutex guarantees that while executing a notification,
    //no other thread can execute the do_timed_wait method.
    {
       //---------------------------------------------------------------
- boost::interprocess::scoped_lock<interprocess_mutex> lock(m_enter_mut);
+ InternalLock lock;
+ if(tout_enabled){
+ InternalLock dummy(m_enter_mut, abs_time);
+ lock = move(dummy);
+ }
+ else{
+ InternalLock dummy(m_enter_mut);
+ lock = move(dummy);
+ }
+
+ if(!lock)
+ return false;
       //---------------------------------------------------------------
       //We increment the waiting thread count protected so that it will be
       //always constant when another thread enters the notification logic.
@@ -146,7 +158,18 @@
          //Notification occurred, we will lock the checking interprocess_mutex so that
          //if a notify_one notification occurs, only one thread can exit
         //---------------------------------------------------------------
- boost::interprocess::scoped_lock<interprocess_mutex> lock(m_check_mut);
+ InternalLock lock;
+ if(tout_enabled){
+ InternalLock dummy(m_check_mut, abs_time);
+ lock = move(dummy);
+ }
+ else{
+ InternalLock dummy(m_check_mut);
+ lock = move(dummy);
+ }
+
+ if(!lock)
+ return false;
          //---------------------------------------------------------------
          boost::uint32_t result = detail::atomic_cas32
                         ((boost::uint32_t*)&m_command, SLEEP, NOTIFY_ONE);

Modified: trunk/boost/interprocess/sync/file_lock.hpp
==============================================================================
--- trunk/boost/interprocess/sync/file_lock.hpp (original)
+++ trunk/boost/interprocess/sync/file_lock.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -20,6 +20,7 @@
 #include <boost/interprocess/exceptions.hpp>
 #include <cassert>
 #include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
 
 //!\file
@@ -108,62 +109,6 @@
 
    bool timed_acquire_file_lock
       (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
- {
- //Obtain current count and target time
- boost::posix_time::ptime now = microsec_clock::universal_time();
- using namespace boost::detail;
-
- if(now >= abs_time) return false;
-
- do{
- if(!try_acquire_file_lock(hnd, acquired))
- return false;
-
- if(acquired)
- return true;
- else{
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- acquired = false;
- return true;
- }
- // relinquish current time slice
- winapi::sched_yield();
- }
- }while (true);
- }
-
- bool timed_acquire_file_lock_sharable
- (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
- {
- //Obtain current count and target time
- boost::posix_time::ptime now = microsec_clock::universal_time();
- using namespace boost::detail;
-
- if(now >= abs_time) return false;
-
- do{
- if(!try_acquire_file_lock_sharable(hnd, acquired))
- return false;
-
- if(acquired)
- return true;
- else{
- now = microsec_clock::universal_time();
-
- if(now >= abs_time){
- acquired = false;
- return true;
- }
- // relinquish current time slice
- winapi::sched_yield();
- }
- }while (true);
- }
-
- bool timed_acquire_file_lock
- (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
    {
       //Obtain current count and target time
       boost::posix_time::ptime now = microsec_clock::universal_time();
@@ -172,7 +117,7 @@
       if(now >= abs_time) return false;
 
       do{
- if(!try_acquire_file_lock(hnd, acquired))
+ if(!detail::try_acquire_file_lock(hnd, acquired))
             return false;
 
          if(acquired)
@@ -185,7 +130,7 @@
                return true;
             }
             // relinquish current time slice
- sleep(0);
+ detail::thread_yield();
          }
       }while (true);
    }
@@ -200,7 +145,7 @@
       if(now >= abs_time) return false;
 
       do{
- if(!try_acquire_file_lock_sharable(hnd, acquired))
+ if(!detail::try_acquire_file_lock_sharable(hnd, acquired))
             return false;
 
          if(acquired)
@@ -213,7 +158,7 @@
                return true;
             }
             // relinquish current time slice
- ::sleep(0);
+ detail::thread_yield();
          }
       }while (true);
    }
@@ -259,7 +204,7 @@
 inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
 {
    bool result;
- if(!detail::timed_acquire_file_lock(m_file_hnd, result, abs_time)){
+ if(!this->timed_acquire_file_lock(m_file_hnd, result, abs_time)){
       error_info err(system_error_code());
       throw interprocess_exception(err);
    }
@@ -295,7 +240,7 @@
 inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
 {
    bool result;
- if(!detail::timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){
+ if(!this->timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){
       error_info err(system_error_code());
       throw interprocess_exception(err);
    }

Modified: trunk/boost/interprocess/sync/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/named_condition.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -159,7 +159,9 @@
       //unlock internal first to avoid deadlock with near simultaneous waits
       lock_inverter<Lock> inverted_lock(lock);
       scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
- scoped_lock<interprocess_mutex> internal_lock(*this->mutex());
+ if(!external_unlock) return false;
+ scoped_lock<interprocess_mutex> internal_lock(*this->mutex(), abs_time);
+ if(!internal_lock) return false;
       return this->condition()->timed_wait(internal_lock, abs_time);
    }
    #endif

Modified: trunk/boost/interprocess/windows_shared_memory.hpp
==============================================================================
--- trunk/boost/interprocess/windows_shared_memory.hpp (original)
+++ trunk/boost/interprocess/windows_shared_memory.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -169,7 +169,7 @@
 inline bool windows_shared_memory::priv_open_or_create
    (detail::create_enum_t type, const char *filename, mode_t mode, std::size_t size)
 {
- m_name = filename;
+ m_name = filename ? filename : "";
 
    unsigned long file_map_access = 0;
    unsigned long map_access = 0;

Modified: trunk/boost/intrusive/avl_set.hpp
==============================================================================
--- trunk/boost/intrusive/avl_set.hpp (original)
+++ trunk/boost/intrusive/avl_set.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -240,7 +240,7 @@
    //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
    //! of avl_set.
    //!
- //! <b>Effects</b>: Returns a const reference to the avl_set associated to the end iterator
+ //! <b>Effects</b>: Returns a const reference to the set associated to the end iterator
    //!
    //! <b>Throws</b>: Nothing.
    //!
@@ -252,6 +252,34 @@
          , &avl_set_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static avl_set_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<avl_set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &avl_set_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const avl_set_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<avl_set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &avl_set_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the avl_set.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1085,6 +1113,12 @@
 
    static const avl_set &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const avl_set &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static avl_set &container_from_iterator(iterator end_iterator)
+ { return static_cast<avl_set &>(Base::container_from_iterator(end_iterator)); }
+
+ static const avl_set &container_from_iterator(const_iterator end_iterator)
+ { return static_cast<const avl_set &>(Base::container_from_iterator(end_iterator)); }
 };
 
 #endif
@@ -1317,6 +1351,34 @@
          , &avl_multiset_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static avl_multiset_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<avl_multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &avl_multiset_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const avl_multiset_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<avl_multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &avl_multiset_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the avl_multiset.
    //!
    //! <b>Complexity</b>: Constant.
@@ -2057,6 +2119,12 @@
 
    static const avl_multiset &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const avl_multiset &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static avl_multiset &container_from_iterator(iterator end_iterator)
+ { return static_cast<avl_multiset &>(Base::container_from_iterator(end_iterator)); }
+
+ static const avl_multiset &container_from_iterator(const_iterator end_iterator)
+ { return static_cast<const avl_multiset &>(Base::container_from_iterator(end_iterator)); }
 };
 
 #endif

Modified: trunk/boost/intrusive/avltree.hpp
==============================================================================
--- trunk/boost/intrusive/avltree.hpp (original)
+++ trunk/boost/intrusive/avltree.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -387,6 +387,28 @@
    static const avltree_impl &container_from_end_iterator(const_iterator end_iterator)
    { return priv_container_from_end_iterator(end_iterator); }
 
+ //! <b>Precondition</b>: it must be a valid iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static avltree_impl &container_from_iterator(iterator it)
+ { return priv_container_from_iterator(it); }
+
+ //! <b>Precondition</b>: it must be a valid end const_iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const avltree_impl &container_from_iterator(const_iterator it)
+ { return priv_container_from_iterator(it); }
+
    //! <b>Effects</b>: Returns the value_compare object used by the tree.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1233,6 +1255,9 @@
       avltree_impl *avl = detail::parent_from_member<avltree_impl, data_t>(d, &avltree_impl::data_);
       return *avl;
    }
+
+ static avltree_impl &priv_container_from_iterator(const const_iterator &it)
+ { return priv_container_from_end_iterator(it.end_iterator_from_it()); }
 };
 
 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
@@ -1426,6 +1451,12 @@
 
    static const avltree &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const avltree &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static avltree &container_from_iterator(iterator it)
+ { return static_cast<avltree &>(Base::container_from_iterator(it)); }
+
+ static const avltree &container_from_iterator(const_iterator it)
+ { return static_cast<const avltree &>(Base::container_from_iterator(it)); }
 };
 
 #endif

Modified: trunk/boost/intrusive/avltree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/avltree_algorithms.hpp (original)
+++ trunk/boost/intrusive/avltree_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -20,7 +20,6 @@
 #include <boost/intrusive/intrusive_fwd.hpp>
 
 #include <boost/intrusive/detail/assert.hpp>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
 #include <boost/intrusive/detail/utilities.hpp>
 #include <boost/intrusive/detail/tree_algorithms.hpp>
 
@@ -641,6 +640,16 @@
       rebalance_after_insertion(header, new_value);
    }
 
+ //! <b>Requires</b>: "n" must be a node inserted in a tree.
+ //!
+ //! <b>Effects</b>: Returns a pointer to the header node of the tree.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ //!
+ //! <b>Throws</b>: Nothing.
+ static node_ptr get_header(node_ptr n)
+ { return tree_algorithms::get_header(n); }
+
    /// @cond
    private:
 

Modified: trunk/boost/intrusive/circular_list_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/circular_list_algorithms.hpp (original)
+++ trunk/boost/intrusive/circular_list_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -62,8 +62,8 @@
    //! <b>Throws</b>: Nothing.
    static void init(node_ptr this_node)
    {
- NodeTraits::set_next(this_node, 0);
- NodeTraits::set_previous(this_node, 0);
+ NodeTraits::set_next(this_node, node_ptr(0));
+ NodeTraits::set_previous(this_node, node_ptr(0));
    }
 
    //! <b>Effects</b>: Returns true is "this_node" is in a non-used state

Modified: trunk/boost/intrusive/circular_slist_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/circular_slist_algorithms.hpp (original)
+++ trunk/boost/intrusive/circular_slist_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -305,12 +305,12 @@
    static node_ptr move_backwards(node_ptr p, std::size_t n)
    {
       //Null shift, nothing to do
- if(!n) return 0;
+ if(!n) return node_ptr(0);
       node_ptr first = NodeTraits::get_next(p);
 
       //count() == 1 or 2, nothing to do
       if(NodeTraits::get_next(first) == p)
- return 0;
+ return node_ptr(0);
 
       bool end_found = false;
       node_ptr new_last(0);
@@ -326,7 +326,7 @@
             //Shortcut the shift with the modulo of the size of the list
             n %= i;
             if(!n)
- return 0;
+ return node_ptr(0);
             i = 0;
             //Unlink p and continue the new first node search
             first = NodeTraits::get_next(p);
@@ -357,11 +357,11 @@
    static node_ptr move_forward(node_ptr p, std::size_t n)
    {
       //Null shift, nothing to do
- if(!n) return 0;
+ if(!n) return node_ptr(0);
       node_ptr first = node_traits::get_next(p);
 
       //count() == 1 or 2, nothing to do
- if(node_traits::get_next(first) == p) return 0;
+ if(node_traits::get_next(first) == p) return node_ptr(0);
 
       //Iterate until p is found to know where the current last node is.
       //If the shift count is less than the size of the list, we can also obtain
@@ -380,7 +380,7 @@
          //Shortcut the shift with the modulo of the size of the list
          std::size_t new_before_last_pos = (distance - (n % distance))% distance;
          //If the shift is a multiple of the size there is nothing to do
- if(!new_before_last_pos) return 0;
+ if(!new_before_last_pos) return node_ptr(0);
          
          for( new_last = p
             ; new_before_last_pos--

Modified: trunk/boost/intrusive/detail/avltree_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/avltree_node.hpp (original)
+++ trunk/boost/intrusive/detail/avltree_node.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -17,7 +17,7 @@
 #include <iterator>
 #include <boost/intrusive/detail/pointer_to_other.hpp>
 #include <boost/intrusive/avltree_algorithms.hpp>
-#include <boost/intrusive/pointer_plus_2_bits.hpp>
+#include <boost/intrusive/pointer_plus_bits.hpp>
 #include <boost/intrusive/detail/mpl.hpp>
 
 namespace boost {
@@ -111,7 +111,7 @@
       <VoidPointer, const node>::type const_node_ptr;
    typedef typename node::balance balance;
 
- typedef pointer_plus_2_bits<node_ptr> ptr_bit;
+ typedef pointer_plus_bits<node_ptr, 2> ptr_bit;
 
    static node_ptr get_parent(const_node_ptr n)
    { return ptr_bit::get_pointer(n->parent_); }
@@ -148,7 +148,7 @@
 };
 
 //Dispatches the implementation based on the boolean
-template<class VoidPointer, bool compact>
+template<class VoidPointer, bool Compact>
 struct avltree_node_traits_dispatch
    : public default_avltree_node_traits_impl<VoidPointer>
 {};
@@ -164,10 +164,10 @@
    : public avltree_node_traits_dispatch
          < VoidPointer
          , OptimizeSize &&
- has_pointer_plus_2_bits
+ max_pointer_plus_bits
             < VoidPointer
             , detail::alignment_of<compact_avltree_node<VoidPointer> >::value
- >::value
+ >::value >= 2u
>
 {};
 

Modified: trunk/boost/intrusive/detail/common_slist_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/detail/common_slist_algorithms.hpp (original)
+++ trunk/boost/intrusive/detail/common_slist_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -47,7 +47,7 @@
    { NodeTraits::set_next(this_node, this_node); }
 
    static void init(node_ptr this_node)
- { NodeTraits::set_next(this_node, 0); }
+ { NodeTraits::set_next(this_node, node_ptr(0)); }
 
    static bool unique(const_node_ptr this_node)
    {

Modified: trunk/boost/intrusive/detail/ebo_functor_holder.hpp
==============================================================================
--- trunk/boost/intrusive/detail/ebo_functor_holder.hpp (original)
+++ trunk/boost/intrusive/detail/ebo_functor_holder.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -23,8 +23,15 @@
 class ebo_functor_holder_impl
 {
    public:
- ebo_functor_holder_impl(){}
- ebo_functor_holder_impl(const T& t):t(t){}
+ ebo_functor_holder_impl()
+ {}
+ ebo_functor_holder_impl(const T& t)
+ : t(t)
+ {}
+ template<class Arg1, class Arg2>
+ ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
+ : t(arg1, arg2)
+ {}
 
    T& get(){return t;}
    const T& get()const{return t;}
@@ -38,8 +45,15 @@
    : public T
 {
    public:
- ebo_functor_holder_impl(){}
- ebo_functor_holder_impl(const T& t):T(t){}
+ ebo_functor_holder_impl()
+ {}
+ ebo_functor_holder_impl(const T& t)
+ : T(t)
+ {}
+ template<class Arg1, class Arg2>
+ ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2)
+ : T(arg1, arg2)
+ {}
 
    T& get(){return *this;}
    const T& get()const{return *this;}
@@ -54,7 +68,14 @@
 
    public:
    ebo_functor_holder(){}
- ebo_functor_holder(const T& t):super(t){}
+ ebo_functor_holder(const T& t)
+ : super(t)
+ {}
+
+ template<class Arg1, class Arg2>
+ ebo_functor_holder(const Arg1& arg1, const Arg2& arg2)
+ : super(arg1, arg2)
+ {}
 
    ebo_functor_holder& operator=(const ebo_functor_holder& x)
    {

Modified: trunk/boost/intrusive/detail/hashtable_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/hashtable_node.hpp (original)
+++ trunk/boost/intrusive/detail/hashtable_node.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -50,6 +50,7 @@
 template <class Slist>
 struct bucket_impl : public Slist
 {
+ typedef Slist slist_type;
    bucket_impl()
    {}
 
@@ -69,28 +70,6 @@
       //Slist::clear();
       return *this;
    }
-
- static typename Slist::difference_type get_bucket_num
- ( typename Slist::const_iterator it
- , const bucket_impl<Slist> &first_bucket
- , const bucket_impl<Slist> &last_bucket)
- {
- typename Slist::const_iterator
- first(first_bucket.cend()), last(last_bucket.cend());
-
- //The end node is embedded in the singly linked list:
- //iterate until we reach it.
- while(!(first.pointed_node() <= it.pointed_node() &&
- it.pointed_node() <= last.pointed_node())){
- ++it;
- }
- //Now get the bucket_impl from the iterator
- const bucket_impl &b = static_cast<const bucket_impl&>
- (Slist::container_from_end_iterator(it));
-
- //Now just calculate the index b has in the bucket array
- return &b - &first_bucket;
- }
 };
 
 template<class Slist>
@@ -133,6 +112,9 @@
       < typename Container::pointer, const Container>::type const_cont_ptr;
    typedef typename Container::size_type size_type;
 
+ static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p)
+ { return typename Container::node_ptr(&static_cast<typename Container::node&>(*p)); }
+
    public:
    typedef typename detail::add_const_if_c
       <typename Container::value_type, IsConst>::type value_type;
@@ -172,7 +154,7 @@
    { return *this->operator ->(); }
 
    value_type* operator->() const
- { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(slist_it_.pointed_node())); }
+ { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); }
 
    const Container *get_container() const
    { return detail::get_pointer(cont_); }
@@ -186,17 +168,19 @@
       const Container *cont = detail::get_pointer(cont_);
       bucket_type* buckets = detail::get_pointer(cont->bucket_pointer());
       size_type buckets_len = cont->bucket_count();
- const_siterator first(buckets[0].cend());
- const_siterator last (buckets[buckets_len].cend());
 
       ++slist_it_;
- if(first.pointed_node() <= slist_it_.pointed_node() &&
- slist_it_.pointed_node()<= last.pointed_node() ){
- size_type n_bucket = (size_type)
- bucket_type::get_bucket_num(slist_it_, buckets[0], buckets[buckets_len]);
+ if(buckets[0].cend().pointed_node() <= slist_it_.pointed_node() &&
+ slist_it_.pointed_node()<= buckets[buckets_len].cend().pointed_node() ){
+ //Now get the bucket_impl from the iterator
+ const bucket_type &b = static_cast<const bucket_type&>
+ (bucket_type::slist_type::container_from_end_iterator(slist_it_));
+
+ //Now just calculate the index b has in the bucket array
+ size_type n_bucket = static_cast<size_type>(&b - &buckets[0]);
          do{
             if (++n_bucket == buckets_len){
- slist_it_ = buckets->end();
+ slist_it_ = (&buckets[0] + buckets_len)->end();
                break;
             }
             slist_it_ = buckets[n_bucket].begin();

Modified: trunk/boost/intrusive/detail/list_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/list_node.hpp (original)
+++ trunk/boost/intrusive/detail/list_node.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -32,7 +32,8 @@
 {
    typedef typename boost::pointer_to_other
       <VoidPointer, list_node>::type node_ptr;
- node_ptr prev_, next_;
+ node_ptr next_;
+ node_ptr prev_;
 };
 
 template<class VoidPointer>
@@ -85,7 +86,7 @@
    typedef value_type * pointer;
 
    list_iterator()
- : members_ (0, 0)
+ : members_ (node_ptr(0), 0)
    {}
 
    explicit list_iterator(node_ptr node, const Container *cont_ptr)

Modified: trunk/boost/intrusive/detail/mpl.hpp
==============================================================================
--- trunk/boost/intrusive/detail/mpl.hpp (original)
+++ trunk/boost/intrusive/detail/mpl.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -13,6 +13,8 @@
 #ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP
 #define BOOST_INTRUSIVE_DETAIL_MPL_HPP
 
+#include <cstddef>
+
 namespace boost {
 namespace intrusive {
 namespace detail {
@@ -290,6 +292,24 @@
    static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2);
 };
 
+template<std::size_t S>
+struct ls_zeros
+{
+ static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value);
+};
+
+template<>
+struct ls_zeros<0>
+{
+ static const std::size_t value = 0;
+};
+
+template<>
+struct ls_zeros<1>
+{
+ static const std::size_t value = 0;
+};
+
 } //namespace detail
 } //namespace intrusive
 } //namespace boost

Deleted: trunk/boost/intrusive/detail/no_exceptions_support.hpp
==============================================================================
--- trunk/boost/intrusive/detail/no_exceptions_support.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
+++ (empty file)
@@ -1,28 +0,0 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2007
-//
-// 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)
-//
-// See http://www.boost.org/libs/intrusive for documentation.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_INTRUSIVE_NO_EXCEPTION_SUPPORT_HPP
-
-#if !(defined BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING)
-# include <boost/detail/no_exceptions_support.hpp>
-# define BOOST_INTRUSIVE_TRY BOOST_TRY
-# define BOOST_INTRUSIVE_CATCH(x) BOOST_CATCH(x)
-# define BOOST_INTRUSIVE_RETHROW BOOST_RETHROW
-# define BOOST_INTRUSIVE_CATCH_END BOOST_CATCH_END
-#else
-# define BOOST_INTRUSIVE_TRY { if (true)
-# define BOOST_INTRUSIVE_CATCH(x) else if (false)
-# define BOOST_INTRUSIVE_RETHROW
-# define BOOST_INTRUSIVE_CATCH_END }
-#endif
-
-#endif //#ifndef BOOST_INTRUSIVE_NO_EXCEPTION_SUPPORT_HPP

Modified: trunk/boost/intrusive/detail/rbtree_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/rbtree_node.hpp (original)
+++ trunk/boost/intrusive/detail/rbtree_node.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -18,7 +18,7 @@
 #include <iterator>
 #include <boost/intrusive/detail/pointer_to_other.hpp>
 #include <boost/intrusive/rbtree_algorithms.hpp>
-#include <boost/intrusive/pointer_plus_bit.hpp>
+#include <boost/intrusive/pointer_plus_bits.hpp>
 #include <boost/intrusive/detail/mpl.hpp>
 
 namespace boost {
@@ -110,7 +110,7 @@
    typedef typename boost::pointer_to_other
       <VoidPointer, const node>::type const_node_ptr;
 
- typedef pointer_plus_bit<node_ptr> ptr_bit;
+ typedef pointer_plus_bits<node_ptr, 1> ptr_bit;
 
    typedef typename node::color color;
 
@@ -133,10 +133,10 @@
    { n->right_ = r; }
 
    static color get_color(const_node_ptr n)
- { return (color)ptr_bit::get_bit(n->parent_); }
+ { return (color)ptr_bit::get_bits(n->parent_); }
 
    static void set_color(node_ptr n, color c)
- { ptr_bit::set_bit(n->parent_, c != 0); }
+ { ptr_bit::set_bits(n->parent_, c != 0); }
 
    static color black()
    { return node::black_t; }
@@ -146,7 +146,7 @@
 };
 
 //Dispatches the implementation based on the boolean
-template<class VoidPointer, bool compact>
+template<class VoidPointer, bool Compact>
 struct rbtree_node_traits_dispatch
    : public default_rbtree_node_traits_impl<VoidPointer>
 {};
@@ -161,11 +161,11 @@
 struct rbtree_node_traits
    : public rbtree_node_traits_dispatch
          < VoidPointer
- , OptimizeSize &&
- has_pointer_plus_bit
+ , OptimizeSize &&
+ (max_pointer_plus_bits
             < VoidPointer
             , detail::alignment_of<compact_rbtree_node<VoidPointer> >::value
- >::value
+ >::value >= 1)
>
 {};
 

Modified: trunk/boost/intrusive/detail/slist_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/slist_node.hpp (original)
+++ trunk/boost/intrusive/detail/slist_node.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -78,7 +78,7 @@
    typedef value_type * pointer;
 
    slist_iterator()
- : members_ (0, 0)
+ : members_ (node_ptr(0), 0)
    {}
 
    explicit slist_iterator(node_ptr node, const Container *cont_ptr)

Modified: trunk/boost/intrusive/detail/tree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/detail/tree_algorithms.hpp (original)
+++ trunk/boost/intrusive/detail/tree_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -17,7 +17,6 @@
 #include <boost/intrusive/detail/assert.hpp>
 #include <boost/intrusive/intrusive_fwd.hpp>
 #include <cstddef>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
 #include <boost/intrusive/detail/utilities.hpp>
 
 namespace boost {
@@ -97,6 +96,7 @@
 {
    /// @cond
    private:
+
    typedef typename NodeTraits::node node;
    /// @endcond
 
@@ -123,6 +123,26 @@
 
    /// @cond
    private:
+ template<class Disposer>
+ struct dispose_subtree_disposer
+ {
+ dispose_subtree_disposer(Disposer &disp, node_ptr subtree)
+ : disposer_(&disp), subtree_(subtree)
+ {}
+
+ void release()
+ { disposer_ = 0; }
+
+ ~dispose_subtree_disposer()
+ {
+ if(disposer_){
+ dispose_subtree(subtree_, *disposer_);
+ }
+ }
+ Disposer *disposer_;
+ node_ptr subtree_;
+ };
+
    static node_ptr uncast(const_node_ptr ptr)
    {
       return node_ptr(const_cast<node*>(::boost::intrusive::detail::get_pointer(ptr)));
@@ -505,9 +525,21 @@
    //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
    static void init(node_ptr node)
    {
- NodeTraits::set_parent(node, 0);
- NodeTraits::set_left(node, 0);
- NodeTraits::set_right(node, 0);
+ NodeTraits::set_parent(node, node_ptr(0));
+ NodeTraits::set_left(node, node_ptr(0));
+ NodeTraits::set_right(node, node_ptr(0));
+ };
+
+ //! <b>Effects</b>: Returns true if node is in the same state as if called init(node)
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Throws</b>: Nothing.
+ static bool inited(const_node_ptr node)
+ {
+ return !NodeTraits::get_parent(node) &&
+ !NodeTraits::get_left(node) &&
+ !NodeTraits::get_right(node) ;
    };
 
    //! <b>Requires</b>: node must not be part of any tree.
@@ -522,7 +554,7 @@
    //! <b>Nodes</b>: If node is inserted in a tree, this function corrupts the tree.
    static void init_header(node_ptr header)
    {
- NodeTraits::set_parent(header, 0);
+ NodeTraits::set_parent(header, node_ptr(0));
       NodeTraits::set_left(header, header);
       NodeTraits::set_right(header, header);
    }
@@ -565,7 +597,7 @@
    {
       node_ptr leftmost = NodeTraits::get_left(header);
       if (leftmost == header)
- return 0;
+ return node_ptr(0);
       node_ptr leftmost_parent(NodeTraits::get_parent(leftmost));
       node_ptr leftmost_right (NodeTraits::get_right(leftmost));
       bool is_root = leftmost_parent == header;
@@ -580,12 +612,12 @@
             NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right);
       }
       else if (is_root){
- NodeTraits::set_parent(header, 0);
+ NodeTraits::set_parent(header, node_ptr(0));
          NodeTraits::set_left(header, header);
          NodeTraits::set_right(header, header);
       }
       else{
- NodeTraits::set_left(leftmost_parent, 0);
+ NodeTraits::set_left(leftmost_parent, node_ptr(0));
          NodeTraits::set_left(header, leftmost_parent);
       }
       return leftmost;
@@ -1143,58 +1175,54 @@
          node_ptr rightmost = target_sub_root;
 
          //First set the subroot
- NodeTraits::set_left(target_sub_root, 0);
- NodeTraits::set_right(target_sub_root, 0);
+ NodeTraits::set_left(target_sub_root, node_ptr(0));
+ NodeTraits::set_right(target_sub_root, node_ptr(0));
          NodeTraits::set_parent(target_sub_root, target_parent);
 
- try {
- while(true) {
- //First clone left nodes
- if( NodeTraits::get_left(current) &&
- !NodeTraits::get_left(insertion_point)) {
- current = NodeTraits::get_left(current);
- node_ptr temp = insertion_point;
- //Clone and mark as leaf
- insertion_point = cloner(current);
- NodeTraits::set_left (insertion_point, 0);
- NodeTraits::set_right (insertion_point, 0);
- //Insert left
- NodeTraits::set_parent(insertion_point, temp);
- NodeTraits::set_left (temp, insertion_point);
- //Update leftmost
- if(rightmost == target_sub_root)
- leftmost = insertion_point;
- }
- //Then clone right nodes
- else if( NodeTraits::get_right(current) &&
- !NodeTraits::get_right(insertion_point)){
- current = NodeTraits::get_right(current);
- node_ptr temp = insertion_point;
- //Clone and mark as leaf
- insertion_point = cloner(current);
- NodeTraits::set_left (insertion_point, 0);
- NodeTraits::set_right (insertion_point, 0);
- //Insert right
- NodeTraits::set_parent(insertion_point, temp);
- NodeTraits::set_right (temp, insertion_point);
- //Update rightmost
- rightmost = insertion_point;
- }
- //If not, go up
- else if(current == source_root){
- break;
- }
- else{
- //Branch completed, go up searching more nodes to clone
- current = NodeTraits::get_parent(current);
- insertion_point = NodeTraits::get_parent(insertion_point);
- }
+ dispose_subtree_disposer<Disposer> rollback(disposer, target_sub_root);
+ while(true) {
+ //First clone left nodes
+ if( NodeTraits::get_left(current) &&
+ !NodeTraits::get_left(insertion_point)) {
+ current = NodeTraits::get_left(current);
+ node_ptr temp = insertion_point;
+ //Clone and mark as leaf
+ insertion_point = cloner(current);
+ NodeTraits::set_left (insertion_point, node_ptr(0));
+ NodeTraits::set_right (insertion_point, node_ptr(0));
+ //Insert left
+ NodeTraits::set_parent(insertion_point, temp);
+ NodeTraits::set_left (temp, insertion_point);
+ //Update leftmost
+ if(rightmost == target_sub_root)
+ leftmost = insertion_point;
+ }
+ //Then clone right nodes
+ else if( NodeTraits::get_right(current) &&
+ !NodeTraits::get_right(insertion_point)){
+ current = NodeTraits::get_right(current);
+ node_ptr temp = insertion_point;
+ //Clone and mark as leaf
+ insertion_point = cloner(current);
+ NodeTraits::set_left (insertion_point, node_ptr(0));
+ NodeTraits::set_right (insertion_point, node_ptr(0));
+ //Insert right
+ NodeTraits::set_parent(insertion_point, temp);
+ NodeTraits::set_right (temp, insertion_point);
+ //Update rightmost
+ rightmost = insertion_point;
+ }
+ //If not, go up
+ else if(current == source_root){
+ break;
+ }
+ else{
+ //Branch completed, go up searching more nodes to clone
+ current = NodeTraits::get_parent(current);
+ insertion_point = NodeTraits::get_parent(insertion_point);
             }
          }
- catch(...) {
- dispose_subtree(target_sub_root, disposer);
- throw;
- }
+ rollback.release();
          leftmost_out = leftmost;
          rightmost_out = rightmost;
       }
@@ -1321,8 +1349,8 @@
              NodeTraits::set_right(header, z);
       }
       NodeTraits::set_parent(z, par);
- NodeTraits::set_right(z, 0);
- NodeTraits::set_left(z, 0);
+ NodeTraits::set_right(z, node_ptr(0));
+ NodeTraits::set_left(z, node_ptr(0));
    }
 
    static void erase(node_ptr header, node_ptr z)
@@ -1384,7 +1412,7 @@
    {
       std::size_t len;
       len = 0;
- if(!old_root) return 0;
+ if(!old_root) return node_ptr(0);
 
       //To avoid irregularities in the algorithm (old_root can be a
       //left or right child or even the root of the tree) just put the
@@ -1392,8 +1420,8 @@
       //information to restore the original relationship after
       //the algorithm is applied.
       node_ptr super_root = NodeTraits::get_parent(old_root);
- assert(super_root);
-
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
+
       //Get info
       node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
       bool super_root_is_header = is_header(super_root);
@@ -1464,7 +1492,7 @@
       //information to restore the original relationship after
       //the algorithm is applied.
       node_ptr super_root = NodeTraits::get_parent(old_root);
- assert(super_root);
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
 
       //Get info
       node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
@@ -1511,6 +1539,28 @@
       return new_root;
    }
 
+ //! <b>Requires</b>: "n" must be a node inserted in a tree.
+ //!
+ //! <b>Effects</b>: Returns a pointer to the header node of the tree.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ //!
+ //! <b>Throws</b>: Nothing.
+ static node_ptr get_root(node_ptr node)
+ {
+ BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node)));
+ node_ptr x = NodeTraits::get_parent(node);
+ if(x){
+ while(!is_header(x)){
+ x = NodeTraits::get_parent(x);
+ }
+ return x;
+ }
+ else{
+ return node;
+ }
+ }
+
    private:
    static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info)
    {
@@ -1569,7 +1619,6 @@
       info.x_parent = x_parent;
       info.y = y;
    }
-
 };
 
 } //namespace detail {

Modified: trunk/boost/intrusive/detail/tree_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/tree_node.hpp (original)
+++ trunk/boost/intrusive/detail/tree_node.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -168,6 +168,11 @@
          return 0;
    }
 
+ tree_iterator end_iterator_from_it() const
+ {
+ return tree_iterator(node_algorithms::get_header(this->pointed_node()), this->get_container());
+ }
+
    private:
    struct members
       : public detail::select_constptr

Modified: trunk/boost/intrusive/detail/utilities.hpp
==============================================================================
--- trunk/boost/intrusive/detail/utilities.hpp (original)
+++ trunk/boost/intrusive/detail/utilities.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -235,16 +235,9 @@
    node_cloner(F f, const Container *cont)
       : base_t(f), cont_(cont)
    {}
-
+
    node_ptr operator()(node_ptr p)
- {
- node_ptr n = cont_->get_real_value_traits().to_node_ptr
- (*base_t::get()(*cont_->get_real_value_traits().to_value_ptr(p)));
- //Cloned node must be in default mode if the linking mode requires it
- if(safemode_or_autounlink)
- BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
- return n;
- }
+ { return this->operator()(*p); }
 
    node_ptr operator()(const node &to_clone)
    {
@@ -396,16 +389,16 @@
 struct link_dispatch
 {};
 
-template<class Container>
-void destructor_impl(Container &cont, detail::link_dispatch<safe_link>)
-{ (void)cont; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!cont.is_linked()); }
-
-template<class Container>
-void destructor_impl(Container &cont, detail::link_dispatch<auto_unlink>)
-{ cont.unlink(); }
+template<class Hook>
+void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
+{ (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked()); }
+
+template<class Hook>
+void destructor_impl(Hook &hook, detail::link_dispatch<auto_unlink>)
+{ hook.unlink(); }
 
-template<class Container>
-void destructor_impl(Container &, detail::link_dispatch<normal_link>)
+template<class Hook>
+void destructor_impl(Hook &, detail::link_dispatch<normal_link>)
 {}
 
 template<class T, class NodeTraits, link_mode_type LinkMode, class Tag, int HookType>
@@ -548,6 +541,62 @@
    return (value >> (pow - x)) + 1;
 }
 
+template<class Container, class Disposer>
+class exception_disposer
+{
+ Container *cont_;
+ Disposer &disp_;
+
+ exception_disposer(const exception_disposer&);
+ exception_disposer &operator=(const exception_disposer&);
+
+ public:
+ exception_disposer(Container &cont, Disposer &disp)
+ : cont_(&cont), disp_(disp)
+ {}
+
+ void release()
+ { cont_ = 0; }
+
+ ~exception_disposer()
+ {
+ if(cont_){
+ cont_->clear_and_dispose(disp_);
+ }
+ }
+};
+
+template<class Container, class Disposer>
+class exception_array_disposer
+{
+ Container *cont_;
+ Disposer &disp_;
+ typename Container::size_type &constructed_;
+
+ exception_array_disposer(const exception_array_disposer&);
+ exception_array_disposer &operator=(const exception_array_disposer&);
+
+ public:
+ typedef typename Container::size_type size_type;
+ exception_array_disposer
+ (Container &cont, Disposer &disp, size_type &constructed)
+ : cont_(&cont), disp_(disp), constructed_(constructed)
+ {}
+
+ void release()
+ { cont_ = 0; }
+
+ ~exception_array_disposer()
+ {
+ size_type n = constructed_;
+ if(cont_){
+ while(n--){
+ cont_[n].clear_and_dispose(disp_);
+ }
+ }
+ }
+};
+
 } //namespace detail
 } //namespace intrusive
 } //namespace boost

Modified: trunk/boost/intrusive/hashtable.hpp
==============================================================================
--- trunk/boost/intrusive/hashtable.hpp (original)
+++ trunk/boost/intrusive/hashtable.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -14,15 +14,15 @@
 
 #include <boost/intrusive/detail/config_begin.hpp>
 //std C++
-#include <functional>
-#include <utility>
-#include <algorithm>
-#include <cstddef>
+#include <functional> //std::equal_to
+#include <utility> //std::pair
+#include <algorithm> //std::swap, std::lower_bound, std::upper_bound
+#include <cstddef> //std::size_t
+#include <iterator> //std::iterator_traits
 //boost
 #include <boost/intrusive/detail/assert.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/functional/hash.hpp>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
 //General intrusive utilities
 #include <boost/intrusive/intrusive_fwd.hpp>
 #include <boost/intrusive/detail/pointer_to_other.hpp>
@@ -34,12 +34,128 @@
 #include <boost/intrusive/trivial_value_traits.hpp>
 #include <boost/intrusive/unordered_set_hook.hpp>
 #include <boost/intrusive/slist.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
 
 namespace boost {
 namespace intrusive {
 
 /// @cond
 
+namespace detail {
+
+template <class NodeTraits>
+struct hash_reduced_slist_node_traits
+{
+ template <class U> static detail::one test(...);
+ template <class U> static detail::two test(typename U::reduced_slist_node_traits* = 0);
+ static const bool value = sizeof(test<NodeTraits>(0)) == sizeof(detail::two);
+};
+
+template <class NodeTraits>
+struct apply_reduced_slist_node_traits
+{
+ typedef typename NodeTraits::reduced_slist_node_traits type;
+};
+
+template <class NodeTraits>
+struct reduced_slist_node_traits
+{
+ typedef typename detail::eval_if_c
+ < hash_reduced_slist_node_traits<NodeTraits>::value
+ , apply_reduced_slist_node_traits<NodeTraits>
+ , detail::identity<NodeTraits>
+ >::type type;
+};
+
+template<class NodeTraits>
+struct get_slist_impl
+{
+ typedef trivial_value_traits<NodeTraits, normal_link> trivial_traits;
+
+ //Reducing symbol length
+ struct type : make_slist
+ < typename NodeTraits::node
+ , boost::intrusive::value_traits<trivial_traits>
+ , boost::intrusive::constant_time_size<false>
+ , boost::intrusive::size_type<std::size_t>
+ >::type
+ {};
+};
+
+template<class SupposedValueTraits>
+struct unordered_bucket_impl
+{
+ /// @cond
+ typedef typename detail::eval_if_c
+ < detail::external_value_traits_is_true
+ <SupposedValueTraits>::value
+ , detail::eval_value_traits
+ <SupposedValueTraits>
+ , detail::identity
+ <SupposedValueTraits>
+ >::type real_value_traits;
+
+ typedef typename detail::get_node_traits
+ <real_value_traits>::type node_traits;
+ typedef typename get_slist_impl
+ <typename reduced_slist_node_traits
+ <node_traits>::type
+ >::type slist_impl;
+ typedef detail::bucket_impl<slist_impl> implementation_defined;
+ typedef implementation_defined type;
+};
+
+template<class SupposedValueTraits>
+struct unordered_bucket_ptr_impl
+{
+ /// @cond
+
+ typedef typename detail::eval_if_c
+ < detail::external_value_traits_is_true
+ <SupposedValueTraits>::value
+ , detail::eval_value_traits
+ <SupposedValueTraits>
+ , detail::identity
+ <SupposedValueTraits>
+ >::type real_value_traits;
+ typedef typename detail::get_node_traits
+ <SupposedValueTraits>::type::node_ptr node_ptr;
+ typedef typename unordered_bucket_impl
+ <SupposedValueTraits>::type bucket_type;
+ typedef typename boost::pointer_to_other
+ <node_ptr, bucket_type>::type implementation_defined;
+ /// @endcond
+ typedef implementation_defined type;
+};
+
+} //namespace detail {
+
+/// @endcond
+
+template<class ValueTraitsOrHookOption>
+struct unordered_bucket
+{
+ /// @cond
+ typedef typename ValueTraitsOrHookOption::
+ template pack<none>::value_traits supposed_value_traits;
+ /// @endcond
+ typedef typename detail::unordered_bucket_impl
+ <supposed_value_traits>::type type;
+};
+
+template<class ValueTraitsOrHookOption>
+struct unordered_bucket_ptr
+{
+ /// @cond
+ typedef typename ValueTraitsOrHookOption::
+ template pack<none>::value_traits supposed_value_traits;
+ /// @endcond
+ typedef typename detail::unordered_bucket_ptr_impl
+ <supposed_value_traits>::type type;
+};
+
+/// @cond
+
 namespace detail{
 
 template <class T>
@@ -59,6 +175,23 @@
    static const bool value = store_hash_bool<T>::value > sizeof(one)*2;
 };
 
+template <class T>
+struct optimize_multikey_bool
+{
+ template<bool Add>
+ struct two_or_three {one _[2 + Add];};
+ template <class U> static one test(...);
+ template <class U> static two_or_three<U::optimize_multikey>
+ test (detail::bool_<U::optimize_multikey>* = 0);
+ static const std::size_t value = sizeof(test<T>(0));
+};
+
+template <class T>
+struct optimize_multikey_is_true
+{
+ static const bool value = optimize_multikey_bool<T>::value > sizeof(one)*2;
+};
+
 template<class Config>
 struct bucket_plus_size
    : public detail::size_holder
@@ -92,7 +225,7 @@
    bucket_plus_size<Config> bucket_plus_size_;
 };
 
-template<class Config>
+template<class Config, bool>
 struct bucket_hash_equal_t : public detail::ebo_functor_holder<typename Config::equal>
 {
    typedef typename Config::equal equal;
@@ -105,19 +238,41 @@
    bucket_hash_t<Config> bucket_hash;
 };
 
+template<class Config> //cache_begin == true version
+struct bucket_hash_equal_t<Config, true>
+ : public detail::ebo_functor_holder<typename Config::equal>
+{
+ typedef typename Config::equal equal;
+ typedef typename Config::hash hasher;
+ typedef typename Config::bucket_traits bucket_traits;
+ typedef typename unordered_bucket_ptr_impl
+ <typename Config::value_traits>::type bucket_ptr;
+
+ bucket_hash_equal_t(const bucket_traits &b_traits, const hasher & h, const equal &e)
+ : detail::ebo_functor_holder<typename Config::equal>(e), bucket_hash(b_traits, h)
+ {}
+ bucket_hash_t<Config> bucket_hash;
+ bucket_ptr cached_begin_;
+};
+
 template<class Config>
-struct data_t : public Config::value_traits
+struct hashtable_data_t : public Config::value_traits
 {
    typedef typename Config::value_traits value_traits;
    typedef typename Config::equal equal;
    typedef typename Config::hash hasher;
    typedef typename Config::bucket_traits bucket_traits;
 
- data_t( const bucket_traits &b_traits, const hasher & h
- , const equal &e, const value_traits &val_traits)
+ hashtable_data_t( const bucket_traits &b_traits, const hasher & h
+ , const equal &e, const value_traits &val_traits)
       : Config::value_traits(val_traits), bucket_hash_equal_(b_traits, h, e)
    {}
- bucket_hash_equal_t<Config> bucket_hash_equal_;
+ bucket_hash_equal_t<Config, Config::cache_begin> bucket_hash_equal_;
+};
+
+struct insert_commit_data_impl
+{
+ std::size_t hash;
 };
 
 } //namespace detail {
@@ -137,12 +292,14 @@
 };
 
 template < class ValueTraits
+ , bool UniqueKeys
          , class Hash
          , class Equal
          , class SizeType
          , bool ConstantTimeSize
          , class BucketTraits
          , bool Power2Buckets
+ , bool CacheBegin
>
 struct usetopt
 {
@@ -153,6 +310,8 @@
    typedef BucketTraits bucket_traits;
    static const bool constant_time_size = ConstantTimeSize;
    static const bool power_2_buckets = Power2Buckets;
+ static const bool unique_keys = UniqueKeys;
+ static const bool cache_begin = CacheBegin;
 };
 
 struct default_bucket_traits;
@@ -174,75 +333,12 @@
       , hash<boost::hash<T> >
       , bucket_traits<default_bucket_traits>
       , power_2_buckets<false>
+ , cache_begin<false>
>::type
 {};
 
-template<class NodeTraits>
-struct get_slist_impl
-{
- typedef trivial_value_traits<NodeTraits, normal_link> trivial_traits;
-
- //Reducing symbol length
- struct type : make_slist
- < typename NodeTraits::node
- , boost::intrusive::value_traits<trivial_traits>
- , boost::intrusive::constant_time_size<false>
- , boost::intrusive::size_type<std::size_t>
- >::type
- {};
-};
-
 /// @endcond
 
-template<class ValueTraitsOrHookOption>
-struct unordered_bucket
-{
- /// @cond
- typedef typename ValueTraitsOrHookOption::
- template pack<none>::value_traits supposed_value_traits;
-
- typedef typename detail::eval_if_c
- < detail::external_value_traits_is_true
- <supposed_value_traits>::value
- , detail::eval_value_traits
- <supposed_value_traits>
- , detail::identity
- <supposed_value_traits>
- >::type real_value_traits;
-
- typedef typename detail::get_node_traits
- <real_value_traits>::type node_traits;
- typedef typename get_slist_impl
- <node_traits>::type slist_impl;
- typedef detail::bucket_impl<slist_impl> implementation_defined;
- /// @endcond
- typedef implementation_defined type;
-};
-
-template<class ValueTraitsOrHookOption>
-struct unordered_bucket_ptr
-{
- /// @cond
- typedef typename ValueTraitsOrHookOption::
- template pack<none>::value_traits supposed_value_traits;
- typedef typename detail::eval_if_c
- < detail::external_value_traits_is_true
- <supposed_value_traits>::value
- , detail::eval_value_traits
- <supposed_value_traits>
- , detail::identity
- <supposed_value_traits>
- >::type real_value_traits;
- typedef typename detail::get_node_traits
- <supposed_value_traits>::type::node_ptr node_ptr;
- typedef typename unordered_bucket
- <ValueTraitsOrHookOption>::type bucket_type;
- typedef typename boost::pointer_to_other
- <node_ptr, bucket_type>::type implementation_defined;
- /// @endcond
- typedef implementation_defined type;
-};
-
 //! The class template hashtable is an intrusive hash table container, that
 //! is used to construct intrusive unordered_set and unordered_multiset containers. The
 //! no-throw guarantee holds only, if the Equal object and Hasher don't throw.
@@ -261,7 +357,8 @@
 //!
 //! The container supports the following options:
 //! \c base_hook<>/member_hook<>/value_traits<>,
-//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> .
+//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
+//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
 //!
 //! hashtable only provides forward iterators but it provides 4 iterator types:
 //! iterator and const_iterator to navigate through the whole container and
@@ -284,13 +381,12 @@
 template<class Config>
 #endif
 class hashtable_impl
- : private detail::data_t<Config>
+ : private detail::hashtable_data_t<Config>
 {
    public:
    typedef typename Config::value_traits value_traits;
 
    /// @cond
-
    static const bool external_value_traits =
       detail::external_value_traits_is_true<value_traits>::value;
    typedef typename detail::eval_if_c
@@ -306,8 +402,10 @@
       , detail::eval_bucket_traits<bucket_traits>
       , detail::identity<bucket_traits>
>::type real_bucket_traits;
- typedef typename get_slist_impl
- <typename real_value_traits::node_traits>::type slist_impl;
+ typedef typename detail::get_slist_impl
+ <typename detail::reduced_slist_node_traits
+ <typename real_value_traits::node_traits>::type
+ >::type slist_impl;
    /// @endcond
 
    typedef typename real_value_traits::pointer pointer;
@@ -327,7 +425,7 @@
    typedef typename slist_impl::const_iterator const_siterator;
    typedef detail::hashtable_iterator<hashtable_impl, false> iterator;
    typedef detail::hashtable_iterator<hashtable_impl, true> const_iterator;
- typedef typename real_value_traits::node_traits node_traits;
+ typedef typename real_value_traits::node_traits node_traits;
    typedef typename node_traits::node node;
    typedef typename boost::pointer_to_other
       <pointer, node>::type node_ptr;
@@ -338,19 +436,67 @@
    static const bool constant_time_size = Config::constant_time_size;
    static const bool stateful_value_traits = detail::store_cont_ptr_on_it<hashtable_impl>::value;
    static const bool store_hash = detail::store_hash_is_true<node_traits>::value;
+ static const bool unique_keys = Config::unique_keys;
+ static const bool optimize_multikey
+ = detail::optimize_multikey_is_true<node_traits>::value && !unique_keys;
+ static const bool power_2_buckets = Config::power_2_buckets;
+ static const bool cache_begin = Config::cache_begin;
 
    /// @cond
    private:
+ typedef typename slist_impl::node_ptr slist_node_ptr;
+ typedef typename boost::pointer_to_other
+ <slist_node_ptr, void>::type void_pointer;
+ //We'll define group traits, but these won't be instantiated if
+ //optimize_multikey is not true
+ typedef unordered_group_node_traits<void_pointer, node> group_traits;
+ typedef circular_slist_algorithms<group_traits> group_algorithms;
+
    typedef detail::bool_<store_hash> store_hash_t;
+ typedef detail::bool_<optimize_multikey> optimize_multikey_t;
+ typedef detail::bool_<cache_begin> cache_begin_t;
+ typedef detail::bool_<power_2_buckets> power_2_buckets_t;
    typedef detail::size_holder<constant_time_size, size_type> size_traits;
- typedef detail::data_t<Config> base_type;
- typedef detail::transform_iterator
- < typename slist_impl::iterator
- , detail::node_to_value<hashtable_impl, false> > local_iterator_impl;
- typedef detail::transform_iterator
- < typename slist_impl::iterator
- , detail::node_to_value<hashtable_impl, true> > const_local_iterator_impl;
+ typedef detail::hashtable_data_t<Config> base_type;
+
+ template<bool IsConst>
+ struct downcast_node_to_value
+ : public detail::node_to_value<hashtable_impl, IsConst>
+ {
+ typedef detail::node_to_value<hashtable_impl, IsConst> base_t;
+ typedef typename base_t::result_type result_type;
+ typedef typename detail::add_const_if_c
+ <typename slist_impl::node, IsConst>::type &first_argument_type;
+ typedef typename detail::add_const_if_c
+ <node, IsConst>::type &intermediate_argument_type;
+
+ downcast_node_to_value(const hashtable_impl *cont)
+ : base_t(cont)
+ {}
+
+ result_type operator()(first_argument_type arg) const
+ { return this->base_t::operator()(static_cast<intermediate_argument_type>(arg)); }
+ };
+
+ template<class F>
+ struct node_cast_adaptor
+ : private detail::ebo_functor_holder<F>
+ {
+ typedef detail::ebo_functor_holder<F> base_t;
+
+ template<class ConvertibleToF>
+ node_cast_adaptor(const ConvertibleToF &c2f, const hashtable_impl *cont)
+ : base_t(base_t(c2f, cont))
+ {}
+
+ typename base_t::node_ptr operator()(const typename slist_impl::node &to_clone)
+ { return base_t::operator()(static_cast<const node &>(to_clone)); }
+
+ void operator()(typename slist_impl::node_ptr to_clone)
+ { base_t::operator()(node_ptr(&static_cast<node &>(*to_clone))); }
+ };
 
+ private:
    //noncopyable
    hashtable_impl (const hashtable_impl&);
    hashtable_impl operator =(const hashtable_impl&);
@@ -362,103 +508,23 @@
    //Constant-time size is incompatible with auto-unlink hooks!
    BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink)));
 
- static const bool power_2_buckets = Config::power_2_buckets;
-
- std::size_t from_hash_to_bucket(std::size_t hash_value) const
- { return from_hash_to_bucket(hash_value, detail::bool_<power_2_buckets>()); }
-
- std::size_t from_hash_to_bucket(std::size_t hash_value, detail::bool_<false>) const
- { return hash_value % this->get_real_bucket_traits().bucket_count(); }
-
- std::size_t from_hash_to_bucket(std::size_t hash_value, detail::bool_<true>) const
- { return hash_value & (this->get_real_bucket_traits().bucket_count() - 1); }
-
- const key_equal &priv_equal() const
- { return static_cast<const key_equal&>(this->bucket_hash_equal_.get()); }
-
- key_equal &priv_equal()
- { return static_cast<key_equal&>(this->bucket_hash_equal_.get()); }
-
- const real_bucket_traits &get_real_bucket_traits(detail::bool_<false>) const
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
-
- const real_bucket_traits &get_real_bucket_traits(detail::bool_<true>) const
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
-
- real_bucket_traits &get_real_bucket_traits(detail::bool_<false>)
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
-
- real_bucket_traits &get_real_bucket_traits(detail::bool_<true>)
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
-
- const real_bucket_traits &get_real_bucket_traits() const
- { return this->get_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
-
- real_bucket_traits &get_real_bucket_traits()
- { return this->get_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
-
- const hasher &priv_hasher() const
- { return static_cast<const hasher&>(this->bucket_hash_equal_.bucket_hash.get()); }
-
- hasher &priv_hasher()
- { return static_cast<hasher&>(this->bucket_hash_equal_.bucket_hash.get()); }
-
- bucket_ptr priv_buckets() const
- { return this->get_real_bucket_traits().bucket_begin(); }
-
- size_type priv_buckets_len() const
- { return this->get_real_bucket_traits().bucket_count(); }
-
- static node_ptr uncast(const_node_ptr ptr)
- {
- return node_ptr(const_cast<node*>(detail::get_pointer(ptr)));
- }
-
- node &from_value_to_node(value_type &v)
- { return *this->get_real_value_traits().to_node_ptr(v); }
-
- const node &from_value_to_node(const value_type &v) const
- { return *this->get_real_value_traits().to_node_ptr(v); }
-
- size_traits &priv_size_traits()
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
-
- const size_traits &priv_size_traits() const
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
+ template<class Disposer>
+ node_cast_adaptor<detail::node_disposer<Disposer, hashtable_impl> >
+ make_node_disposer(const Disposer &disposer) const
+ { return node_cast_adaptor<detail::node_disposer<Disposer, hashtable_impl> >(disposer, this); }
 
- struct insert_commit_data_impl
- {
- size_type hash;
- };
    /// @endcond
 
    public:
+ typedef detail::insert_commit_data_impl insert_commit_data;
 
- class local_iterator
- : public local_iterator_impl
- {
- public:
- local_iterator()
- {}
-
- local_iterator(siterator sit, const hashtable_impl *cont)
- : local_iterator_impl(sit, cont)
- {}
- };
-
- class const_local_iterator
- : public const_local_iterator_impl
- {
- public:
- const_local_iterator()
- {}
-
- const_local_iterator(siterator sit, const hashtable_impl *cont)
- : const_local_iterator_impl(sit, cont)
- {}
- };
+ typedef detail::transform_iterator
+ < typename slist_impl::iterator
+ , downcast_node_to_value<false> > local_iterator;
 
- typedef insert_commit_data_impl insert_commit_data;
+ typedef detail::transform_iterator
+ < typename slist_impl::iterator
+ , downcast_node_to_value<true> > const_local_iterator;
 
    /// @cond
 
@@ -503,7 +569,7 @@
                   , const value_traits &v_traits = value_traits())
       : base_type(b_traits, hash_func, equal_func, v_traits)
    {
- priv_clear_buckets();
+ priv_initialize_buckets();
       this->priv_size_traits().set_size(size_type(0));
       BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_buckets_len() != 0);
       //Check power of two bucket array if the option is activated
@@ -562,7 +628,7 @@
    //!
    //! <b>Throws</b>: Nothing.
    iterator end()
- { return iterator(invalid_local_it(this->get_real_bucket_traits()), 0); }
+ { return iterator(priv_invalid_local_it(), 0); }
 
    //! <b>Effects</b>: Returns a const_iterator pointing to the end of the unordered_set.
    //!
@@ -578,7 +644,7 @@
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator cend() const
- { return const_iterator(invalid_local_it(this->get_real_bucket_traits()), 0); }
+ { return const_iterator(priv_invalid_local_it(), 0); }
 
    //! <b>Effects</b>: Returns the hasher object used by the unordered_set.
    //!
@@ -598,8 +664,8 @@
 
    //! <b>Effects</b>: Returns true is the container is empty.
    //!
- //! <b>Complexity</b>: if constant_time_size is false, average constant time
- //! (worst case, with empty() == true): O(this->bucket_count()).
+ //! <b>Complexity</b>: if constant-time size and cache_last options are disabled,
+ //! average constant time (worst case, with empty() == true: O(this->bucket_count()).
    //! Otherwise constant.
    //!
    //! <b>Throws</b>: Nothing.
@@ -608,6 +674,9 @@
       if(constant_time_size){
          return !this->size();
       }
+ else if(cache_begin){
+ return this->begin() == this->end();
+ }
       else{
          size_type buckets_len = this->priv_buckets_len();
          const bucket_type *b = detail::get_pointer(this->priv_buckets());
@@ -658,7 +727,8 @@
       swap(this->priv_equal(), other.priv_equal());
       swap(this->priv_hasher(), other.priv_hasher());
       //These can't throw
- swap(this->get_real_bucket_traits(), other.get_real_bucket_traits());
+ swap(this->priv_real_bucket_traits(), other.priv_real_bucket_traits());
+ priv_swap_cache(cache_begin_t(), other);
       if(constant_time_size){
          size_type backup = this->priv_size_traits().get_size();
          this->priv_size_traits().set_size(other.priv_size_traits().get_size());
@@ -698,75 +768,71 @@
             const bucket_ptr src_buckets = src.priv_buckets();
             const bucket_ptr dst_buckets = this->priv_buckets();
             size_type constructed;
- BOOST_INTRUSIVE_TRY{
- for( constructed = 0
- ; constructed < dst_bucket_count
+ typedef node_cast_adaptor<detail::node_disposer<Disposer, hashtable_impl> > NodeDisposer;
+ typedef node_cast_adaptor<detail::node_cloner<Cloner, hashtable_impl> > NodeCloner;
+ NodeDisposer node_disp(disposer, this);
+
+ detail::exception_array_disposer<bucket_type, NodeDisposer>
+ rollback(dst_buckets[0], node_disp, constructed);
+ for( constructed = 0
+ ; constructed < dst_bucket_count
+ ; ++constructed){
+ dst_buckets[constructed].clone_from
+ ( src_buckets[constructed]
+ , NodeCloner(cloner, this), node_disp);
+ }
+ if(src_bucket_count != dst_bucket_count){
+ //Now insert the remaining ones using the modulo trick
+ for(//"constructed" comes from the previous loop
+ ; constructed < src_bucket_count
                   ; ++constructed){
- dst_buckets[constructed].clone_from
- ( src_buckets[constructed]
- , detail::node_cloner<Cloner, hashtable_impl>(cloner, this)
- , detail::node_disposer<Disposer, hashtable_impl>(disposer, this)
- );
- }
- if(src_bucket_count != dst_bucket_count){
- //Now insert the remaining ones using the modulo trick
- for(//"constructed" comes from the previous loop
- ; constructed < src_bucket_count
- ; ++constructed){
- bucket_type &dst_b = (power_2_buckets)
- ? dst_buckets[constructed & (dst_bucket_count-1)]
- : dst_buckets[constructed % dst_bucket_count];
- bucket_type &src_b = src_buckets[constructed];
- for( siterator b(src_b.begin()), e(src_b.end())
- ; b != e
- ; ++b){
- dst_b.push_front(*detail::node_cloner<Cloner, hashtable_impl>
- (cloner, this)(b.pointed_node()));
- }
+ bucket_type &dst_b =
+ dst_buckets[priv_hash_to_bucket(constructed, dst_bucket_count)];
+ bucket_type &src_b = src_buckets[constructed];
+ for( siterator b(src_b.begin()), e(src_b.end())
+ ; b != e
+ ; ++b){
+ dst_b.push_front(*(NodeCloner(cloner, this)(*b.pointed_node())));
                   }
                }
             }
- BOOST_INTRUSIVE_CATCH(...){
- while(constructed--){
- dst_buckets[constructed].clear_and_dispose
- (detail::node_disposer<Disposer, hashtable_impl>(disposer, this));
- }
- BOOST_INTRUSIVE_RETHROW;
- }
- BOOST_INTRUSIVE_CATCH_END
+ rollback.release();
             this->priv_size_traits().set_size(src.priv_size_traits().get_size());
+ priv_insertion_update_cache(0u);
+ priv_erasure_update_cache();
          }
          else{
             //Unlike previous cloning algorithm, this can throw
             //if cloner, the hasher or comparison functor throw
             const_iterator b(src.begin()), e(src.end());
- BOOST_INTRUSIVE_TRY{
- for(; b != e; ++b){
- this->insert_equal(*cloner(*b));
- }
+ detail::exception_disposer<hashtable_impl, Disposer>
+ rollback(*this, disposer);
+ for(; b != e; ++b){
+ this->insert_equal(*cloner(*b));
             }
- BOOST_INTRUSIVE_CATCH(...){
- this->clear_and_dispose(disposer);
- BOOST_INTRUSIVE_RETHROW;
- }
- BOOST_INTRUSIVE_CATCH_END
+ rollback.release();
          }
       }
    }
 
    iterator insert_equal(reference value)
    {
- size_type bucket_num, hash_value;
+ size_type bucket_num;
+ std::size_t hash_value;
+ siterator prev;
       siterator it = this->priv_find
- (value, this->priv_hasher(), this->priv_equal(), bucket_num, hash_value);
+ (value, this->priv_hasher(), this->priv_equal(), bucket_num, hash_value, prev);
       bucket_type &b = this->priv_buckets()[bucket_num];
- if(it == invalid_local_it(this->get_real_bucket_traits())){
- it = b.before_begin();
- }
- node_ptr n = node_ptr(&from_value_to_node(value));
+ bool found_equal = it != priv_invalid_local_it();
+ node_ptr n = node_ptr(&priv_value_to_node(value));
       this->priv_store_hash(n, hash_value, store_hash_t());
       if(safemode_or_autounlink)
          BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
+ if(!found_equal){
+ it = b.before_begin();
+ }
+ this->priv_insert_in_group(found_equal ? dcast_bucket_ptr(it.pointed_node()) : node_ptr(0), n, optimize_multikey_t());
+ priv_insertion_update_cache(bucket_num);
       this->priv_size_traits().increment();
       return iterator(b.insert_after(it, *n), this);
    }
@@ -867,9 +933,10 @@
       , insert_commit_data &commit_data)
    {
       size_type bucket_num;
+ siterator prev;
       siterator prev_pos =
- this->priv_find(key, hash_func, equal_func, bucket_num, commit_data.hash);
- bool success = prev_pos == invalid_local_it(this->get_real_bucket_traits());
+ this->priv_find(key, hash_func, equal_func, bucket_num, commit_data.hash, prev);
+ bool success = prev_pos == priv_invalid_local_it();
       if(success){
          prev_pos = this->priv_buckets()[bucket_num].before_begin();
       }
@@ -897,14 +964,16 @@
    //! After a successful rehashing insert_commit_data remains valid.
    iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
    {
- size_type bucket_num = from_hash_to_bucket(commit_data.hash);
+ size_type bucket_num = priv_hash_to_bucket(commit_data.hash);
       bucket_type &b = this->priv_buckets()[bucket_num];
       this->priv_size_traits().increment();
- node_ptr n = node_ptr(&from_value_to_node(value));
+ node_ptr n = node_ptr(&priv_value_to_node(value));
       this->priv_store_hash(n, commit_data.hash, store_hash_t());
       if(safemode_or_autounlink)
          BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
- return iterator( b.insert_after(b.before_begin(), *n), this);
+ priv_insertion_update_cache(bucket_num);
+ this->priv_insert_in_group(node_ptr(0), n, optimize_multikey_t());
+ return iterator(b.insert_after(b.before_begin(), *n), this);
    }
 
    //! <b>Effects</b>: Erases the element pointed to by i.
@@ -983,12 +1052,9 @@
    template<class Disposer>
    void erase_and_dispose(const_iterator i, Disposer disposer)
    {
- siterator to_erase(i.slist_it());
- bucket_ptr f(priv_buckets()), l(f + priv_buckets_len());
- bucket_type &b = this->priv_buckets()[bucket_type::get_bucket_num(to_erase, *f, *l)];
- b.erase_after_and_dispose
- (b.previous(to_erase), detail::node_disposer<Disposer, hashtable_impl>(disposer, this));
+ priv_erase(i, disposer, optimize_multikey_t());
       this->priv_size_traits().decrement();
+ priv_erasure_update_cache();
    }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
@@ -1009,67 +1075,27 @@
       if(b == e) return;
 
       //Get the bucket number and local iterator for both iterators
- bucket_ptr f(priv_buckets()), l(f + priv_buckets_len());
- size_type first_bucket_num = bucket_type::get_bucket_num(b.slist_it(), *f, *l);
+ siterator first_local_it(b.slist_it());
+ size_type first_bucket_num = this->priv_get_bucket_num(first_local_it);
 
       siterator before_first_local_it
- = priv_buckets()[first_bucket_num].previous(b.slist_it());
+ = priv_get_previous(priv_buckets()[first_bucket_num], first_local_it);
       size_type last_bucket_num;
       siterator last_local_it;
 
       //For the end iterator, we will assign the end iterator
       //of the last bucket
- if(e == end()){
+ if(e == this->end()){
          last_bucket_num = this->bucket_count() - 1;
          last_local_it = priv_buckets()[last_bucket_num].end();
       }
       else{
          last_local_it = e.slist_it();
- last_bucket_num = bucket_type::get_bucket_num(last_local_it, *f, *l);
+ last_bucket_num = this->priv_get_bucket_num(last_local_it);
       }
-
- const bucket_ptr buckets = priv_buckets();
- //First erase the nodes of the first bucket
- {
- bucket_type &first_b = buckets[first_bucket_num];
- siterator nxt(before_first_local_it); ++nxt;
- siterator end = first_b.end();
- while(nxt != end){
- nxt = first_b.erase_after_and_dispose
- ( before_first_local_it
- , detail::node_disposer<Disposer, hashtable_impl>(disposer, this));
- this->priv_size_traits().decrement();
- }
- }
-
- //Now fully clear the intermediate buckets
- for(size_type i = first_bucket_num+1; i < last_bucket_num; ++i){
- bucket_type &b = buckets[i];
- if(b.empty())
- continue;
- siterator b_begin(b.before_begin());
- siterator nxt(b_begin); ++nxt;
- siterator end = b.end();
- while(nxt != end){
- nxt = b.erase_after_and_dispose
- (b_begin, detail::node_disposer<Disposer, hashtable_impl>(disposer, this));
- this->priv_size_traits().decrement();
- }
- }
-
- //Now erase nodes from the last bucket
- {
- bucket_type &last_b = buckets[last_bucket_num];
- siterator b_begin(last_b.before_begin());
- siterator nxt(b_begin); ++nxt;
- while(nxt != last_local_it){
- nxt = last_b.erase_after_and_dispose
- (b_begin, detail::node_disposer<Disposer, hashtable_impl>
- (disposer, this));
- this->priv_size_traits().decrement();
- }
- }
- }
+ priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer);
+ priv_erasure_update_cache(first_bucket_num, last_bucket_num);
+ }
 
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
@@ -1109,40 +1135,35 @@
    size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func
                               ,KeyValueEqual equal_func, Disposer disposer)
    {
+ size_type bucket_num;
+ std::size_t hash;
+ siterator prev;
+ siterator it =
+ this->priv_find(key, hash_func, equal_func, bucket_num, hash, prev);
+ bool success = it != priv_invalid_local_it();
       size_type count(0);
-
- if(constant_time_size && this->empty()){
+ if(!success){
          return 0;
       }
-
- bucket_type &b = this->priv_buckets()[from_hash_to_bucket(hash_func(key))];
- siterator it = b.begin();
- siterator prev = b.before_begin();
-
- bool found = false;
- //Find equal value
- while(it != b.end()){
- const value_type &v =
- *this->get_real_value_traits().to_value_ptr(it.pointed_node());
- if(equal_func(key, v)){
- found = true;
- break;
- }
- ++prev;
- ++it;
+ else if(optimize_multikey){
+ siterator last = bucket_type::s_iterator_to
+ (*node_traits::get_next(priv_get_last_in_group
+ (dcast_bucket_ptr(it.pointed_node()))));
+ this->priv_erase_range_impl(bucket_num, prev, last, disposer, count);
       }
-
- if(!found)
- return 0;
-
- //If found erase all equal values
- for(siterator end = b.end(); it != end &&
- equal_func(key, *this->get_real_value_traits().to_value_ptr(it.pointed_node()))
- ; ++count){
- it = b.erase_after_and_dispose
- (prev, detail::node_disposer<Disposer, hashtable_impl>(disposer, this));
- this->priv_size_traits().decrement();
+ else{
+ //If found erase all equal values
+ bucket_type &b = this->priv_buckets()[bucket_num];
+ for(siterator end = b.end(); it != end; ++count, ++it){
+ slist_node_ptr n(it.pointed_node());
+ if(!equal_func(key, priv_value_from_slist_node(n))){
+ break;
+ }
+ this->priv_size_traits().decrement();
+ }
+ b.erase_after_and_dispose(prev, it, make_node_disposer(disposer));
       }
+ priv_erasure_update_cache();
       return count;
    }
 
@@ -1179,11 +1200,11 @@
          size_type num_buckets = this->bucket_count();
          bucket_ptr b = this->priv_buckets();
          for(; num_buckets--; ++b){
- b->clear_and_dispose
- (detail::node_disposer<Disposer, hashtable_impl>(disposer, this));
+ b->clear_and_dispose(make_node_disposer(disposer));
          }
          this->priv_size_traits().set_size(size_type(0));
       }
+ priv_initialize_cache();
    }
 
    //! <b>Effects</b>: Returns the number of contained elements with the given value
@@ -1246,8 +1267,10 @@
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    iterator find(const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func)
    {
- size_type bucket_n, hash;
- siterator local_it = this->priv_find(key, hash_func, equal_func, bucket_n, hash);
+ size_type bucket_n;
+ std::size_t hash;
+ siterator prev;
+ siterator local_it = this->priv_find(key, hash_func, equal_func, bucket_n, hash, prev);
       return iterator(local_it, this);
    }
 
@@ -1283,8 +1306,10 @@
    const_iterator find
       (const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) const
    {
- size_type bucket_n, hash_value;
- siterator sit = this->priv_find(key, hash_func, equal_func, bucket_n, hash_value);
+ size_type bucket_n;
+ std::size_t hash_value;
+ siterator prev;
+ siterator sit = this->priv_find(key, hash_func, equal_func, bucket_n, hash_value, prev);
       return const_iterator(sit, this);
    }
 
@@ -1382,7 +1407,7 @@
    //! <b>Throws</b>: If the internal hash function throws.
    iterator iterator_to(reference value)
    {
- return iterator(bucket_type::s_iterator_to(from_value_to_node(value)), this);
+ return iterator(bucket_type::s_iterator_to(priv_value_to_node(value)), this);
    }
 
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
@@ -1396,12 +1421,9 @@
    //! <b>Throws</b>: If the internal hash function throws.
    const_iterator iterator_to(const_reference value) const
    {
- return const_iterator(bucket_type::s_iterator_to(from_value_to_node(const_cast<reference>(value))), this);
+ return const_iterator(bucket_type::s_iterator_to(priv_value_to_node(const_cast<reference>(value))), this);
    }
 
-
-
-
    //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
    //! appropriate type. Otherwise the behavior is undefined.
    //!
@@ -1417,7 +1439,7 @@
    static local_iterator s_local_iterator_to(reference value)
    {
       BOOST_STATIC_ASSERT((!stateful_value_traits));
- siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->from_value_to_node(value));
+ siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(value));
       return local_iterator(sit, (hashtable_impl*)0);
    }
 
@@ -1436,7 +1458,7 @@
    static const_local_iterator s_local_iterator_to(const_reference value)
    {
       BOOST_STATIC_ASSERT((!stateful_value_traits));
- siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->from_value_to_node(const_cast<value_type&>(value)));
+ siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(const_cast<value_type&>(value)));
       return const_local_iterator(sit, (hashtable_impl*)0);
    }
 
@@ -1451,7 +1473,7 @@
    //! <b>Throws</b>: Nothing.
    local_iterator local_iterator_to(reference value)
    {
- siterator sit = bucket_type::s_iterator_to(this->from_value_to_node(value));
+ siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value));
       return local_iterator(sit, this);
    }
 
@@ -1467,7 +1489,7 @@
    const_local_iterator local_iterator_to(const_reference value) const
    {
       siterator sit = bucket_type::s_iterator_to
- (const_cast<node &>(this->from_value_to_node(value)));
+ (const_cast<node &>(this->priv_value_to_node(value)));
       return const_local_iterator(sit, this);
    }
 
@@ -1515,7 +1537,7 @@
    //! <b>Note</b>: the return value is in the range [0, this->bucket_count()).
    template<class KeyType, class KeyHasher>
    size_type bucket(const KeyType& k, const KeyHasher &hash_func) const
- { return from_hash_to_bucket(hash_func(k)); }
+ { return priv_hash_to_bucket(hash_func(k)); }
 
    //! <b>Effects</b>: Returns the bucket array pointer passed in the constructor
    //! or the last rehash function.
@@ -1630,75 +1652,81 @@
       size_type new_buckets_len = new_bucket_traits.bucket_count();
       bucket_ptr old_buckets = this->priv_buckets();
       size_type old_buckets_len = this->priv_buckets_len();
+
       //Check power of two bucket array if the option is activated
       BOOST_INTRUSIVE_INVARIANT_ASSERT
       (!power_2_buckets || (0 == (new_buckets_len & (new_buckets_len-1u))));
 
- BOOST_INTRUSIVE_TRY{
- size_type n = 0;
- const bool same_buffer = old_buckets == new_buckets;
- //If the new bucket length is a common factor
- //of the old one we can avoid hash calculations.
- const bool fast_shrink = (old_buckets_len > new_buckets_len) &&
- (power_2_buckets ||(old_buckets_len % new_buckets_len) == 0);
- //If we are shrinking the same bucket array and it's
- //is a fast shrink, just rehash the last nodes
- if(same_buffer && fast_shrink){
- n = new_buckets_len;
- }
-
- //Iterate through nodes
- for(; n < old_buckets_len; ++n){
- bucket_type &old_bucket = old_buckets[n];
-
- if(!fast_shrink){
- siterator before_i(old_bucket.before_begin());
- siterator end(old_bucket.end());
- siterator i(old_bucket.begin());
- for(;i != end; ++i){
- const value_type &v = *this->get_real_value_traits().to_value_ptr(i.pointed_node());
- const std::size_t hash_value = this->priv_hash_when_rehashing(v, store_hash_t());
- const size_type new_n = (power_2_buckets)
- ? (hash_value & (new_buckets_len-1)) : (hash_value % new_buckets_len);
- //If this is a buffer expansion don't move if it's not necessary
- if(same_buffer && new_n == n){
- ++before_i;
- }
- else{
- bucket_type &new_b = new_buckets[new_n];
- new_b.splice_after(new_b.before_begin(), old_bucket, before_i);
- i = before_i;
- }
+ size_type n = this->priv_get_cache() - this->priv_buckets();
+ const bool same_buffer = old_buckets == new_buckets;
+ //If the new bucket length is a common factor
+ //of the old one we can avoid hash calculations.
+ const bool fast_shrink = (old_buckets_len > new_buckets_len) &&
+ (power_2_buckets ||(old_buckets_len % new_buckets_len) == 0);
+ //If we are shrinking the same bucket array and it's
+ //is a fast shrink, just rehash the last nodes
+ if(same_buffer && fast_shrink){
+ n = new_buckets_len;
+ }
+
+ //Anti-exception stuff: they destroy the elements if something goes wrong
+ typedef detail::init_disposer<node_algorithms> NodeDisposer;
+ NodeDisposer node_disp;
+ detail::exception_array_disposer<bucket_type, NodeDisposer>
+ rollback1(new_buckets[0], node_disp, new_buckets_len);
+ detail::exception_array_disposer<bucket_type, NodeDisposer>
+ rollback2(old_buckets[0], node_disp, old_buckets_len);
+
+ //Put size in a safe value for rollback exception
+ size_type size_backup = this->priv_size_traits().get_size();
+ this->priv_size_traits().set_size(0);
+ //Put cache to safe position
+ priv_initialize_cache();
+ priv_insertion_update_cache(size_type(0u));
+
+ //Iterate through nodes
+ for(; n < old_buckets_len; ++n){
+ bucket_type &old_bucket = old_buckets[n];
+
+ if(!fast_shrink){
+ siterator before_i(old_bucket.before_begin());
+ siterator end(old_bucket.end());
+ siterator i(old_bucket.begin());
+ for(;i != end; ++i){
+ const value_type &v = priv_value_from_slist_node(i.pointed_node());
+ const std::size_t hash_value = this->priv_stored_hash(v, store_hash_t());
+ const size_type new_n = priv_hash_to_bucket(hash_value, new_buckets_len);
+ siterator last = bucket_type::s_iterator_to
+ (*priv_get_last_in_group(dcast_bucket_ptr(i.pointed_node())));
+ if(same_buffer && new_n == n){
+ before_i = last;
                }
- }
- else{
- const size_type new_n = (power_2_buckets)
- ? (n & (new_buckets_len-1))
- : (n % new_buckets_len);
- bucket_type &new_b = new_buckets[new_n];
- new_b.splice_after(new_b.before_begin(), old_bucket);
+ else{
+ bucket_type &new_b = new_buckets[new_n];
+ new_b.splice_after(new_b.before_begin(), old_bucket, before_i, last);
+ }
+ i = before_i;
             }
          }
-
- this->get_real_bucket_traits()= new_bucket_traits;
- }
- BOOST_INTRUSIVE_CATCH(...){
- for(size_type n = 0; n < new_buckets_len; ++n){
- if(safemode_or_autounlink){
- new_buckets[n].clear_and_dispose
- (detail::init_disposer<node_algorithms>());
- old_buckets[n].clear_and_dispose
- (detail::init_disposer<node_algorithms>());
- }
- else{
- new_buckets[n].clear();
- old_buckets[n].clear();
+ else{
+ const size_type new_n = priv_hash_to_bucket(n, new_buckets_len);
+ bucket_type &new_b = new_buckets[new_n];
+ if(!old_bucket.empty()){
+ new_b.splice_after( new_b.before_begin()
+ , old_bucket
+ , old_bucket.before_begin()
+ , priv_get_last(old_bucket));
             }
          }
- this->priv_size_traits().set_size(size_type(0));
- BOOST_INTRUSIVE_RETHROW;
       }
- BOOST_INTRUSIVE_CATCH_END
+
+ this->priv_size_traits().set_size(size_backup);
+ this->priv_real_bucket_traits() = new_bucket_traits;
+ priv_initialize_cache();
+ priv_insertion_update_cache(size_type(0u));
+ priv_erasure_update_cache();
+ rollback1.release();
+ rollback2.release();
    }
 
    //! <b>Effects</b>: Returns the nearest new bucket count optimized for
@@ -1714,8 +1742,7 @@
    {
       const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0];
       const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size;
- size_type const* bound =
- std::lower_bound(primes, primes_end, n);
+ size_type const* bound = std::lower_bound(primes, primes_end, n);
       if(bound == primes_end)
             bound--;
       return size_type(*bound);
@@ -1734,8 +1761,7 @@
    {
       const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0];
       const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size;
- size_type const* bound =
- std::upper_bound(primes, primes_end, n);
+ size_type const* bound = std::upper_bound(primes, primes_end, n);
       if(bound != primes_end)
             bound--;
       return size_type(*bound);
@@ -1743,72 +1769,666 @@
 
    /// @cond
    private:
+ std::size_t priv_hash_to_bucket(std::size_t hash_value) const
+ { return priv_hash_to_bucket(hash_value, power_2_buckets_t()); }
+
+ std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_<false>) const
+ { return hash_value % this->priv_real_bucket_traits().bucket_count(); }
+
+ std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_<true>) const
+ { return hash_value & (this->priv_real_bucket_traits().bucket_count() - 1); }
+
+ std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len) const
+ { return priv_hash_to_bucket(hash_value, bucket_len, power_2_buckets_t()); }
+
+ std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_<false>) const
+ { return hash_value % bucket_len; }
+
+ std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_<true>) const
+ { return hash_value & (bucket_len - 1); }
+
+ const key_equal &priv_equal() const
+ { return static_cast<const key_equal&>(this->bucket_hash_equal_.get()); }
+
+ key_equal &priv_equal()
+ { return static_cast<key_equal&>(this->bucket_hash_equal_.get()); }
+
+ value_type &priv_value_from_slist_node(slist_node_ptr n)
+ { return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); }
+
+ const value_type &priv_value_from_slist_node(slist_node_ptr n) const
+ { return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); }
+
+ const real_bucket_traits &priv_real_bucket_traits(detail::bool_<false>) const
+ { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
+
+ const real_bucket_traits &priv_real_bucket_traits(detail::bool_<true>) const
+ { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
+
+ real_bucket_traits &priv_real_bucket_traits(detail::bool_<false>)
+ { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
+
+ real_bucket_traits &priv_real_bucket_traits(detail::bool_<true>)
+ { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
+
+ const real_bucket_traits &priv_real_bucket_traits() const
+ { return this->priv_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
+
+ real_bucket_traits &priv_real_bucket_traits()
+ { return this->priv_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
+
+ const hasher &priv_hasher() const
+ { return static_cast<const hasher&>(this->bucket_hash_equal_.bucket_hash.get()); }
+
+ hasher &priv_hasher()
+ { return static_cast<hasher&>(this->bucket_hash_equal_.bucket_hash.get()); }
 
- std::size_t priv_hash_when_rehashing(const value_type &v, detail::true_)
+ bucket_ptr priv_buckets() const
+ { return this->priv_real_bucket_traits().bucket_begin(); }
+
+ size_type priv_buckets_len() const
+ { return this->priv_real_bucket_traits().bucket_count(); }
+
+ static node_ptr uncast(const_node_ptr ptr)
+ { return node_ptr(const_cast<node*>(detail::get_pointer(ptr))); }
+
+ node &priv_value_to_node(value_type &v)
+ { return *this->get_real_value_traits().to_node_ptr(v); }
+
+ const node &priv_value_to_node(const value_type &v) const
+ { return *this->get_real_value_traits().to_node_ptr(v); }
+
+ size_traits &priv_size_traits()
+ { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
+
+ const size_traits &priv_size_traits() const
+ { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
+
+ template<class Disposer>
+ void priv_erase_range_impl
+ (size_type bucket_num, siterator before_first_it, siterator end, Disposer disposer, size_type &num_erased)
+ {
+ const bucket_ptr buckets = priv_buckets();
+ bucket_type &b = buckets[bucket_num];
+
+ if(before_first_it == b.before_begin() && end == b.end()){
+ priv_erase_range_impl(bucket_num, 1, disposer, num_erased);
+ }
+ else{
+ num_erased = 0;
+ siterator to_erase(before_first_it);
+ ++to_erase;
+ slist_node_ptr end_ptr = end.pointed_node();
+ while(to_erase != end){
+ priv_erase_from_group(end_ptr, dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t());
+ to_erase = b.erase_after_and_dispose(before_first_it, make_node_disposer(disposer));
+ ++num_erased;
+ }
+ this->priv_size_traits().set_size(this->priv_size_traits().get_size()-num_erased);
+ }
+ }
+
+ template<class Disposer>
+ void priv_erase_range_impl
+ (size_type first_bucket_num, size_type num_buckets, Disposer disposer, size_type &num_erased)
+ {
+ //Now fully clear the intermediate buckets
+ const bucket_ptr buckets = priv_buckets();
+ num_erased = 0;
+ for(size_type i = first_bucket_num; i < (num_buckets + first_bucket_num); ++i){
+ bucket_type &b = buckets[i];
+ siterator b_begin(b.before_begin());
+ siterator nxt(b_begin);
+ ++nxt;
+ siterator end(b.end());
+ while(nxt != end){
+ priv_init_group(nxt.pointed_node(), optimize_multikey_t());
+ nxt = b.erase_after_and_dispose
+ (b_begin, make_node_disposer(disposer));
+ this->priv_size_traits().decrement();
+ ++num_erased;
+ }
+ }
+ }
+
+ template<class Disposer>
+ void priv_erase_range( siterator before_first_it, size_type first_bucket
+ , siterator last_it, size_type last_bucket
+ , Disposer disposer)
+ {
+ size_type num_erased;
+ if (first_bucket == last_bucket){
+ priv_erase_range_impl(first_bucket, before_first_it, last_it, disposer, num_erased);
+ }
+ else {
+ bucket_type *b = (&this->priv_buckets()[0]);
+ priv_erase_range_impl(first_bucket, before_first_it, b[first_bucket].end(), disposer, num_erased);
+ if(size_type n = (last_bucket - first_bucket - 1))
+ priv_erase_range_impl(first_bucket + 1, n, disposer, num_erased);
+ priv_erase_range_impl(last_bucket, b[last_bucket].before_begin(), last_it, disposer, num_erased);
+ }
+ }
+
+ static node_ptr dcast_bucket_ptr(typename slist_impl::node_ptr p)
+ { return node_ptr(&static_cast<node&>(*p)); }
+
+ std::size_t priv_stored_hash(const value_type &v, detail::true_)
    { return node_traits::get_hash(this->get_real_value_traits().to_node_ptr(v)); }
 
- std::size_t priv_hash_when_rehashing(const value_type &v, detail::false_)
+ std::size_t priv_stored_hash(const value_type &v, detail::false_)
    { return priv_hasher()(v); }
 
- void priv_store_hash(node_ptr p, std::size_t h, detail::true_)
+ std::size_t priv_stored_hash(slist_node_ptr n, detail::true_)
+ { return node_traits::get_hash(dcast_bucket_ptr(n)); }
+
+ std::size_t priv_stored_hash(slist_node_ptr, detail::false_)
+ {
+ //This code should never be reached!
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(0);
+ return 0;
+ }
+
+ static void priv_store_hash(node_ptr p, std::size_t h, detail::true_)
    { return node_traits::set_hash(p, h); }
 
- void priv_store_hash(node_ptr, std::size_t, detail::false_)
+ static void priv_store_hash(node_ptr, std::size_t, detail::false_)
+ {}
+
+ static void priv_clear_group_nodes(bucket_type &b, detail::true_)
+ {
+ siterator it(b.begin()), itend(b.end());
+ while(it != itend){
+ node_ptr to_erase(dcast_bucket_ptr(it.pointed_node()));
+ ++it;
+ group_algorithms::init(to_erase);
+ }
+ }
+
+ static void priv_clear_group_nodes(bucket_type &, detail::false_)
+ {}
+
+ std::size_t priv_get_bucket_num(siterator it)
+ { return priv_get_bucket_num_hash_dispatch(it, store_hash_t()); }
+
+ std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::true_)
+ {
+ return this->priv_hash_to_bucket
+ (this->priv_stored_hash(it.pointed_node(), store_hash_t()));
+ }
+
+ std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_)
+ { return priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); }
+
+ std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::true_)
+ {
+ bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1);
+ slist_node_ptr bb = priv_get_bucket_before_begin
+ ( f->end().pointed_node()
+ , l->end().pointed_node()
+ , dcast_bucket_ptr(it.pointed_node()));
+ //Now get the bucket_impl from the iterator
+ const bucket_type &b = static_cast<const bucket_type&>
+ (bucket_type::slist_type::container_from_end_iterator(bucket_type::s_iterator_to(*bb)));
+ //Now just calculate the index b has in the bucket array
+ return static_cast<size_type>(&b - &*f);
+ }
+
+ std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::false_)
+ {
+ bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1);
+ slist_node_ptr first_ptr(f->cend().pointed_node())
+ , last_ptr(l->cend().pointed_node());
+
+ //The end node is embedded in the singly linked list:
+ //iterate until we reach it.
+ while(!(first_ptr <= it.pointed_node() && it.pointed_node() <= last_ptr)){
+ ++it;
+ }
+ //Now get the bucket_impl from the iterator
+ const bucket_type &b = static_cast<const bucket_type&>
+ (bucket_type::container_from_end_iterator(it));
+
+ //Now just calculate the index b has in the bucket array
+ return static_cast<std::size_t>(&b - &*f);
+ }
+
+ void priv_erase_from_group(slist_node_ptr end_ptr, node_ptr to_erase_ptr, detail::true_)
+ {
+ node_ptr nxt_ptr(node_traits::get_next(to_erase_ptr));
+ node_ptr prev_in_group_ptr(group_traits::get_next(to_erase_ptr));
+ bool last_in_group = (end_ptr == nxt_ptr) ||
+ (group_traits::get_next(nxt_ptr) != to_erase_ptr);
+ bool first_in_group = node_traits::get_next(prev_in_group_ptr) != to_erase_ptr;
+
+ if(first_in_group && last_in_group){
+ group_algorithms::init(to_erase_ptr);
+ }
+ else if(first_in_group){
+ group_algorithms::unlink_after(nxt_ptr);
+ }
+ else if(last_in_group){
+ node_ptr first_in_group = //possible_first_in_group ? possible_first_in_group :
+ priv_get_first_in_group_of_last_in_group(to_erase_ptr);
+ group_algorithms::unlink_after(first_in_group);
+ //possible_first_in_group = 0;
+ }
+ else{
+ group_algorithms::unlink_after(nxt_ptr);
+ }
+ }
+
+ void priv_erase_from_group(slist_node_ptr, node_ptr, detail::false_)
+ {}
+
+ void priv_init_group(slist_node_ptr n, detail::true_)
+ { group_algorithms::init(dcast_bucket_ptr(n)); }
+
+ void priv_init_group(slist_node_ptr, detail::false_)
+ {}
+
+ void priv_insert_in_group(node_ptr first_in_group, node_ptr n, detail::true_)
+ {
+ if(first_in_group){
+ if(group_algorithms::unique(first_in_group))
+ group_algorithms::link_after(first_in_group, n);
+ else{
+ group_algorithms::link_after(node_traits::get_next(first_in_group), n);
+ }
+ }
+ else{
+ group_algorithms::init_header(n);
+ }
+ }
+
+ static slist_node_ptr priv_get_bucket_before_begin
+ (slist_node_ptr bucket_beg, slist_node_ptr bucket_end, node_ptr p)
+ {
+ //First find the last node of p's group.
+ //This requires checking the first node of the next group or
+ //the bucket node.
+ node_ptr prev_node = p;
+ node_ptr nxt(node_traits::get_next(p));
+ while(!(bucket_beg <= nxt && nxt <= bucket_end) &&
+ (group_traits::get_next(nxt) == prev_node)){
+ prev_node = nxt;
+ nxt = node_traits::get_next(nxt);
+ }
+
+ //If we've reached the bucket node just return it.
+ if(bucket_beg <= nxt && nxt <= bucket_end){
+ return nxt;
+ }
+
+ //Otherwise, iterate using group links until the bucket node
+ node_ptr first_node_of_group = nxt;
+ node_ptr last_node_group = group_traits::get_next(first_node_of_group);
+ slist_node_ptr possible_end = node_traits::get_next(last_node_group);
+
+ while(!(bucket_beg <= possible_end && possible_end <= bucket_end)){
+ first_node_of_group = dcast_bucket_ptr(possible_end);
+ last_node_group = group_traits::get_next(first_node_of_group);
+ possible_end = node_traits::get_next(last_node_group);
+ }
+ return possible_end;
+ }
+
+ static node_ptr priv_get_prev_to_first_in_group(slist_node_ptr bucket_node, node_ptr first_in_group)
+ {
+ //Just iterate using group links and obtain the node
+ //before "first_in_group)"
+ node_ptr prev_node = dcast_bucket_ptr(bucket_node);
+ node_ptr nxt(node_traits::get_next(prev_node));
+ while(nxt != first_in_group){
+ prev_node = group_traits::get_next(nxt);
+ nxt = node_traits::get_next(prev_node);
+ }
+ return prev_node;
+ }
+
+ static node_ptr priv_get_first_in_group_of_last_in_group(node_ptr last_in_group)
+ {
+ //Just iterate using group links and obtain the node
+ //before "last_in_group"
+ node_ptr possible_first = group_traits::get_next(last_in_group);
+ node_ptr possible_first_prev = group_traits::get_next(possible_first);
+ // The deleted node is at the end of the group, so the
+ // node in the group pointing to it is at the beginning
+ // of the group. Find that to change its pointer.
+ while(possible_first_prev != last_in_group){
+ possible_first = possible_first_prev;
+ possible_first_prev = group_traits::get_next(possible_first);
+ }
+ return possible_first;
+ }
+
+ void priv_insert_in_group(node_ptr, node_ptr, detail::false_)
    {}
+
+ static node_ptr priv_get_last_in_group(node_ptr first_in_group)
+ { return priv_get_last_in_group(first_in_group, optimize_multikey_t()); }
+
+ static node_ptr priv_get_last_in_group(node_ptr first_in_group, detail::true_)
+ { return group_traits::get_next(first_in_group); }
+
+ static node_ptr priv_get_last_in_group(node_ptr n, detail::false_)
+ { return n; }
+
+ siterator priv_get_previous
+ (bucket_type &b, siterator i)
+ { return priv_get_previous(b, i, optimize_multikey_t()); }
+
+ siterator priv_get_previous
+ (bucket_type &b, siterator i, detail::true_)
+ {
+ node_ptr elem(dcast_bucket_ptr(i.pointed_node()));
+ node_ptr prev_in_group(group_traits::get_next(elem));
+ bool first_in_group = node_traits::get_next(prev_in_group) != elem;
+
+ typename bucket_type::node &n = first_in_group
+ ? *priv_get_prev_to_first_in_group(b.end().pointed_node(), elem)
+ : *group_traits::get_next(elem)
+ ;
+ return bucket_type::s_iterator_to(n);
+ }
+
+ siterator priv_get_previous
+ (bucket_type &b, siterator i, detail::false_)
+ { return b.previous(i); }
+
+ static siterator priv_get_last(bucket_type &b)
+ { return priv_get_last(b, optimize_multikey_t()); }
+
+ static siterator priv_get_last(bucket_type &b, detail::true_)
+ {
+ //First find the last node of p's group.
+ //This requires checking the first node of the next group or
+ //the bucket node.
+ slist_node_ptr end_ptr(b.end().pointed_node());
+ node_ptr possible_end(node_traits::get_next( dcast_bucket_ptr(end_ptr)));
+ node_ptr last_node_group(possible_end);
+
+ while(end_ptr != possible_end){
+ last_node_group = group_traits::get_next(dcast_bucket_ptr(possible_end));
+ possible_end = node_traits::get_next(last_node_group);
+ }
+ return bucket_type::s_iterator_to(*last_node_group);
+ }
+
+ static siterator priv_get_last(bucket_type &b, detail::false_)
+ { return b.previous(b.end()); }
+
+ siterator priv_get_previous_and_next_in_group
+ (siterator i, node_ptr &nxt_in_group)
+ {
+ siterator prev;
+ node_ptr elem(dcast_bucket_ptr(i.pointed_node()));
+ bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1);
+
+ slist_node_ptr first_end_ptr(f->cend().pointed_node());
+ slist_node_ptr last_end_ptr (l->cend().pointed_node());
+
+ node_ptr nxt(node_traits::get_next(elem));
+ node_ptr prev_in_group(group_traits::get_next(elem));
+ bool last_in_group = (first_end_ptr <= nxt && nxt <= last_end_ptr) ||
+ (group_traits::get_next(nxt) != elem);
+ bool first_in_group = node_traits::get_next(prev_in_group) != elem;
+
+ if(first_in_group){
+ node_ptr start_pos;
+ if(last_in_group){
+ start_pos = elem;
+ nxt_in_group = 0;
+ }
+ else{
+ start_pos = prev_in_group;
+ nxt_in_group = node_traits::get_next(elem);
+ }
+ slist_node_ptr bucket_node;
+ if(store_hash){
+ bucket_node = this->priv_buckets()
+ [this->priv_hash_to_bucket
+ (this->priv_stored_hash(elem, store_hash_t()))
+ ].before_begin().pointed_node();
+ }
+ else{
+ bucket_node = priv_get_bucket_before_begin
+ (first_end_ptr, last_end_ptr, start_pos);
+ }
+ prev = bucket_type::s_iterator_to
+ (*priv_get_prev_to_first_in_group(bucket_node, elem));
+ }
+ else{
+ if(last_in_group){
+ nxt_in_group = priv_get_first_in_group_of_last_in_group(elem);
+ }
+ else{
+ nxt_in_group = node_traits::get_next(elem);
+ }
+ prev = bucket_type::s_iterator_to(*group_traits::get_next(elem));
+ }
+ return prev;
+ }
+
+ template<class Disposer>
+ void priv_erase(const_iterator i, Disposer disposer, detail::true_)
+ {
+ siterator elem(i.slist_it());
+ node_ptr nxt_in_group;
+ siterator prev = priv_get_previous_and_next_in_group(elem, nxt_in_group);
+ bucket_type::s_erase_after_and_dispose(prev, make_node_disposer(disposer));
+ if(nxt_in_group)
+ group_algorithms::unlink_after(nxt_in_group);
+ if(safemode_or_autounlink)
+ group_algorithms::init(dcast_bucket_ptr(elem.pointed_node()));
+ }
+
+ template <class Disposer>
+ void priv_erase(const_iterator i, Disposer disposer, detail::false_)
+ {
+ siterator to_erase(i.slist_it());
+ bucket_type &b = this->priv_buckets()[this->priv_get_bucket_num(to_erase)];
+ siterator prev(priv_get_previous(b, to_erase));
+ b.erase_after_and_dispose(prev, make_node_disposer(disposer));
+ }
+
+ bucket_ptr priv_invalid_bucket() const
+ {
+ const real_bucket_traits &rbt = this->priv_real_bucket_traits();
+ return rbt.bucket_begin() + rbt.bucket_count();
+ }
    
- static siterator invalid_local_it(const real_bucket_traits &b)
- { return b.bucket_begin()->end(); }
+ siterator priv_invalid_local_it() const
+ { return priv_invalid_bucket()->end(); }
 
    siterator priv_begin(size_type &bucket_num) const
+ { return priv_begin(bucket_num, cache_begin_t()); }
+
+ siterator priv_begin(size_type &bucket_num, detail::bool_<false>) const
    {
+ size_type n = 0;
       size_type buckets_len = this->priv_buckets_len();
- for (bucket_num = 0; bucket_num < buckets_len; ++bucket_num){
- bucket_type &b = this->priv_buckets()[bucket_num];
- if(!b.empty())
+ for (n = 0; n < buckets_len; ++n){
+ bucket_type &b = this->priv_buckets()[n];
+ if(!b.empty()){
+ bucket_num = n;
             return b.begin();
+ }
+ }
+ bucket_num = n;
+ return priv_invalid_local_it();
+ }
+
+ siterator priv_begin(size_type &bucket_num, detail::bool_<true>) const
+ {
+ bucket_num = this->bucket_hash_equal_.cached_begin_ - this->priv_buckets();
+ if(this->bucket_hash_equal_.cached_begin_ == priv_invalid_bucket()){
+ return priv_invalid_local_it();
+ }
+ else{
+ return this->bucket_hash_equal_.cached_begin_->begin();
+ }
+ }
+
+ void priv_initialize_cache()
+ { priv_initialize_cache(cache_begin_t()); }
+
+ void priv_initialize_cache(detail::bool_<true>)
+ { this->bucket_hash_equal_.cached_begin_ = priv_invalid_bucket(); }
+
+ void priv_initialize_cache(detail::bool_<false>)
+ {}
+
+ void priv_insertion_update_cache(size_type insertion_bucket)
+ { priv_insertion_update_cache(insertion_bucket, cache_begin_t()); }
+
+ void priv_insertion_update_cache(size_type insertion_bucket, detail::bool_<true>)
+ {
+ bucket_ptr p = priv_buckets() + insertion_bucket;
+ if(p < this->bucket_hash_equal_.cached_begin_){
+ this->bucket_hash_equal_.cached_begin_ = p;
+ }
+ }
+
+ void priv_insertion_update_cache(size_type, detail::bool_<false>)
+ {}
+
+ void priv_erasure_update_cache(size_type first_bucket, size_type last_bucket)
+ { priv_erasure_update_cache(first_bucket, last_bucket, cache_begin_t()); }
+
+ void priv_erasure_update_cache(size_type first_bucket_num, size_type last_bucket_num, detail::bool_<true>)
+ {
+ //If the last bucket is the end, the cache must be updated
+ //to the last position if all
+ if(priv_get_cache_bucket_num() == first_bucket_num &&
+ priv_buckets()[first_bucket_num].empty() ){
+ priv_set_cache(priv_buckets() + last_bucket_num);
+ priv_erasure_update_cache();
+ }
+ }
+
+ void priv_erasure_update_cache(size_type, size_type, detail::bool_<false>)
+ {}
+
+ void priv_erasure_update_cache()
+ { priv_erasure_update_cache(cache_begin_t()); }
+
+ void priv_erasure_update_cache(detail::bool_<true>)
+ {
+ if(constant_time_size && !size()){
+ priv_initialize_cache();
+ }
+ else{
+ size_type current_n = this->bucket_hash_equal_.cached_begin_ - priv_buckets();
+ for( const size_type num_buckets = this->priv_buckets_len()
+ ; current_n < num_buckets
+ ; ++current_n, ++this->bucket_hash_equal_.cached_begin_){
+ if(!this->bucket_hash_equal_.cached_begin_->empty()){
+ return;
+ }
+ }
+ priv_initialize_cache();
       }
- return invalid_local_it(this->get_real_bucket_traits());
    }
 
+ void priv_erasure_update_cache(detail::bool_<false>)
+ {}
+
+ void priv_swap_cache(detail::bool_<true>, hashtable_impl &other)
+ {
+ std::swap( this->bucket_hash_equal_.cached_begin_
+ , other.bucket_hash_equal_.cached_begin_);
+ }
+
+ void priv_swap_cache(detail::bool_<false>, hashtable_impl &)
+ {}
+
+ bucket_ptr priv_get_cache()
+ { return priv_get_cache(cache_begin_t()); }
+
+ bucket_ptr priv_get_cache(detail::bool_<true>)
+ { return this->bucket_hash_equal_.cached_begin_; }
+
+ bucket_ptr priv_get_cache(detail::bool_<false>)
+ { return this->priv_buckets(); }
+
+ void priv_set_cache(bucket_ptr p)
+ { priv_set_cache(p, cache_begin_t()); }
+
+ void priv_set_cache(bucket_ptr p, detail::bool_<true>)
+ { this->bucket_hash_equal_.cached_begin_ = p; }
+
+ void priv_set_cache(bucket_ptr, detail::bool_<false>)
+ {}
+
+ size_type priv_get_cache_bucket_num()
+ { return priv_get_cache_bucket_num(cache_begin_t()); }
+
+ size_type priv_get_cache_bucket_num(detail::bool_<true>)
+ { return this->bucket_hash_equal_.cached_begin_ - this->priv_buckets(); }
+
+ size_type priv_get_cache_bucket_num(detail::bool_<false>)
+ { return 0u; }
+
    void priv_clear_buckets()
- { priv_clear_buckets(this->priv_buckets(), this->priv_buckets_len()); }
+ {
+ this->priv_clear_buckets
+ ( priv_get_cache()
+ , this->priv_buckets_len() - (priv_get_cache() - priv_buckets()));
+ }
 
- static void priv_clear_buckets(bucket_ptr buckets_ptr, size_type buckets_len)
+ void priv_initialize_buckets()
+ {
+ this->priv_clear_buckets
+ ( priv_buckets(), this->priv_buckets_len());
+ }
+
+ void priv_clear_buckets(bucket_ptr buckets_ptr, size_type buckets_len)
    {
       for(; buckets_len--; ++buckets_ptr){
          if(safemode_or_autounlink){
+ priv_clear_group_nodes(*buckets_ptr, optimize_multikey_t());
             buckets_ptr->clear_and_dispose(detail::init_disposer<node_algorithms>());
          }
          else{
             buckets_ptr->clear();
          }
       }
+ priv_initialize_cache();
    }
 
    template<class KeyType, class KeyHasher, class KeyValueEqual>
    siterator priv_find
       ( const KeyType &key, KeyHasher hash_func
- , KeyValueEqual equal_func, size_type &bucket_number, size_type &h) const
+ , KeyValueEqual equal_func, size_type &bucket_number, std::size_t &h, siterator &previt) const
    {
- bucket_number = from_hash_to_bucket((h = hash_func(key)));
+ bucket_number = priv_hash_to_bucket((h = hash_func(key)));
 
       if(constant_time_size && this->empty()){
- return invalid_local_it(this->get_real_bucket_traits());
+ return priv_invalid_local_it();
       }
       
       bucket_type &b = this->priv_buckets()[bucket_number];
- siterator it = b.begin();
+ previt = b.before_begin();
+ siterator it = previt;
+ ++it;
 
       while(it != b.end()){
- const value_type &v =
- *this->get_real_value_traits().to_value_ptr(it.pointed_node());
+ const value_type &v = priv_value_from_slist_node(it.pointed_node());
          if(equal_func(key, v)){
             return it;
          }
+ if(optimize_multikey){
+ previt = bucket_type::s_iterator_to
+ (*priv_get_last_in_group(dcast_bucket_ptr(it.pointed_node())));
+ it = previt;
+ }
+ else{
+ previt = it;
+ }
          ++it;
       }
 
- return invalid_local_it(this->get_real_bucket_traits());
+ return priv_invalid_local_it();
    }
 
    template<class KeyType, class KeyHasher, class KeyValueEqual>
@@ -1820,33 +2440,44 @@
       , size_type &bucket_number_second
       , size_type &count) const
    {
- size_type h;
+ std::size_t h;
       count = 0;
+ siterator prev;
       //Let's see if the element is present
       std::pair<siterator, siterator> to_return
- ( priv_find(key, hash_func, equal_func, bucket_number_first, h)
- , invalid_local_it(this->get_real_bucket_traits()));
+ ( priv_find(key, hash_func, equal_func, bucket_number_first, h, prev)
+ , priv_invalid_local_it());
       if(to_return.first == to_return.second){
          bucket_number_second = bucket_number_first;
          return to_return;
       }
- ++count;
       //If it's present, find the first that it's not equal in
       //the same bucket
       bucket_type &b = this->priv_buckets()[bucket_number_first];
       siterator it = to_return.first;
- ++it;
-
- while(it != b.end()){
- const value_type &v =
- *this->get_real_value_traits().to_value_ptr(it.pointed_node());
- if(!equal_func(key, v)){
- to_return.second = it;
+ if(optimize_multikey){
+ to_return.second = bucket_type::s_iterator_to
+ (*node_traits::get_next(priv_get_last_in_group
+ (dcast_bucket_ptr(it.pointed_node()))));
+ count = std::distance(it, to_return.second);
+ if(to_return.second != b.end()){
             bucket_number_second = bucket_number_first;
             return to_return;
          }
- ++it;
+ }
+ else{
          ++count;
+ ++it;
+ while(it != b.end()){
+ const value_type &v = priv_value_from_slist_node(it.pointed_node());
+ if(!equal_func(key, v)){
+ to_return.second = it;
+ bucket_number_second = bucket_number_first;
+ return to_return;
+ }
+ ++it;
+ ++count;
+ }
       }
    
       //If we reached the end, find the first, non-empty bucket
@@ -1861,22 +2492,24 @@
       }
 
       //Otherwise, return the end node
- to_return.second = invalid_local_it(this->get_real_bucket_traits());
+ to_return.second = priv_invalid_local_it();
       return to_return;
    }
    /// @endcond
 };
 
 /// @cond
-template<class T, class O1 = none, class O2 = none
- , class O3 = none, class O4 = none
- , class O5 = none, class O6 = none
- , class O7 = none
- >
+template < class T
+ , bool UniqueKeys
+ , class O1 = none, class O2 = none
+ , class O3 = none, class O4 = none
+ , class O5 = none, class O6 = none
+ , class O7 = none, class O8 = none
+ >
 struct make_hashtable_opt
 {
    typedef typename pack_options
- < uset_defaults<T>, O1, O2, O3, O4, O5, O6, O7>::type packed_options;
+ < uset_defaults<T>, O1, O2, O3, O4, O5, O6, O7, O8>::type packed_options;
 
    //Real value traits must be calculated from options
    typedef typename detail::get_value_traits
@@ -1891,9 +2524,16 @@
>::type real_value_traits;
    typedef typename packed_options::bucket_traits specified_bucket_traits;
    /// @endcond
- //Real bucket traits must be calculated from options and calculated valute_traits
- typedef typename get_slist_impl
- <typename real_value_traits::node_traits>::type slist_impl;
+
+ //Real bucket traits must be calculated from options and calculated value_traits
+ typedef typename detail::get_slist_impl
+ <typename detail::reduced_slist_node_traits
+ <typename real_value_traits::node_traits>::type
+ >::type slist_impl;
+
+ typedef typename detail::reduced_slist_node_traits
+ <typename real_value_traits::node_traits>::type node_traits;
+
    typedef typename
       detail::if_c< detail::is_same
                      < specified_bucket_traits
@@ -1905,12 +2545,14 @@
 
    typedef usetopt
       < value_traits
+ , UniqueKeys
       , typename packed_options::hash
       , typename packed_options::equal
       , typename packed_options::size_type
       , packed_options::constant_time_size
       , real_bucket_traits
       , packed_options::power_2_buckets
+ , packed_options::cache_begin
> type;
 };
 /// @endcond
@@ -1923,7 +2565,7 @@
 template<class T, class O1 = none, class O2 = none
                 , class O3 = none, class O4 = none
                 , class O5 = none, class O6 = none
- , class O7 = none
+ , class O7 = none, class O8 = none
>
 #endif
 struct make_hashtable
@@ -1931,7 +2573,7 @@
    /// @cond
    typedef hashtable_impl
       < typename make_hashtable_opt
- <T, O1, O2, O3, O4, O5, O6, O7>::type
+ <T, false, O1, O2, O3, O4, O5, O6, O7, O8>::type
> implementation_defined;
 
    /// @endcond
@@ -1939,12 +2581,12 @@
 };
 
 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
-template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7>
+template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8>
 class hashtable
- : public make_hashtable<T, O1, O2, O3, O4, O5, O6, O7>::type
+ : public make_hashtable<T, O1, O2, O3, O4, O5, O6, O7, O8>::type
 {
    typedef typename make_hashtable
- <T, O1, O2, O3, O4, O5, O6, O7>::type Base;
+ <T, O1, O2, O3, O4, O5, O6, O7, O8>::type Base;
 
    public:
    typedef typename Base::value_traits value_traits;

Modified: trunk/boost/intrusive/intrusive_fwd.hpp
==============================================================================
--- trunk/boost/intrusive/intrusive_fwd.hpp (original)
+++ trunk/boost/intrusive/intrusive_fwd.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -283,8 +283,7 @@
>
 class bs_set_member_hook;
 
-//hash/unordered
-//rbtree/set/multiset
+//hashtable/unordered_set/unordered_multiset
 template
    < class T
    , class O1 = none
@@ -294,6 +293,7 @@
    , class O5 = none
    , class O6 = none
    , class O7 = none
+ , class O8 = none
>
 class hashtable;
 
@@ -306,6 +306,7 @@
    , class O5 = none
    , class O6 = none
    , class O7 = none
+ , class O8 = none
>
 class unordered_set;
 
@@ -318,6 +319,7 @@
    , class O5 = none
    , class O6 = none
    , class O7 = none
+ , class O8 = none
>
 class unordered_multiset;
 

Modified: trunk/boost/intrusive/linear_slist_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/linear_slist_algorithms.hpp (original)
+++ trunk/boost/intrusive/linear_slist_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -136,7 +136,7 @@
    //!
    //! <b>Throws</b>: Nothing.
    static void init_header(node_ptr this_node)
- { NodeTraits::set_next(this_node, 0); }
+ { NodeTraits::set_next(this_node, node_ptr(0)); }
 
    //! <b>Requires</b>: this_node and prev_init_node must be in the same linear list.
    //!
@@ -195,7 +195,7 @@
    //! <b>Complexity</b>: This function is linear to the contained elements.
    static node_ptr reverse(node_ptr p)
    {
- if(!p) return 0;
+ if(!p) return node_ptr(0);
       node_ptr i = NodeTraits::get_next(p);
       node_ptr first(p);
       while(i){
@@ -218,7 +218,7 @@
    //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
    static std::pair<node_ptr, node_ptr> move_first_n_backwards(node_ptr p, std::size_t n)
    {
- std::pair<node_ptr, node_ptr> ret(0, 0);
+ std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0));
       //Null shift, or count() == 0 or 1, nothing to do
       if(!n || !p || !NodeTraits::get_next(p)){
          return ret;
@@ -252,12 +252,12 @@
       //If the p has not been found in the previous loop, find it
       //starting in the new first node and unlink it
       if(!end_found){
- old_last = base_t::get_previous_node(first, 0);
+ old_last = base_t::get_previous_node(first, node_ptr(0));
       }
       
       //Now link p after the new last node
       NodeTraits::set_next(old_last, p);
- NodeTraits::set_next(new_last, 0);
+ NodeTraits::set_next(new_last, node_ptr(0));
       ret.first = first;
       ret.second = new_last;
       return ret;
@@ -273,7 +273,7 @@
    //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions.
    static std::pair<node_ptr, node_ptr> move_first_n_forward(node_ptr p, std::size_t n)
    {
- std::pair<node_ptr, node_ptr> ret(0, 0);
+ std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0));
       //Null shift, or count() == 0 or 1, nothing to do
       if(!n || !p || !NodeTraits::get_next(p))
          return ret;
@@ -311,7 +311,7 @@
       node_ptr new_first(node_traits::get_next(new_last));
       //Now put the old beginning after the old end
       NodeTraits::set_next(old_last, p);
- NodeTraits::set_next(new_last, 0);
+ NodeTraits::set_next(new_last, node_ptr(0));
       ret.first = new_first;
       ret.second = new_last;
       return ret;

Modified: trunk/boost/intrusive/list.hpp
==============================================================================
--- trunk/boost/intrusive/list.hpp (original)
+++ trunk/boost/intrusive/list.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -24,7 +24,7 @@
 #include <boost/intrusive/link_mode.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/intrusive/options.hpp>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
+#include <boost/intrusive/detail/utilities.hpp>
 #include <iterator>
 #include <algorithm>
 #include <functional>
@@ -732,17 +732,13 @@
    void clone_from(const list_impl &src, Cloner cloner, Disposer disposer)
    {
       this->clear_and_dispose(disposer);
- BOOST_INTRUSIVE_TRY{
- const_iterator b(src.begin()), e(src.end());
- for(; b != e; ++b){
- this->push_back(*cloner(*b));
- }
- }
- BOOST_INTRUSIVE_CATCH(...){
- this->clear_and_dispose(disposer);
- BOOST_INTRUSIVE_RETHROW;
+ detail::exception_disposer<list_impl, Disposer>
+ rollback(*this, disposer);
+ const_iterator b(src.begin()), e(src.end());
+ for(; b != e; ++b){
+ this->push_back(*cloner(*b));
       }
- BOOST_INTRUSIVE_CATCH_END
+ rollback.release();
    }
 
    //! <b>Requires</b>: value must be an lvalue and p must be a valid iterator of *this.

Modified: trunk/boost/intrusive/options.hpp
==============================================================================
--- trunk/boost/intrusive/options.hpp (original)
+++ trunk/boost/intrusive/options.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -406,6 +406,24 @@
 /// @endcond
 };
 
+//!This option setter specifies if the unordered hook
+//!should offer room to store another link to another node
+//!with the same key.
+//!Storing this link will speed up lookups and insertions on
+//!unordered_multiset containers with a great number of elements
+//!with the same key.
+template<bool Enabled>
+struct optimize_multikey
+{
+/// @cond
+ template<class Base>
+ struct pack : Base
+ {
+ static const bool optimize_multikey = Enabled;
+ };
+/// @endcond
+};
+
 //!This option setter specifies if the bucket array will be always power of two.
 //!This allows using masks instead of the default modulo operation to determine
 //!the bucket number from the hash value, leading to better performance.
@@ -423,6 +441,22 @@
 /// @endcond
 };
 
+//!This option setter specifies if the container will cache a pointer to the first
+//!non-empty bucket so that begin() is always constant-time.
+//!This is specially helpful when we can have containers with a few elements
+//!but with big bucket arrays (that is, hashtables with low load factors).
+template<bool Enabled>
+struct cache_begin
+{
+/// @cond
+ template<class Base>
+ struct pack : Base
+ {
+ static const bool cache_begin = Enabled;
+ };
+/// @endcond
+};
+
 /// @cond
 
 template<class Prev, class Next>
@@ -500,6 +534,7 @@
       , optimize_size<false>
       , store_hash<false>
       , linear<false>
+ , optimize_multikey<false>
>::type
 {};
 

Deleted: trunk/boost/intrusive/pointer_plus_2_bits.hpp
==============================================================================
--- trunk/boost/intrusive/pointer_plus_2_bits.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
+++ (empty file)
@@ -1,82 +0,0 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2007
-//
-// 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)
-//
-// See http://www.boost.org/libs/intrusive for documentation.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_INTRUSIVE_POINTER_PLUS_2_BIT_HPP
-#define BOOST_INTRUSIVE_POINTER_PLUS_2_BIT_HPP
-
-namespace boost {
-namespace intrusive {
-
-//!This trait class is used to know if a pointer
-//!can embed 2 extra bits of information if
-//!it's going to be used to point to objects
-//!with an alignment of "Alignment" bytes.
-template<class VoidPointer, std::size_t Alignment>
-struct has_pointer_plus_2_bits
-{
- static const bool value = false;
-};
-
-//!This is an specialization for raw pointers.
-//!Raw pointers can embed two extra bits in the lower bits
-//!if the alignment is multiple of 4.
-template<std::size_t N>
-struct has_pointer_plus_2_bits<void*, N>
-{
- static const bool value = (N % 4u == 0);
-};
-
-//!This is class that is supposed to have static methods
-//!to embed 2 extra bits of information in a pointer.
-//!
-//!This is a declaration and there is no default implementation,
-//!because operations to embed bits change with every pointer type.
-//!
-//!An implementation that detects that a pointer type whose
-//!has_pointer_plus_2_bits<>::value is non-zero can make use of these
-//!operations to embed bits in the pointer.
-template<class Pointer>
-struct pointer_plus_2_bits
-{
- static const bool value = false;
-};
-
-//!This is the specialization to embed 2 extra bits of information
-//!in a raw pointer. Extra bits are stored in the lower bits of the pointer.
-template<class T>
-struct pointer_plus_2_bits<T*>
-{
- typedef T* pointer;
-
- static pointer get_pointer(pointer n)
- { return pointer(std::size_t(n) & ~std::size_t(3u)); }
-
- static void set_pointer(pointer &n, pointer p)
- {
- assert(0 == (std::size_t(p) & std::size_t(3u)));
- n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(3u)));
- }
-
- static std::size_t get_bits(pointer n)
- { return (std::size_t(n) & std::size_t(3u)); }
-
- static void set_bits(pointer &n, std::size_t c)
- {
- assert(c < 4);
- n = pointer(std::size_t(get_pointer(n)) | c);
- }
-};
-
-} //namespace intrusive
-} //namespace boost
-
-#endif //BOOST_INTRUSIVE_POINTER_PLUS_2_BIT_HPP

Deleted: trunk/boost/intrusive/pointer_plus_bit.hpp
==============================================================================
--- trunk/boost/intrusive/pointer_plus_bit.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
+++ (empty file)
@@ -1,78 +0,0 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2007
-//
-// 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)
-//
-// See http://www.boost.org/libs/intrusive for documentation.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
-#define BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP
-
-namespace boost {
-namespace intrusive {
-
-//!This trait class is used to know if a pointer
-//!can embed an extra bit of information if
-//!it's going to be used to point to objects
-//!with an alignment of "Alignment" bytes.
-template<class VoidPointer, std::size_t Alignment>
-struct has_pointer_plus_bit
-{
- static const bool value = false;
-};
-
-//!This is an specialization for raw pointers.
-//!Raw pointers can embed an extra bit in the lower bit
-//!if the alignment is multiple of 2.
-template<std::size_t N>
-struct has_pointer_plus_bit<void*, N>
-{
- static const bool value = (N % 2u == 0);
-};
-
-//!This is class that is supposed to have static methods
-//!to embed an extra bit of information in a pointer.
-//!This is a declaration and there is no default implementation,
-//!because operations to embed the bit change with every pointer type.
-//!
-//!An implementation that detects that a pointer type whose
-//!has_pointer_plus_bit<>::value is non-zero can make use of these
-//!operations to embed the bit in the pointer.
-template<class Pointer>
-struct pointer_plus_bit
-{
- static const bool value = false;
-};
-
-//!This is the specialization to embed an extra bit of information
-//!in a raw pointer. The extra bit is stored in the lower bit of the pointer.
-template<class T>
-struct pointer_plus_bit<T*>
-{
- typedef T* pointer;
-
- static pointer get_pointer(pointer n)
- { return pointer(std::size_t(n) & ~std::size_t(1u)); }
-
- static void set_pointer(pointer &n, pointer p)
- {
- assert(0 == (std::size_t(p) & std::size_t(1u)));
- n = pointer(std::size_t(p) | (std::size_t(n) & std::size_t(1u)));
- }
-
- static bool get_bit(pointer n)
- { return (std::size_t(n) & std::size_t(1u)) != 0; }
-
- static void set_bit(pointer &n, bool c)
- { n = pointer(std::size_t(get_pointer(n)) | std::size_t(c)); }
-};
-
-} //namespace intrusive
-} //namespace boost
-
-#endif //BOOST_INTRUSIVE_POINTER_PLUS_BIT_HPP

Added: trunk/boost/intrusive/pointer_plus_bits.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/intrusive/pointer_plus_bits.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,81 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007
+//
+// 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)
+//
+// See http://www.boost.org/libs/intrusive for documentation.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
+#define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
+
+#include <boost/intrusive/detail/mpl.hpp> //ls_zeros
+
+namespace boost {
+namespace intrusive {
+
+//!This trait class is used to know if a pointer
+//!can embed extra bits of information if
+//!it's going to be used to point to objects
+//!with an alignment of "Alignment" bytes.
+template<class VoidPointer, std::size_t Alignment>
+struct max_pointer_plus_bits
+{
+ static const std::size_t value = 0;
+};
+
+//!This is an specialization for raw pointers.
+//!Raw pointers can embed extra bits in the lower bits
+//!if the alignment is multiple of 2pow(NumBits).
+template<std::size_t Alignment>
+struct max_pointer_plus_bits<void*, Alignment>
+{
+ static const std::size_t value = detail::ls_zeros<Alignment>::value;
+};
+
+//!This is class that is supposed to have static methods
+//!to embed extra bits of information in a pointer.
+//!This is a declaration and there is no default implementation,
+//!because operations to embed the bits change with every pointer type.
+//!
+//!An implementation that detects that a pointer type whose
+//!has_pointer_plus_bits<>::value is non-zero can make use of these
+//!operations to embed the bits in the pointer.
+template<class Pointer, std::size_t NumBits>
+struct pointer_plus_bits;
+
+//!This is the specialization to embed extra bits of information
+//!in a raw pointer. The extra bits are stored in the lower bit of the pointer.
+template<class T, std::size_t NumBits>
+struct pointer_plus_bits<T*, NumBits>
+{
+ static const std::size_t Mask = ((std::size_t(1u) << NumBits) - 1);
+ typedef T* pointer;
+
+ static pointer get_pointer(pointer n)
+ { return pointer(std::size_t(n) & ~Mask); }
+
+ static void set_pointer(pointer &n, pointer p)
+ {
+ assert(0 == (std::size_t(p) & Mask));
+ n = pointer(std::size_t(p) | (std::size_t(n) & Mask));
+ }
+
+ static std::size_t get_bits(pointer n)
+ { return (std::size_t(n) & Mask); }
+
+ static void set_bits(pointer &n, std::size_t c)
+ {
+ assert(c <= Mask);
+ n = pointer(std::size_t(get_pointer(n)) | c);
+ }
+};
+
+} //namespace intrusive
+} //namespace boost
+
+#endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP

Modified: trunk/boost/intrusive/rbtree.hpp
==============================================================================
--- trunk/boost/intrusive/rbtree.hpp (original)
+++ trunk/boost/intrusive/rbtree.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -379,7 +379,7 @@
    //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
    //! of rbtree.
    //!
- //! <b>Effects</b>: Returns a const reference to the rbtree associated to the end iterator
+ //! <b>Effects</b>: Returns a const reference to the rbtree associated to the iterator
    //!
    //! <b>Throws</b>: Nothing.
    //!
@@ -387,6 +387,28 @@
    static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator)
    { return priv_container_from_end_iterator(end_iterator); }
 
+ //! <b>Precondition</b>: it must be a valid iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static rbtree_impl &container_from_iterator(iterator it)
+ { return priv_container_from_iterator(it); }
+
+ //! <b>Precondition</b>: it must be a valid end const_iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the end iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const rbtree_impl &container_from_iterator(const_iterator it)
+ { return priv_container_from_iterator(it); }
+
    //! <b>Effects</b>: Returns the value_compare object used by the tree.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1176,33 +1198,26 @@
    static void init_node(reference value)
    { node_algorithms::init(value_traits::to_node_ptr(value)); }
 
-/*
- //! <b>Effects</b>: removes x from a tree of the appropriate type. It has no effect,
- //! if x is not in such a tree.
+ //! <b>Effects</b>: removes "value" from the container.
    //!
    //! <b>Throws</b>: Nothing.
    //!
- //! <b>Complexity</b>: Constant time.
+ //! <b>Complexity</b>: Logarithmic time.
    //!
- //! <b>Note</b>: This static function is only usable with the "safe mode"
- //! hook and non-constant time size lists. Otherwise, the user must use
- //! the non-static "erase(reference )" member. If the user calls
- //! this function with a non "safe mode" or constant time size list
- //! a compilation error will be issued.
- template<class T>
- static void remove_node(T& value)
- {
- //This function is only usable for safe mode hooks and non-constant
- //time lists.
- //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size)));
+ //! <b>Note</b>: This static function is only usable with non-constant
+ //! time size containers that have stateless comparison functors.
+ //!
+ //! If the user calls
+ //! this function with a constant time size container or stateful comparison
+ //! functor a compilation error will be issued.
+ static void remove_node(reference value)
+ {
       BOOST_STATIC_ASSERT((!constant_time_size));
- BOOST_STATIC_ASSERT((boost::is_convertible<T, value_type>::value));
       node_ptr to_remove(value_traits::to_node_ptr(value));
- node_algorithms::unlink_and_rebalance(to_remove);
+ node_algorithms::unlink(to_remove);
       if(safemode_or_autounlink)
          node_algorithms::init(to_remove);
    }
-*/
 
    /// @cond
    private:
@@ -1233,6 +1248,9 @@
       rbtree_impl *rb = detail::parent_from_member<rbtree_impl, data_t>(d, &rbtree_impl::data_);
       return *rb;
    }
+
+ static rbtree_impl &priv_container_from_iterator(const const_iterator &it)
+ { return priv_container_from_end_iterator(it.end_iterator_from_it()); }
 };
 
 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
@@ -1426,6 +1444,12 @@
 
    static const rbtree &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const rbtree &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static rbtree &container_from_it(iterator it)
+ { return static_cast<rbtree &>(Base::container_from_iterator(it)); }
+
+ static const rbtree &container_from_it(const_iterator it)
+ { return static_cast<const rbtree &>(Base::container_from_iterator(it)); }
 };
 
 #endif

Modified: trunk/boost/intrusive/rbtree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/rbtree_algorithms.hpp (original)
+++ trunk/boost/intrusive/rbtree_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -54,7 +54,6 @@
 #include <boost/intrusive/intrusive_fwd.hpp>
 
 #include <boost/intrusive/detail/assert.hpp>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
 #include <boost/intrusive/detail/utilities.hpp>
 #include <boost/intrusive/detail/tree_algorithms.hpp>
 
@@ -695,6 +694,16 @@
       rebalance_after_insertion(header, new_value);
    }
 
+ //! <b>Requires</b>: "n" must be a node inserted in a tree.
+ //!
+ //! <b>Effects</b>: Returns a pointer to the header node of the tree.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ //!
+ //! <b>Throws</b>: Nothing.
+ static node_ptr get_header(node_ptr n)
+ { return tree_algorithms::get_header(n); }
+
    /// @cond
    private:
 

Modified: trunk/boost/intrusive/set.hpp
==============================================================================
--- trunk/boost/intrusive/set.hpp (original)
+++ trunk/boost/intrusive/set.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -226,7 +226,7 @@
    //! <b>Precondition</b>: end_iterator must be a valid end iterator
    //! of set.
    //!
- //! <b>Effects</b>: Returns a const reference to the set associated to the end iterator
+ //! <b>Effects</b>: Returns a reference to the set associated to the end iterator
    //!
    //! <b>Throws</b>: Nothing.
    //!
@@ -253,6 +253,34 @@
          , &set_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static set_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &set_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const set_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &set_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the set.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1086,6 +1114,12 @@
 
    static const set &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const set &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static set &container_from_iterator(iterator it)
+ { return static_cast<set &>(Base::container_from_iterator(it)); }
+
+ static const set &container_from_iterator(const_iterator it)
+ { return static_cast<const set &>(Base::container_from_iterator(it)); }
 };
 
 #endif
@@ -1318,6 +1352,34 @@
          , &multiset_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ static multiset_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &multiset_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ static const multiset_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &multiset_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the multiset.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1932,6 +1994,21 @@
    void replace_node(iterator replace_this, reference with_this)
    { tree_.replace_node(replace_this, with_this); }
 
+ //! <b>Effects</b>: removes "value" from the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic time.
+ //!
+ //! <b>Note</b>: This static function is only usable with non-constant
+ //! time size containers that have stateless comparison functors.
+ //!
+ //! If the user calls
+ //! this function with a constant time size container or stateful comparison
+ //! functor a compilation error will be issued.
+ static void remove_node(reference value)
+ { tree_type::remove_node(value); }
+
    /// @cond
    friend bool operator==(const multiset_impl &x, const multiset_impl &y)
    { return x.tree_ == y.tree_; }
@@ -2058,6 +2135,12 @@
 
    static const multiset &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const multiset &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static multiset &container_from_iterator(iterator it)
+ { return static_cast<multiset &>(Base::container_from_iterator(it)); }
+
+ static const multiset &container_from_iterator(const_iterator it)
+ { return static_cast<const multiset &>(Base::container_from_iterator(it)); }
 };
 
 #endif

Modified: trunk/boost/intrusive/sg_set.hpp
==============================================================================
--- trunk/boost/intrusive/sg_set.hpp (original)
+++ trunk/boost/intrusive/sg_set.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -252,6 +252,34 @@
          , &sg_set_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static sg_set_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<sg_set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &sg_set_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const sg_set_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<sg_set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &sg_set_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the sg_set.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1124,6 +1152,12 @@
 
    static const sg_set &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const sg_set &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static sg_set &container_from_iterator(iterator it)
+ { return static_cast<sg_set &>(Base::container_from_iterator(it)); }
+
+ static const sg_set &container_from_iterator(const_iterator it)
+ { return static_cast<const sg_set &>(Base::container_from_iterator(it)); }
 };
 
 #endif
@@ -1356,6 +1390,34 @@
          , &sg_multiset_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ static sg_multiset_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<sg_multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &sg_multiset_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ static const sg_multiset_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<sg_multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &sg_multiset_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the sg_multiset.
    //!
    //! <b>Complexity</b>: Constant.
@@ -2135,6 +2197,12 @@
 
    static const sg_multiset &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const sg_multiset &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static sg_multiset &container_from_iterator(iterator it)
+ { return static_cast<sg_multiset &>(Base::container_from_iterator(it)); }
+
+ static const sg_multiset &container_from_iterator(const_iterator it)
+ { return static_cast<const sg_multiset &>(Base::container_from_iterator(it)); }
 };
 
 #endif

Modified: trunk/boost/intrusive/sgtree.hpp
==============================================================================
--- trunk/boost/intrusive/sgtree.hpp (original)
+++ trunk/boost/intrusive/sgtree.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -527,6 +527,28 @@
    static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator)
    { return priv_container_from_end_iterator(end_iterator); }
 
+ //! <b>Precondition</b>: it must be a valid iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static sgtree_impl &container_from_iterator(iterator it)
+ { return priv_container_from_iterator(it); }
+
+ //! <b>Precondition</b>: it must be a valid end const_iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const sgtree_impl &container_from_iterator(const_iterator it)
+ { return priv_container_from_iterator(it); }
+
    //! <b>Effects</b>: Returns the value_compare object used by the tree.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1442,6 +1464,9 @@
       sgtree_impl *scapegoat = detail::parent_from_member<sgtree_impl, data_t>(d, &sgtree_impl::data_);
       return *scapegoat;
    }
+
+ static sgtree_impl &priv_container_from_iterator(const const_iterator &it)
+ { return priv_container_from_end_iterator(it.end_iterator_from_it()); }
 };
 
 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED

Modified: trunk/boost/intrusive/sgtree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/sgtree_algorithms.hpp (original)
+++ trunk/boost/intrusive/sgtree_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -22,7 +22,6 @@
 #include <cstddef>
 #include <boost/intrusive/intrusive_fwd.hpp>
 #include <boost/intrusive/detail/assert.hpp>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
 #include <boost/intrusive/detail/utilities.hpp>
 #include <boost/intrusive/detail/tree_algorithms.hpp>
 
@@ -640,6 +639,16 @@
    static node_ptr rebalance_subtree(node_ptr old_root)
    { return tree_algorithms::rebalance_subtree(old_root); }
 
+ //! <b>Requires</b>: "n" must be a node inserted in a tree.
+ //!
+ //! <b>Effects</b>: Returns a pointer to the header node of the tree.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ //!
+ //! <b>Throws</b>: Nothing.
+ static node_ptr get_header(node_ptr n)
+ { return tree_algorithms::get_header(n); }
+
    /// @cond
    private:
 

Modified: trunk/boost/intrusive/slist.hpp
==============================================================================
--- trunk/boost/intrusive/slist.hpp (original)
+++ trunk/boost/intrusive/slist.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -16,7 +16,6 @@
 
 #include <boost/intrusive/detail/config_begin.hpp>
 #include <boost/static_assert.hpp>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
 #include <boost/intrusive/detail/assert.hpp>
 #include <boost/intrusive/intrusive_fwd.hpp>
 #include <boost/intrusive/slist_hook.hpp>
@@ -25,6 +24,7 @@
 #include <boost/intrusive/detail/pointer_to_other.hpp>
 #include <boost/intrusive/link_mode.hpp>
 #include <boost/intrusive/options.hpp>
+#include <boost/intrusive/detail/utilities.hpp>
 #include <iterator>
 #include <functional>
 #include <algorithm>
@@ -183,10 +183,12 @@
    BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink)));
 
    node_ptr get_end_node()
- { return node_ptr(linear ? 0 : this->get_root_node()); }
+ { return node_ptr(linear ? node_ptr(0) : this->get_root_node()); }
 
    const_node_ptr get_end_node() const
- { return const_node_ptr(linear ? 0 : this->get_root_node()); }
+ {
+ return const_node_ptr
+ (linear ? const_node_ptr(0) : this->get_root_node()); }
 
    node_ptr get_root_node()
    { return node_ptr(&data_.root_plus_size_.root_); }
@@ -203,13 +205,10 @@
    void set_last_node(node_ptr n)
    { return this->set_last_node(n, detail::bool_<cache_last>()); }
 
- node_ptr get_last_node(detail::bool_<false>)
+ static node_ptr get_last_node(detail::bool_<false>)
    { return node_ptr(0); }
 
- const_node_ptr get_last_node(detail::bool_<false>) const
- { return const_node_ptr(0); }
-
- void set_last_node(node_ptr, detail::bool_<false>)
+ static void set_last_node(node_ptr, detail::bool_<false>)
    {}
 
    node_ptr get_last_node(detail::bool_<true>)
@@ -667,18 +666,14 @@
    void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer)
    {
       this->clear_and_dispose(disposer);
- BOOST_INTRUSIVE_TRY{
- iterator prev(this->before_begin());
- const_iterator b(src.begin()), e(src.end());
- for(; b != e; ++b){
- prev = this->insert_after(prev, *cloner(*b));
- }
+ detail::exception_disposer<slist_impl, Disposer>
+ rollback(*this, disposer);
+ iterator prev(this->before_begin());
+ const_iterator b(src.begin()), e(src.end());
+ for(; b != e; ++b){
+ prev = this->insert_after(prev, *cloner(*b));
       }
- BOOST_INTRUSIVE_CATCH(...){
- this->clear_and_dispose(disposer);
- BOOST_INTRUSIVE_RETHROW;
- }
- BOOST_INTRUSIVE_CATCH_END
+ rollback.release();
    }
 
    //! <b>Requires</b>: value must be an lvalue and prev_p must point to an element
@@ -849,13 +844,36 @@
       if(cache_last && (to_erase == this->get_last_node())){
          this->set_last_node(prev_n);
       }
- this->priv_size_traits().decrement();
       if(safemode_or_autounlink)
          node_algorithms::init(to_erase);
       disposer(get_real_value_traits().to_value_ptr(to_erase));
+ this->priv_size_traits().decrement();
+ return it;
+ }
+
+ /// @cond
+
+ template<class Disposer>
+ static iterator s_erase_after_and_dispose(iterator prev, Disposer disposer)
+ {
+ BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits)));
+ iterator it(prev);
+ ++it;
+ node_ptr to_erase(it.pointed_node());
+ ++it;
+ node_ptr prev_n(prev.pointed_node());
+ node_algorithms::unlink_after(prev_n);
+ if(safemode_or_autounlink)
+ node_algorithms::init(to_erase);
+ disposer(real_value_traits::to_value_ptr(to_erase));
       return it;
    }
 
+ static iterator s_erase_after(iterator prev)
+ { return s_erase_after_and_dispose(prev, detail::null_disposer()); }
+
+ /// @endcond
+
    //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
    //!
    //! <b>Effects</b>: Erases the range (before_first, last) from

Modified: trunk/boost/intrusive/splay_set.hpp
==============================================================================
--- trunk/boost/intrusive/splay_set.hpp (original)
+++ trunk/boost/intrusive/splay_set.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -252,6 +252,34 @@
          , &splay_set_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ static splay_set_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<splay_set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &splay_set_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of set.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the set associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const splay_set_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<splay_set_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &splay_set_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the splay_set.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1161,6 +1189,12 @@
 
    static const splay_set &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const splay_set &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static splay_set &container_from_iterator(iterator it)
+ { return static_cast<splay_set &>(Base::container_from_iterator(it)); }
+
+ static const splay_set &container_from_iterator(const_iterator it)
+ { return static_cast<const splay_set &>(Base::container_from_iterator(it)); }
 };
 
 #endif
@@ -1393,6 +1427,34 @@
          , &splay_multiset_impl::tree_);
    }
 
+ //! <b>Precondition</b>: it must be a valid iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static splay_multiset_impl &container_from_iterator(iterator it)
+ {
+ return *detail::parent_from_member<splay_multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &splay_multiset_impl::tree_);
+ }
+
+ //! <b>Precondition</b>: it must be a valid const_iterator of multiset.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the multiset associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ static const splay_multiset_impl &container_from_iterator(const_iterator it)
+ {
+ return *detail::parent_from_member<splay_multiset_impl, tree_type>
+ ( &tree_type::container_from_iterator(it)
+ , &splay_multiset_impl::tree_);
+ }
+
    //! <b>Effects</b>: Returns the key_compare object used by the splay_multiset.
    //!
    //! <b>Complexity</b>: Constant.
@@ -2209,6 +2271,12 @@
 
    static const splay_multiset &container_from_end_iterator(const_iterator end_iterator)
    { return static_cast<const splay_multiset &>(Base::container_from_end_iterator(end_iterator)); }
+
+ static splay_multiset &container_from_iterator(iterator it)
+ { return static_cast<splay_multiset &>(Base::container_from_iterator(it)); }
+
+ static const splay_multiset &container_from_iterator(const_iterator it)
+ { return static_cast<const splay_multiset &>(Base::container_from_iterator(it)); }
 };
 
 #endif

Modified: trunk/boost/intrusive/splaytree.hpp
==============================================================================
--- trunk/boost/intrusive/splaytree.hpp (original)
+++ trunk/boost/intrusive/splaytree.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -387,6 +387,28 @@
    static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator)
    { return priv_container_from_end_iterator(end_iterator); }
 
+ //! <b>Precondition</b>: it must be a valid iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static splaytree_impl &container_from_iterator(iterator it)
+ { return priv_container_from_iterator(it); }
+
+ //! <b>Precondition</b>: it must be a valid end const_iterator
+ //! of rbtree.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the tree associated to the iterator
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ static const splaytree_impl &container_from_iterator(const_iterator it)
+ { return priv_container_from_iterator(it); }
+
    //! <b>Effects</b>: Returns the value_compare object used by the tree.
    //!
    //! <b>Complexity</b>: Constant.
@@ -1312,6 +1334,9 @@
       splaytree_impl *rb = detail::parent_from_member<splaytree_impl, data_t>(d, &splaytree_impl::data_);
       return *rb;
    }
+
+ static splaytree_impl &priv_container_from_iterator(const const_iterator &it)
+ { return priv_container_from_end_iterator(it.end_iterator_from_it()); }
 };
 
 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED

Modified: trunk/boost/intrusive/splaytree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/splaytree_algorithms.hpp (original)
+++ trunk/boost/intrusive/splaytree_algorithms.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -50,13 +50,48 @@
 #include <boost/intrusive/detail/assert.hpp>
 #include <boost/intrusive/intrusive_fwd.hpp>
 #include <cstddef>
-#include <boost/intrusive/detail/no_exceptions_support.hpp>
 #include <boost/intrusive/detail/utilities.hpp>
 #include <boost/intrusive/detail/tree_algorithms.hpp>
 
 namespace boost {
 namespace intrusive {
 
+/// @cond
+namespace detail {
+
+template<class NodeTraits>
+struct splaydown_rollback
+{
+ typedef typename NodeTraits::node_ptr node_ptr;
+ splaydown_rollback( const node_ptr *pcur_subtree, node_ptr header
+ , node_ptr leftmost , node_ptr rightmost)
+ : pcur_subtree_(pcur_subtree) , header_(header)
+ , leftmost_(leftmost) , rightmost_(rightmost)
+ {}
+
+ void release()
+ { pcur_subtree_ = 0; }
+
+ ~splaydown_rollback()
+ {
+ if(pcur_subtree_){
+ //Exception can only be thrown by comp, but
+ //tree invariants still hold. *pcur_subtree is the current root
+ //so link it to the header.
+ NodeTraits::set_parent(*pcur_subtree_, header_);
+ NodeTraits::set_parent(header_, *pcur_subtree_);
+ //Recover leftmost/rightmost pointers
+ NodeTraits::set_left (header_, leftmost_);
+ NodeTraits::set_right(header_, rightmost_);
+ }
+ }
+ const node_ptr *pcur_subtree_;
+ node_ptr header_, leftmost_, rightmost_;
+};
+
+} //namespace detail {
+/// @endcond
+
 //! A splay tree is an implementation of a binary search tree. The tree is
 //! self balancing using the splay algorithm as described in
 //!
@@ -656,7 +691,8 @@
       node_ptr leftmost = NodeTraits::get_left(header);
       node_ptr rightmost = NodeTraits::get_right(header);
 
- try{
+ {
+ detail::splaydown_rollback<NodeTraits> rollback(&t, header, leftmost, rightmost);
          node_ptr null = header;
          node_ptr l = null;
          node_ptr r = null;
@@ -712,18 +748,9 @@
          }
 
          assemble(t, l, r, null);
+ rollback.release();
       }
- catch(...){
- //Exception can only be thrown by comp, but
- //tree invariants still hold. t is the current root
- //so link it to the header.
- NodeTraits::set_parent(t, header);
- NodeTraits::set_parent(header, t);
- //Recover leftmost/rightmost pointers
- NodeTraits::set_left (header, leftmost);
- NodeTraits::set_right(header, rightmost);
- throw;
- }
+
       //t is the current root
       NodeTraits::set_parent(header, t);
       NodeTraits::set_parent(t, header);
@@ -755,6 +782,17 @@
    static node_ptr rebalance_subtree(node_ptr old_root)
    { return tree_algorithms::rebalance_subtree(old_root); }
 
+
+ //! <b>Requires</b>: "n" must be a node inserted in a tree.
+ //!
+ //! <b>Effects</b>: Returns a pointer to the header node of the tree.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ //!
+ //! <b>Throws</b>: Nothing.
+ static node_ptr get_header(node_ptr n)
+ { return tree_algorithms::get_header(n); }
+
    private:
 
    /// @cond

Modified: trunk/boost/intrusive/unordered_set.hpp
==============================================================================
--- trunk/boost/intrusive/unordered_set.hpp (original)
+++ trunk/boost/intrusive/unordered_set.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -38,7 +38,8 @@
 //!
 //! The container supports the following options:
 //! \c base_hook<>/member_hook<>/value_traits<>,
-//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> .
+//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
+//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
 //!
 //! unordered_set only provides forward iterators but it provides 4 iterator types:
 //! iterator and const_iterator to navigate through the whole container and
@@ -167,8 +168,8 @@
 
    //! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_set.
    //!
- //! <b>Complexity</b>: Amortized constant time.
- //! Worst case (empty unordered_set): O(this->bucket_count())
+ //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
+ //! constant time with worst case (empty unordered_set) O(this->bucket_count())
    //!
    //! <b>Throws</b>: Nothing.
    iterator begin()
@@ -177,8 +178,8 @@
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //! of the unordered_set.
    //!
- //! <b>Complexity</b>: Amortized constant time.
- //! Worst case (empty unordered_set): O(this->bucket_count())
+ //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
+ //! constant time with worst case (empty unordered_set) O(this->bucket_count())
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator begin() const
@@ -187,8 +188,8 @@
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //! of the unordered_set.
    //!
- //! <b>Complexity</b>: Amortized constant time.
- //! Worst case (empty unordered_set): O(this->bucket_count())
+ //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
+ //! constant time with worst case (empty unordered_set) O(this->bucket_count())
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator cbegin() const
@@ -236,8 +237,8 @@
 
    //! <b>Effects</b>: Returns true is the container is empty.
    //!
- //! <b>Complexity</b>: if constant-time size option is disabled, average constant time
- //! (worst case, with empty() == true): O(this->bucket_count()).
+ //! <b>Complexity</b>: if constant-time size and cache_last options are disabled,
+ //! average constant time (worst case, with empty() == true: O(this->bucket_count()).
    //! Otherwise constant.
    //!
    //! <b>Throws</b>: Nothing.
@@ -959,7 +960,7 @@
 template<class T, class O1 = none, class O2 = none
                 , class O3 = none, class O4 = none
                 , class O5 = none, class O6 = none
- , class O7 = none
+ , class O7 = none, class O8 = none
>
 #endif
 struct make_unordered_set
@@ -967,19 +968,19 @@
    /// @cond
    typedef unordered_set_impl
       < typename make_hashtable_opt
- <T, O1, O2, O3, O4, O5, O6, O7>::type
+ <T, true, O1, O2, O3, O4, O5, O6, O7, O8>::type
> implementation_defined;
    /// @endcond
    typedef implementation_defined type;
 };
 
 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
-template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7>
+template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8>
 class unordered_set
- : public make_unordered_set<T, O1, O2, O3, O4, O5, O6, O7>::type
+ : public make_unordered_set<T, O1, O2, O3, O4, O5, O6, O7, O8>::type
 {
    typedef typename make_unordered_set
- <T, O1, O2, O3, O4, O5, O6, O7>::type Base;
+ <T, O1, O2, O3, O4, O5, O6, O7, O8>::type Base;
 
    //Assert if passed value traits are compatible with the type
    BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
@@ -1032,7 +1033,8 @@
 //!
 //! The container supports the following options:
 //! \c base_hook<>/member_hook<>/value_traits<>,
-//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> .
+//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
+//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
 //!
 //! unordered_multiset only provides forward iterators but it provides 4 iterator types:
 //! iterator and const_iterator to navigate through the whole container and
@@ -1161,8 +1163,8 @@
 
    //! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_multiset.
    //!
- //! <b>Complexity</b>: Amortized constant time.
- //! Worst case (empty unordered_multiset): O(this->bucket_count())
+ //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
+ //! constant time with worst case (empty unordered_set) O(this->bucket_count())
    //!
    //! <b>Throws</b>: Nothing.
    iterator begin()
@@ -1171,8 +1173,8 @@
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //! of the unordered_multiset.
    //!
- //! <b>Complexity</b>: Amortized constant time.
- //! Worst case (empty unordered_multiset): O(this->bucket_count())
+ //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
+ //! constant time with worst case (empty unordered_set) O(this->bucket_count())
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator begin() const
@@ -1181,8 +1183,8 @@
    //! <b>Effects</b>: Returns a const_iterator pointing to the beginning
    //! of the unordered_multiset.
    //!
- //! <b>Complexity</b>: Amortized constant time.
- //! Worst case (empty unordered_multiset): O(this->bucket_count())
+ //! <b>Complexity</b>: Constant time if `cache_begin<>` is true. Amortized
+ //! constant time with worst case (empty unordered_set) O(this->bucket_count())
    //!
    //! <b>Throws</b>: Nothing.
    const_iterator cbegin() const
@@ -1230,8 +1232,8 @@
 
    //! <b>Effects</b>: Returns true is the container is empty.
    //!
- //! <b>Complexity</b>: if constant-time size option is disabled, average constant time
- //! (worst case, with empty() == true): O(this->bucket_count()).
+ //! <b>Complexity</b>: if constant-time size and cache_last options are disabled,
+ //! average constant time (worst case, with empty() == true: O(this->bucket_count()).
    //! Otherwise constant.
    //!
    //! <b>Throws</b>: Nothing.
@@ -1891,7 +1893,7 @@
 template<class T, class O1 = none, class O2 = none
                 , class O3 = none, class O4 = none
                 , class O5 = none, class O6 = none
- , class O7 = none
+ , class O7 = none, class O8 = none
>
 #endif
 struct make_unordered_multiset
@@ -1899,19 +1901,19 @@
    /// @cond
    typedef unordered_multiset_impl
       < typename make_hashtable_opt
- <T, O1, O2, O3, O4, O5, O6, O7>::type
+ <T, false, O1, O2, O3, O4, O5, O6, O7, O8>::type
> implementation_defined;
    /// @endcond
    typedef implementation_defined type;
 };
 
 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
-template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7>
+template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8>
 class unordered_multiset
- : public make_unordered_multiset<T, O1, O2, O3, O4, O5, O6, O7>::type
+ : public make_unordered_multiset<T, O1, O2, O3, O4, O5, O6, O7, O8>::type
 {
    typedef typename make_unordered_multiset
- <T, O1, O2, O3, O4, O5, O6, O7>::type Base;
+ <T, O1, O2, O3, O4, O5, O6, O7, O8>::type Base;
    //Assert if passed value traits are compatible with the type
    BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
 

Modified: trunk/boost/intrusive/unordered_set_hook.hpp
==============================================================================
--- trunk/boost/intrusive/unordered_set_hook.hpp (original)
+++ trunk/boost/intrusive/unordered_set_hook.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -17,6 +17,7 @@
 #include <boost/intrusive/detail/config_begin.hpp>
 #include <boost/intrusive/intrusive_fwd.hpp>
 #include <boost/intrusive/detail/utilities.hpp>
+#include <boost/intrusive/detail/pointer_to_other.hpp>
 #include <boost/intrusive/slist_hook.hpp>
 #include <boost/intrusive/options.hpp>
 #include <boost/intrusive/detail/generic_hook.hpp>
@@ -26,35 +27,69 @@
 
 /// @cond
 
-template<class VoidPointer>
-struct slist_node_plus_hash
+template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
+struct unordered_node
+ : public slist_node<VoidPointer>
 {
    typedef typename boost::pointer_to_other
- <VoidPointer, slist_node_plus_hash>::type node_ptr;
- node_ptr next_;
+ < VoidPointer
+ , unordered_node<VoidPointer, StoreHash, OptimizeMultiKey>
+ >::type node_ptr;
+// node_ptr next_;
+ node_ptr prev_in_group_;
    std::size_t hash_;
 };
 
-// slist_node_traits can be used with circular_slist_algorithms and supplies
-// a slist_node holding the pointers needed for a singly-linked list
-// it is used by slist_base_hook and slist_member_hook
 template<class VoidPointer>
-struct slist_node_traits_plus_hash
+struct unordered_node<VoidPointer, false, true>
+ : public slist_node<VoidPointer>
+{
+ typedef typename boost::pointer_to_other
+ < VoidPointer
+ , unordered_node<VoidPointer, false, true>
+ >::type node_ptr;
+// node_ptr next_;
+ node_ptr prev_in_group_;
+};
+
+template<class VoidPointer>
+struct unordered_node<VoidPointer, true, false>
+ : public slist_node<VoidPointer>
 {
- typedef slist_node_plus_hash<VoidPointer> node;
+ typedef typename boost::pointer_to_other
+ < VoidPointer
+ , unordered_node<VoidPointer, true, false>
+ >::type node_ptr;
+// node_ptr next_;
+ std::size_t hash_;
+};
+
+template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
+struct unordered_node_traits
+ : public slist_node_traits<VoidPointer>
+{
+ typedef slist_node_traits<VoidPointer> reduced_slist_node_traits;
+ typedef unordered_node<VoidPointer, StoreHash, OptimizeMultiKey> node;
    typedef typename boost::pointer_to_other
       <VoidPointer, node>::type node_ptr;
    typedef typename boost::pointer_to_other
       <VoidPointer, const node>::type const_node_ptr;
 
- static const bool store_hash = true;
+ static const bool store_hash = StoreHash;
+ static const bool optimize_multikey = OptimizeMultiKey;
 
    static node_ptr get_next(const_node_ptr n)
- { return n->next_; }
+ { return node_ptr(&static_cast<node &>(*n->next_)); }
 
    static void set_next(node_ptr n, node_ptr next)
    { n->next_ = next; }
 
+ static node_ptr get_prev_in_group(const_node_ptr n)
+ { return n->prev_in_group_; }
+
+ static void set_prev_in_group(node_ptr n, node_ptr prev)
+ { n->prev_in_group_ = prev; }
+
    static std::size_t get_hash(const_node_ptr n)
    { return n->hash_; }
 
@@ -62,15 +97,68 @@
    { n->hash_ = h; }
 };
 
-template<class VoidPointer, bool StoreHash>
+template<class VoidPointer, class Node>
+struct unordered_group_node_traits
+{
+ typedef Node node;
+ typedef typename boost::pointer_to_other
+ <VoidPointer, node>::type node_ptr;
+ typedef typename boost::pointer_to_other
+ <VoidPointer, const node>::type const_node_ptr;
+
+ static node_ptr get_next(const_node_ptr n)
+ { return n->prev_in_group_; }
+
+ static void set_next(node_ptr n, node_ptr next)
+ { n->prev_in_group_ = next; }
+};
+
+template<class NodeTraits>
+struct unordered_algorithms
+ : public circular_slist_algorithms<NodeTraits>
+{
+ typedef circular_slist_algorithms<NodeTraits> base_type;
+ typedef unordered_group_node_traits
+ < typename boost::pointer_to_other
+ < typename NodeTraits::node_ptr
+ , void
+ >::type
+ , typename NodeTraits::node
+ > group_traits;
+ typedef circular_slist_algorithms<group_traits> group_algorithms;
+
+ static void init(typename base_type::node_ptr n)
+ {
+ base_type::init(n);
+ group_algorithms::init(n);
+ }
+
+ static void init_header(typename base_type::node_ptr n)
+ {
+ base_type::init_header(n);
+ group_algorithms::init_header(n);
+ }
+
+ static void unlink(typename base_type::node_ptr n)
+ {
+ base_type::unlink(n);
+ group_algorithms::unlink(n);
+ }
+};
+
+template<class VoidPointer, bool StoreHash, bool OptimizeMultiKey>
 struct get_uset_node_algo
 {
    typedef typename detail::if_c
- < StoreHash
- , slist_node_traits_plus_hash<VoidPointer>
+ < (StoreHash || OptimizeMultiKey)
+ , unordered_node_traits<VoidPointer, StoreHash, OptimizeMultiKey>
       , slist_node_traits<VoidPointer>
>::type node_traits_type;
- typedef circular_slist_algorithms<node_traits_type> type;
+ typedef typename detail::if_c
+ < OptimizeMultiKey
+ , unordered_algorithms<node_traits_type>
+ , circular_slist_algorithms<node_traits_type>
+ >::type type;
 };
 /// @endcond
 
@@ -90,6 +178,7 @@
    typedef detail::generic_hook
    < get_uset_node_algo<typename packed_options::void_pointer
                        , packed_options::store_hash
+ , packed_options::optimize_multikey
>
    , typename packed_options::tag
    , packed_options::link_mode
@@ -104,7 +193,7 @@
 //! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set.
 //!
 //! The hook admits the following options: \c tag<>, \c void_pointer<>,
-//! \c link_mode<> and \c store_hash<>.
+//! \c link_mode<>, \c store_hash<> and \c optimize_multikey<>.
 //!
 //! \c tag<> defines a tag to identify the node.
 //! The same tag value can be used in different classes, but if a class is
@@ -119,6 +208,10 @@
 //!
 //! \c store_hash<> will tell the hook to store the hash of the value
 //! to speed up rehashings.
+//!
+//! \c optimize_multikey<> will tell the hook to store a link to form a group
+//! with other value with the same value to speed up searches and insertions
+//! in unordered_multisets with a great number of with equivalent keys.
 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
 template<class ...Options>
 #else
@@ -211,6 +304,7 @@
    typedef detail::generic_hook
    < get_uset_node_algo< typename packed_options::void_pointer
                        , packed_options::store_hash
+ , packed_options::optimize_multikey
>
    , member_tag
    , packed_options::link_mode

Modified: trunk/libs/interprocess/doc/interprocess.qbk
==============================================================================
--- trunk/libs/interprocess/doc/interprocess.qbk (original)
+++ trunk/libs/interprocess/doc/interprocess.qbk 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -58,6 +58,15 @@
 not need any separate compilation so the user can define `BOOST_DATE_TIME_NO_LIB`
 to avoid Boost from trying to automatically link the [*Boost.DateTime].
 
+In POSIX systems, [*Boost.Interprocess] uses pthread system calls to implement
+classes like mutexes, condition variables, etc... In some operating systems,
+these POSIX calls are implemented in separate libraries that are not automatically
+linked by the compiler. For example, in some Linux systems POSIX pthread functions
+are implemented in `librt.a` library, so you might need to add that library
+when linking an executable or shared library that uses [*Boost.Interprocess].
+If you obtain linking errors related to those pthread functions, please revise
+your system's documentation to know which library implements them.
+
 [endsect]
 
 [section:tested_compilers Tested compilers]
@@ -551,6 +560,30 @@
 
 [endsect]
 
+[section:anonymous_shared_memory Anonymous shared memory for UNIX systems]
+
+Creating a shared memory segment and mapping it can be a bit tedious when several
+processes are involved. When processes are related via `fork()` operating system
+call in UNIX sytems a simpler method is available using anonymous shared memory.
+
+This feature has been implemented in UNIX systems mapping the device `\dev\zero` or
+just using the `MAP_ANONYMOUS` in a POSIX conformant `mmap` system call.
+
+This feature is wrapped in [*Boost.Interprocess] using the `anonymous_shared_memory()`
+function, which returns a `mapped_region` object holding an anonymous shared memory
+segment that can be shared by related processes.
+
+Here's is an example:
+
+[import ../example/doc_anonymous_shared_memory.cpp]
+[doc_anonymous_shared_memory]
+
+Once the segment is created, a `fork()` call can
+be used so that `region` is used to communicate two related processes.
+
+[endsect]
+
+
 [section:windows_shared_memory Native windows shared memory]
 
 Windows operating system also offers shared memory, but the lifetime of this
@@ -1298,7 +1331,7 @@
 [blurb ['[*void lock()]]]
 
 [*Effects:]
- The calling thread tries to obtain ownership of the mutex, and if another thread has ownership of the mutex, it waits until it can obtain the ownership. If a thread takes ownership of the mutex the mutex must be unlocked by the same mutex. If the mutex supports recursive locking, the mutex must be unlocked the same number of times it is locked.
+ The calling thread tries to obtain ownership of the mutex, and if another thread has ownership of the mutex, it waits until it can obtain the ownership. If a thread takes ownership of the mutex the mutex must be unlocked by the same thread. If the mutex supports recursive locking, the mutex must be unlocked the same number of times it is locked.
 
 [*Throws:] *interprocess_exception* on error.
 
@@ -4935,6 +4968,41 @@
 
 [endsect]
 
+[section:additional_containers Boost containers compatible with Boost.Interprocess]
+
+As mentioned, container developers might need to change their implementation to make them
+compatible with Boost.Interprocess, because implementation usually ignore allocators with
+smart pointers. Hopefully several Boost containers are compatible with [*Interprocess].
+
+[section:unordered Boost unordered containers]
+
+[*Boost.Unordered] containers are compatible with Interprocess, so programmers can store
+hash containers in shared memory and memory mapped files. Here's an small example storing
+`unordered_map` in shared memory:
+
+[import ../example/doc_unordered_map.cpp]
+[doc_unordered_map]
+
+[endsect]
+
+[section:multi_index Boost.MultiIndex containers]
+
+The widely used [*Boost.MultiIndex] library is compatible with [*Boost.Interprocess] so
+we can construct pretty good databases in shared memory. Constructing databases in shared
+memory is a bit tougher than in normal memory, usually because those databases contain strings
+and those strings need to be placed in shared memory. Shared memory strings require
+an allocator in their constructors so this usually makes object insertion a bit more
+complicated.
+
+Here's is an example that shows how to put a multi index container in shared memory:
+
+[import ../example/doc_multi_index.cpp]
+[doc_multi_index]
+
+[endsect]
+
+[endsect]
+
 [section:memory_algorithms Memory allocation algorithms]
 
 [section:simple_seq_fit simple_seq_fit: A simple shared memory management algorithm]
@@ -6262,7 +6330,7 @@
 For example, the index type `flat_map_index` based in `boost::interprocess::flat_map`
 is just defined as:
 
-[import ../../../boost/interprocess/indexes/flat_map_index.hpp]
+[import ../../boost/interprocess/indexes/flat_map_index.hpp]
 [flat_map_index]
 
 
@@ -6385,6 +6453,12 @@
 
 [section:release_notes Release Notes]
 
+[section:release_notes_boost_1_36_00 Boost 1.36 Release]
+
+* Added anonymous shared memory for UNIX systems.
+
+[endsect]
+
 [section:release_notes_boost_1_35_00 Boost 1.35 Release]
 
 * Added auxiliary utilities to ease the definition and construction of
@@ -6654,20 +6728,6 @@
 
 [endsect]
 
-[section:future_containers Unordered associative containers and other containers]
-
-We should be able to construct boost::unordered_xxx family in managed memory segments,
-so that there is no code duplication in boost. So [*Boost.Interprocess] should cooperate
-with boost container developers instead of duplicating effort writing it's own containers.
-
-A very interesting project is making [*boost::multi_index] compatible with
-[*Boost.Interprocess] ready for shared memory. This could be a good basis for memory
-mapped data-bases. The work to achieve this, however, can be huge. It would be
-interesting a collaboration with [*Intrusive] library to achieve shared memory
-intrusive containers.
-
-[endsect]
-
 [endsect]
 
 [endsect]

Added: trunk/libs/interprocess/example/doc_anonymous_shared_memory.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/example/doc_anonymous_shared_memory.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,36 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2007. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/interprocess/detail/config_begin.hpp>
+//[doc_anonymous_shared_memory
+#include <boost/interprocess/anonymous_shared_memory.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#include <iostream>
+#include <cstring>
+
+int main ()
+{
+ using namespace boost::interprocess;
+ try{
+ //Create an anonymous shared memory segment with size 1000
+ mapped_region region(anonymous_shared_memory(1000));
+
+ //Write all the memory to 1
+ std::memset(region.get_address(), 1, region.get_size());
+
+ //The segment is unmapped when "region" goes out of scope
+ }
+ catch(interprocess_exception &ex){
+ std::cout << ex.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+//]
+#include <boost/interprocess/detail/config_end.hpp>

Added: trunk/libs/interprocess/example/doc_multi_index.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/example/doc_multi_index.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,91 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2007. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+//[doc_multi_index
+#include <boost/interprocess/managed_shared_memory.hpp>
+#include <boost/interprocess/allocators/allocator.hpp>
+#include <boost/interprocess/containers/string.hpp>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+using namespace boost::interprocess;
+namespace bmi = boost::multi_index;
+
+typedef managed_shared_memory::allocator<char>::type char_allocator;
+typedef basic_string<char, std::char_traits<char>, char_allocator>shm_string;
+
+//Data to insert in shared memory
+struct employee
+{
+ int id;
+ int age;
+ shm_string name;
+ employee( int id_
+ , int age_
+ , const char *name_
+ , const char_allocator &a)
+ : id(id_), age(age_), name(name_, a)
+ {}
+};
+
+//Tags
+struct id{};
+struct age{};
+struct name{};
+
+// Define a multi_index_container of employees with following indices:
+// - a unique index sorted by employee::int,
+// - a non-unique index sorted by employee::name,
+// - a non-unique index sorted by employee::age.
+typedef bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ managed_shared_memory::allocator<employee>::type
+> employee_set;
+
+int main ()
+{
+ //Erase previous shared memory with the name
+ shared_memory_object::remove("MySharedMemory");
+
+ try{
+ //Create shared memory
+ managed_shared_memory segment(create_only,"MySharedMemory", 65536);
+
+ //Construct the multi_index in shared memory
+ employee_set *es = segment.construct<employee_set>
+ ("My MultiIndex Container") //Container's name in shared memory
+ ( employee_set::ctor_args_list()
+ , segment.get_allocator<employee>()); //Ctor parameters
+
+ //Now insert elements
+ char_allocator ca(segment.get_allocator<char>());
+ es->insert(employee(0,31, "Joe", ca));
+ es->insert(employee(1,27, "Robert", ca));
+ es->insert(employee(2,40, "John", ca));
+ }
+ catch(...){
+ shared_memory_object::remove("MySharedMemory");
+ throw;
+ }
+ shared_memory_object::remove("MySharedMemory");
+ return 0;
+}
+//]
+#include <boost/interprocess/detail/config_end.hpp>

Added: trunk/libs/interprocess/example/doc_unordered_map.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/example/doc_unordered_map.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,66 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2007. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+//[doc_unordered_map
+#include <boost/interprocess/managed_shared_memory.hpp>
+#include <boost/interprocess/allocators/allocator.hpp>
+
+#include <boost/unordered_map.hpp> //boost::unordered_map
+#include <functional> //std::equal_to
+#include <boost/functional/hash.hpp> //boost::hash
+
+int main ()
+{
+ using namespace boost::interprocess;
+ //Erase previous shared memory with the name
+ shared_memory_object::remove("MySharedMemory");
+
+ try{
+ //Create shared memory
+ managed_shared_memory segment(create_only ,"MySharedMemory" ,65536);
+
+ //Note that unordered_map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
+ //so the allocator must allocate that pair.
+ typedef int KeyType;
+ typedef float MappedType;
+ typedef std::pair<const int, float> ValueType;
+
+ //Typedef the allocator
+ typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;
+
+ //Alias an unordered_map of ints that uses the previous STL-like allocator.
+ typedef boost::unordered_map
+ < KeyType , MappedType
+ , boost::hash<KeyType> ,std::equal_to<KeyType>
+ , ShmemAllocator>
+ MyHashMap;
+
+ //Construct a shared memory hash map.
+ //Note that the first parameter is the initial bucket count and
+ //after that, the hash function, the equality function and the allocator
+ MyHashMap *myhashmap = segment.construct<MyHashMap>("MyHashMap") //object name
+ ( 3, boost::hash<int>(), std::equal_to<int>() //
+ , segment.get_allocator<ValueType>()); //allocator instance
+
+ //Insert data in the hash map
+ for(int i = 0; i < 100; ++i){
+ myhashmap->insert(ValueType(i, (float)i));
+ }
+ }
+ catch(...){
+ shared_memory_object::remove("MySharedMemory");
+ throw;
+ }
+ shared_memory_object::remove("MySharedMemory");
+ return 0;
+}
+//]
+#include <boost/interprocess/detail/config_end.hpp>

Added: trunk/libs/interprocess/proj/to-do.txt
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/to-do.txt 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,54 @@
+-> Implement zero_memory flag for allocation_command
+
+-> The general allocation funtion can be improved with some fixed size allocation bins.
+
+-> Adapt error reporting to TR1 system exceptions
+
+-> Improve exception messages
+
+-> Movability of containers should depend on the no-throw guarantee of allocators copy constructor
+
+-> Check self-assignment for vectors
+
+-> Update writing a new memory allocator explaining new functions (like alignment)
+
+-> private node allocators could take the number of nodes as a runtime parameter.
+
+-> Explain how to build intrusive indexes.
+
+-> Add intrusive index types as available indexes.
+
+-> Add maximum alignment allocation limit in PageSize bytes. Otherwise, we can't
+ guarantee alignment for process-shared allocations.
+
+-> Add default algorithm and index types. The user does not need to know how are
+ they implemented.
+
+-> Add private mapping to managed classes.
+
+-> Add unique_ptr documentation.
+
+-> Pass max size check in allocation to node pools
+
+-> Add atomic_func explanation in docs
+
+-> Once shrink to fit indexes is implemented test all memory has been deallocated
+ in tests to detect leaks/implementation failures.
+
+-> Improve allocate_many functions to allocate all the nodes forming a singly
+ linked list of nodes.
+
+-> Use in-place expansion capabilities to shrink_to_fit and reserve functions
+ from iunordered_index.
+
+-> Optimize copy_n with std::copy in vector. Revise other functions to improve optimizations
+
+-> Keep an eye on container iterator constness issue to bring Interprocess containers up-to-date.
+
+-> change unique_ptr to avoid using compressed_pair
+
+-> Improve unique_ptr test to test move assignment and other goodies like assigment from null
+
+-> barrier_test fails on MacOS X on PowerPC.
+
+-> void allocator instantiations fail.

Modified: trunk/libs/interprocess/proj/vc7ide/Interprocess.sln
==============================================================================
--- trunk/libs/interprocess/proj/vc7ide/Interprocess.sln (original)
+++ trunk/libs/interprocess/proj/vc7ide/Interprocess.sln 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -415,6 +415,34 @@
         ProjectSection(ProjectDependencies) = postProject
         EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_anonymous_shared_memory", "doc_anonymous_shared_memory.vcproj", "{6DE178C3-12FE-6032-4FC7-879B63B9F651}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "anonymous_shared_memory_test", "anonymous_shared_memory_test.vcproj", "{58DE8A13-4FA7-6252-36FE-B3A0A6D92812}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_unordered_map", "doc_unordered_map.vcproj", "{9C185DF3-B75F-1928-8F6D-735108AABE62}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_multi_index", "doc_multi_index.vcproj", "{918C5DF3-1928-B73F-F626-7358518CBE62}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unordered_test", "unordered_test.vcproj", "{C3CE1183-09F2-A46A-4FE6-D06BA7923A02}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multi_index_test", "multi_index_test.vcproj", "{9285DFD3-1928-F662-CB73-73518CB53A62}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file_lock_test", "file_lock_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792639}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
 Global
         GlobalSection(SolutionConfiguration) = preSolution
                 Debug = Debug
@@ -839,6 +867,34 @@
                 {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Debug.Build.0 = Debug|Win32
                 {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.ActiveCfg = Release|Win32
                 {5CE11C83-096A-84FE-4FA2-D3A6BA792002}.Release.Build.0 = Release|Win32
+ {6DE178C3-12FE-6032-4FC7-879B63B9F651}.Debug.ActiveCfg = Debug|Win32
+ {6DE178C3-12FE-6032-4FC7-879B63B9F651}.Debug.Build.0 = Debug|Win32
+ {6DE178C3-12FE-6032-4FC7-879B63B9F651}.Release.ActiveCfg = Release|Win32
+ {6DE178C3-12FE-6032-4FC7-879B63B9F651}.Release.Build.0 = Release|Win32
+ {58DE8A13-4FA7-6252-36FE-B3A0A6D92812}.Debug.ActiveCfg = Debug|Win32
+ {58DE8A13-4FA7-6252-36FE-B3A0A6D92812}.Debug.Build.0 = Debug|Win32
+ {58DE8A13-4FA7-6252-36FE-B3A0A6D92812}.Release.ActiveCfg = Release|Win32
+ {58DE8A13-4FA7-6252-36FE-B3A0A6D92812}.Release.Build.0 = Release|Win32
+ {9C185DF3-B75F-1928-8F6D-735108AABE62}.Debug.ActiveCfg = Debug|Win32
+ {9C185DF3-B75F-1928-8F6D-735108AABE62}.Debug.Build.0 = Debug|Win32
+ {9C185DF3-B75F-1928-8F6D-735108AABE62}.Release.ActiveCfg = Release|Win32
+ {9C185DF3-B75F-1928-8F6D-735108AABE62}.Release.Build.0 = Release|Win32
+ {918C5DF3-1928-B73F-F626-7358518CBE62}.Debug.ActiveCfg = Debug|Win32
+ {918C5DF3-1928-B73F-F626-7358518CBE62}.Debug.Build.0 = Debug|Win32
+ {918C5DF3-1928-B73F-F626-7358518CBE62}.Release.ActiveCfg = Release|Win32
+ {918C5DF3-1928-B73F-F626-7358518CBE62}.Release.Build.0 = Release|Win32
+ {C3CE1183-09F2-A46A-4FE6-D06BA7923A02}.Debug.ActiveCfg = Debug|Win32
+ {C3CE1183-09F2-A46A-4FE6-D06BA7923A02}.Debug.Build.0 = Debug|Win32
+ {C3CE1183-09F2-A46A-4FE6-D06BA7923A02}.Release.ActiveCfg = Release|Win32
+ {C3CE1183-09F2-A46A-4FE6-D06BA7923A02}.Release.Build.0 = Release|Win32
+ {9285DFD3-1928-F662-CB73-73518CB53A62}.Debug.ActiveCfg = Debug|Win32
+ {9285DFD3-1928-F662-CB73-73518CB53A62}.Debug.Build.0 = Debug|Win32
+ {9285DFD3-1928-F662-CB73-73518CB53A62}.Release.ActiveCfg = Release|Win32
+ {9285DFD3-1928-F662-CB73-73518CB53A62}.Release.Build.0 = Release|Win32
+ {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.ActiveCfg = Debug|Win32
+ {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.Build.0 = Debug|Win32
+ {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.ActiveCfg = Release|Win32
+ {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.Build.0 = Release|Win32
         EndGlobalSection
         GlobalSection(ExtensibilityGlobals) = postSolution
         EndGlobalSection

Added: trunk/libs/interprocess/proj/vc7ide/anonymous_shared_memory_test.vcproj
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/vc7ide/anonymous_shared_memory_test.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="anonymous_shared_memory_test"
+ ProjectGUID="{58DE8A13-4FA7-6252-36FE-B3A0A6D92812}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../Bin/Win32/Debug"
+ IntermediateDirectory="Debug/anonymous_shared_memory_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ GeneratePreprocessedFile="0"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/mapped_file_test_d.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/anonymous_shared_memory_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ FixedBaseAddress="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../Bin/Win32/Release"
+ IntermediateDirectory="Release/anonymous_shared_memory_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ RuntimeLibrary="2"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/anonymous_shared_memory_test.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{37F46E1-7A60-7AB5-3256-2B3A235E7E2F}">
+ <File
+ RelativePath="..\..\test\anonymous_shared_memory_test.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: trunk/libs/interprocess/proj/vc7ide/doc_anonymous_shared_memory.vcproj
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/vc7ide/doc_anonymous_shared_memory.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="doc_anonymous_shared_memory"
+ ProjectGUID="{6DE178C3-12FE-6032-4FC7-879B63B9F651}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../Bin/Win32/Debug"
+ IntermediateDirectory="Debug/doc_anonymous_shared_memory"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/doc_anonymous_shared_memory_d.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/doc_anonymous_shared_memory.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ FixedBaseAddress="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../Bin/Win32/Release"
+ IntermediateDirectory="Release/doc_anonymous_shared_memory"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ RuntimeLibrary="2"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/doc_anonymous_shared_memory.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4F7371DF-A5DA-6437-60A6-22A352A2D7FF}">
+ <File
+ RelativePath="..\..\example\doc_anonymous_shared_memory.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{95431998-8EB8-9BCA-44D0-ECD5A7BE2B52}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: trunk/libs/interprocess/proj/vc7ide/doc_multi_index.vcproj
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/vc7ide/doc_multi_index.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="doc_multi_index"
+ ProjectGUID="{918C5DF3-1928-B73F-F626-7358518CBE62}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../Bin/Win32/Debug"
+ IntermediateDirectory="Debug/doc_multi_index"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/doc_multi_index_d.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/doc_multi_index.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ FixedBaseAddress="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../Bin/Win32/Release"
+ IntermediateDirectory="Release/doc_multi_index"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ RuntimeLibrary="2"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/doc_multi_index.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{F37CE270-AB55-7439-5C26-1C5A5E3A21EA}">
+ <File
+ RelativePath="..\..\example\doc_multi_index.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: trunk/libs/interprocess/proj/vc7ide/doc_unordered_map.vcproj
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/vc7ide/doc_unordered_map.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="doc_unordered_map"
+ ProjectGUID="{9C185DF3-B75F-1928-8F6D-735108AABE62}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../Bin/Win32/Debug"
+ IntermediateDirectory="Debug/doc_unordered_map"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/doc_unordered_map_d.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/doc_unordered_map.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ FixedBaseAddress="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../Bin/Win32/Release"
+ IntermediateDirectory="Release/doc_unordered_map"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ RuntimeLibrary="2"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/doc_unordered_map.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4737FCC1-7AB5-7A06-4376-1C5A5E3A21EA}">
+ <File
+ RelativePath="..\..\example\doc_unordered_map.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: trunk/libs/interprocess/proj/vc7ide/file_lock_test.vcproj
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/vc7ide/file_lock_test.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="file_lock_test"
+ ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792639}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../Bin/Win32/Debug"
+ IntermediateDirectory="Debug/file_lock_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/file_lock_test_d.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/file_lock_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ FixedBaseAddress="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../Bin/Win32/Release"
+ IntermediateDirectory="Release/file_lock_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/file_lock_test.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{7FCFEF41-3746-C7A5-8B8E-A352A2F22D7F}">
+ <File
+ RelativePath="..\..\test\file_lock_test.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{95393980-8912-4b74-66A0-607BE52EB5FB}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Modified: trunk/libs/interprocess/proj/vc7ide/interprocesslib.vcproj
==============================================================================
--- trunk/libs/interprocess/proj/vc7ide/interprocesslib.vcproj (original)
+++ trunk/libs/interprocess/proj/vc7ide/interprocesslib.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -316,6 +316,9 @@
                         Filter="h;hpp;hxx;hm;inl;inc;xsd"
                         UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
                         <File
+ RelativePath="..\..\..\..\boost\interprocess\anonymous_shared_memory.hpp">
+ </File>
+ <File
                                 RelativePath="..\..\..\..\boost\interprocess\creation_tags.hpp">
                         </File>
                         <File

Added: trunk/libs/interprocess/proj/vc7ide/multi_index_test.vcproj
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/vc7ide/multi_index_test.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="multi_index_test"
+ ProjectGUID="{9285DFD3-1928-F662-CB73-73518CB53A62}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../Bin/Win32/Debug"
+ IntermediateDirectory="Debug/multi_index_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/multi_index_test_d.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/multi_index_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ FixedBaseAddress="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../Bin/Win32/Release"
+ IntermediateDirectory="Release/multi_index_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ RuntimeLibrary="2"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/multi_index_test.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{FE2726C0-356C-55BB-7439-12C5EB3E06AA}">
+ <File
+ RelativePath="..\..\test\multi_index_test.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: trunk/libs/interprocess/proj/vc7ide/unordered_test.vcproj
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/proj/vc7ide/unordered_test.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="unordered_test"
+ ProjectGUID="{C3CE1183-09F2-A46A-4FE6-D06BA7923A02}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../Bin/Win32/Debug"
+ IntermediateDirectory="Debug/unordered_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/unordered_test_d.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/unordered_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ FixedBaseAddress="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../Bin/Win32/Release"
+ IntermediateDirectory="Release/unordered_test"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
+ RuntimeLibrary="2"
+ TreatWChar_tAsBuiltInType="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib"
+ OutputFile="$(OutDir)/unordered_test.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="../../../../stage/lib"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{437BC07F-3132-A066-7AC5-32A2B22D75AF}">
+ <File
+ RelativePath="..\..\test\unordered_test.cpp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Modified: trunk/libs/interprocess/test/adaptive_node_pool_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/adaptive_node_pool_test.cpp (original)
+++ trunk/libs/interprocess/test/adaptive_node_pool_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -11,6 +11,8 @@
 #include "node_pool_test.hpp"
 #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
 
+#include <vector>
+
 int main ()
 {
    using namespace boost::interprocess;

Modified: trunk/libs/interprocess/test/adaptive_pool_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/adaptive_pool_test.cpp (original)
+++ trunk/libs/interprocess/test/adaptive_pool_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -41,7 +41,6 @@
 typedef vector<int, shmem_node_allocator_t> MyShmVector;
 typedef vector<int, shmem_node_allocator_v1_t> MyShmVectorV1;
 
-
 int main ()
 {
    if(test::list_test<managed_shared_memory, MyShmList, true>())

Modified: trunk/libs/interprocess/test/allocator_v1.hpp
==============================================================================
--- trunk/libs/interprocess/test/allocator_v1.hpp (original)
+++ trunk/libs/interprocess/test/allocator_v1.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -114,17 +114,17 @@
 
    //!Deallocates memory previously allocated. Never throws
    void deallocate(const pointer &ptr, size_type)
- { mp_mngr->deallocate(detail::get_pointer(ptr)); }
-/*
+ { mp_mngr->deallocate((void*)detail::get_pointer(ptr)); }
+
    //!Construct object, calling constructor.
    //!Throws if T(const T&) throws
    void construct(const pointer &ptr, const_reference value)
- { new(detail::get_pointer(ptr)) value_type(value); }
+ { new((void*)detail::get_pointer(ptr)) value_type(value); }
 
    //!Destroys object. Throws if object's destructor throws
    void destroy(const pointer &ptr)
    { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); }
-*/
+
    //!Returns the number of elements that could be allocated. Never throws
    size_type max_size() const
    { return mp_mngr->get_size(); }

Added: trunk/libs/interprocess/test/anonymous_shared_memory_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/test/anonymous_shared_memory_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,54 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2007. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <iostream>
+#include <boost/interprocess/mapped_region.hpp>
+#include <boost/interprocess/anonymous_shared_memory.hpp>
+#include <cstddef>
+#include <exception>
+
+using namespace boost::interprocess;
+
+int main ()
+{
+ try{
+ const std::size_t MemSize = 99999*2;
+ {
+ //Now check anonymous mapping
+ mapped_region region(anonymous_shared_memory(MemSize));
+
+ //Write pattern
+ unsigned char *pattern = static_cast<unsigned char*>(region.get_address());
+ for(std::size_t i = 0
+ ;i < MemSize
+ ;++i, ++pattern){
+ *pattern = static_cast<unsigned char>(i);
+ }
+
+ //Check pattern
+ pattern = static_cast<unsigned char*>(region.get_address());
+ for(std::size_t i = 0
+ ;i < MemSize
+ ;++i, ++pattern){
+ if(*pattern != static_cast<unsigned char>(i)){
+ return 1;
+ }
+ }
+ }
+ }
+ catch(std::exception &exc){
+ std::cout << "Unhandled exception: " << exc.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+
+#include <boost/interprocess/detail/config_end.hpp>

Modified: trunk/libs/interprocess/test/dummy_test_allocator.hpp
==============================================================================
--- trunk/libs/interprocess/test/dummy_test_allocator.hpp (original)
+++ trunk/libs/interprocess/test/dummy_test_allocator.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -82,26 +82,26 @@
    template<class T2>
    dummy_test_allocator(const dummy_test_allocator<T2> &)
    {}
-/*
+
    pointer address(reference value)
    { return pointer(addressof(value)); }
 
    const_pointer address(const_reference value) const
    { return const_pointer(addressof(value)); }
-*/
+
    pointer allocate(size_type, cvoid_ptr = 0)
    { return 0; }
 
    void deallocate(const pointer &, size_type)
    { }
-/*
+
    template<class Convertible>
    void construct(pointer, const Convertible &)
    {}
 
    void destroy(pointer)
    {}
-*/
+
    size_type max_size() const
    { return 0; }
 

Modified: trunk/libs/interprocess/test/expand_bwd_test_allocator.hpp
==============================================================================
--- trunk/libs/interprocess/test/expand_bwd_test_allocator.hpp (original)
+++ trunk/libs/interprocess/test/expand_bwd_test_allocator.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -85,26 +85,26 @@
    expand_bwd_test_allocator(const expand_bwd_test_allocator<T2> &other)
       : mp_buffer(other.mp_buffer), m_size(other.m_size)
       , m_offset(other.m_offset), m_allocations(0){ }
-/*
+
    pointer address(reference value)
    { return pointer(addressof(value)); }
 
    const_pointer address(const_reference value) const
    { return const_pointer(addressof(value)); }
-*/
+
    pointer allocate(size_type , cvoid_ptr hint = 0)
    { (void)hint; return 0; }
 
    void deallocate(const pointer &, size_type)
    {}
-/*
+
    template<class Convertible>
    void construct(pointer ptr, const Convertible &value)
    { new((void*)ptr) value_type(value); }
 
    void destroy(pointer ptr)
    { (*ptr).~value_type(); }
-*/
+
    size_type max_size() const
    { return m_size; }
 

Modified: trunk/libs/interprocess/test/expand_bwd_test_template.hpp
==============================================================================
--- trunk/libs/interprocess/test/expand_bwd_test_template.hpp (original)
+++ trunk/libs/interprocess/test/expand_bwd_test_template.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -15,6 +15,7 @@
 #include <vector>
 #include "expand_bwd_test_allocator.hpp"
 #include <algorithm>
+#include <boost/type_traits/remove_volatile.hpp>
 
 namespace boost { namespace interprocess { namespace test {
 
@@ -107,7 +108,8 @@
 bool test_insert_with_expand_bwd()
 {
    typedef typename VectorWithExpandBwdAllocator::value_type value_type;
- typedef std::vector<value_type> Vect;
+ typedef typename boost::remove_volatile<value_type>::type non_volatile_value_type;
+ typedef std::vector<non_volatile_value_type> Vect;
    const int MemorySize = 1000;
 
    //Distance old and new buffer
@@ -131,37 +133,42 @@
 
    for(int iteration = 0; iteration < Iterations; ++iteration)
    {
- Vect memory;
- memory.resize(MemorySize);
-
- Vect initial_data;
- initial_data.resize(InitialSize[iteration]);
- for(int i = 0; i < InitialSize[iteration]; ++i){
- initial_data[i] = value_type(i);
- }
-
- Vect data_to_insert;
- data_to_insert.resize(InsertSize[iteration]);
- for(int i = 0; i < InsertSize[iteration]; ++i){
- data_to_insert[i] = value_type(-i);
- }
-
- expand_bwd_test_allocator<value_type> alloc
- (&memory[0], memory.size(), Offset[iteration]);
- VectorWithExpandBwdAllocator vector(alloc);
- vector.insert( vector.begin()
- , initial_data.begin(), initial_data.end());
- vector.insert( vector.begin() + Position[iteration]
- , data_to_insert.begin(), data_to_insert.end());
- initial_data.insert(initial_data.begin() + Position[iteration]
- , data_to_insert.begin(), data_to_insert.end());
- //Now check that values are equal
- if(!CheckEqualVector(vector, initial_data)){
- std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
- << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
- << " Iteration: " << iteration << std::endl;
- return false;
+ value_type *memory = new value_type[MemorySize];
+ try {
+ std::vector<non_volatile_value_type> initial_data;
+ initial_data.resize(InitialSize[iteration]);
+ for(int i = 0; i < InitialSize[iteration]; ++i){
+ initial_data[i] = i;
+ }
+
+ Vect data_to_insert;
+ data_to_insert.resize(InsertSize[iteration]);
+ for(int i = 0; i < InsertSize[iteration]; ++i){
+ data_to_insert[i] = -i;
+ }
+
+ expand_bwd_test_allocator<value_type> alloc
+ ((value_type*)&memory[0], MemorySize, Offset[iteration]);
+ VectorWithExpandBwdAllocator vector(alloc);
+ vector.insert( vector.begin()
+ , initial_data.begin(), initial_data.end());
+ vector.insert( vector.begin() + Position[iteration]
+ , data_to_insert.begin(), data_to_insert.end());
+ initial_data.insert(initial_data.begin() + Position[iteration]
+ , data_to_insert.begin(), data_to_insert.end());
+ //Now check that values are equal
+ if(!CheckEqualVector(vector, initial_data)){
+ std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
+ << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
+ << " Iteration: " << iteration << std::endl;
+ return false;
+ }
+ }
+ catch(...){
+ delete []((non_volatile_value_type*)memory);
+ throw;
       }
+ delete []((non_volatile_value_type*)memory);
    }
 
    return true;
@@ -173,7 +180,8 @@
 bool test_assign_with_expand_bwd()
 {
    typedef typename VectorWithExpandBwdAllocator::value_type value_type;
- typedef std::vector<value_type> Vect;
+ typedef typename boost::remove_volatile<value_type>::type non_volatile_value_type;
+ typedef std::vector<non_volatile_value_type> Vect;
    const int MemorySize = 200;
 
    const int Offset[] = { 50, 50, 50};
@@ -183,41 +191,46 @@
 
    for(int iteration = 0; iteration <Iterations; ++iteration)
    {
- Vect memory;
- memory.resize(MemorySize);
-
- //Create initial data
- Vect initial_data;
- initial_data.resize(InitialSize[iteration]);
- for(int i = 0; i < InitialSize[iteration]; ++i){
- initial_data[i] = i;
- }
-
- //Create data to assign
- Vect data_to_assign;
- data_to_assign.resize(AssignSize[iteration]);
- for(int i = 0; i < AssignSize[iteration]; ++i){
- data_to_assign[i] = -i;
- }
-
- //Insert initial data to the vector to test
- expand_bwd_test_allocator<value_type> alloc
- (&memory[0], memory.size(), Offset[iteration]);
- VectorWithExpandBwdAllocator vector(alloc);
- vector.insert( vector.begin()
- , initial_data.begin(), initial_data.end());
-
- //Assign data
- vector.assign(data_to_assign.begin(), data_to_assign.end());
- initial_data.assign(data_to_assign.begin(), data_to_assign.end());
-
- //Now check that values are equal
- if(!CheckEqualVector(vector, initial_data)){
- std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
- << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
- << " Iteration: " << iteration << std::endl;
- return false;
+ value_type *memory = new value_type[MemorySize];
+ try {
+ //Create initial data
+ std::vector<non_volatile_value_type> initial_data;
+ initial_data.resize(InitialSize[iteration]);
+ for(int i = 0; i < InitialSize[iteration]; ++i){
+ initial_data[i] = i;
+ }
+
+ //Create data to assign
+ std::vector<non_volatile_value_type> data_to_assign;
+ data_to_assign.resize(AssignSize[iteration]);
+ for(int i = 0; i < AssignSize[iteration]; ++i){
+ data_to_assign[i] = -i;
+ }
+
+ //Insert initial data to the vector to test
+ expand_bwd_test_allocator<value_type> alloc
+ (&memory[0], MemorySize, Offset[iteration]);
+ VectorWithExpandBwdAllocator vector(alloc);
+ vector.insert( vector.begin()
+ , initial_data.begin(), initial_data.end());
+
+ //Assign data
+ vector.assign(data_to_assign.begin(), data_to_assign.end());
+ initial_data.assign(data_to_assign.begin(), data_to_assign.end());
+
+ //Now check that values are equal
+ if(!CheckEqualVector(vector, initial_data)){
+ std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
+ << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
+ << " Iteration: " << iteration << std::endl;
+ return false;
+ }
+ }
+ catch(...){
+ delete []((typename boost::remove_volatile<value_type>::type*)memory);
+ throw;
       }
+ delete []((typename boost::remove_volatile<value_type>::type*)memory);
    }
 
    return true;

Added: trunk/libs/interprocess/test/file_lock_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/test/file_lock_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,62 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2008. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/file_lock.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include "mutex_test_template.hpp"
+#include "sharable_mutex_test_template.hpp"
+#include "get_process_id_name.hpp"
+#include <fstream>
+#include <cstdio>
+
+using namespace boost::interprocess;
+//This wrapper is necessary to have a default constructor
+//in generic mutex_test_template functions
+class file_lock_lock_test_wrapper
+ : public boost::interprocess::file_lock
+{
+ public:
+ file_lock_lock_test_wrapper()
+ : boost::interprocess::file_lock(test::get_process_id_name())
+ {}
+};
+
+int main ()
+{
+ //Destroy and create file
+ {
+ std::remove(test::get_process_id_name());
+ std::ofstream file(test::get_process_id_name());
+ if(!file){
+ return 1;
+ }
+ file_lock flock(test::get_process_id_name());
+ {
+ scoped_lock<file_lock> sl(flock);
+ }
+ {
+ scoped_lock<file_lock> sl(flock, try_to_lock);
+ }
+ {
+ scoped_lock<file_lock> sl(flock, test::delay(1));
+ }
+ }
+
+ //test::test_all_lock<file_lock_lock_test_wrapper>();
+ //test::test_all_mutex<false, file_lock_lock_test_wrapper>();
+ //test::test_all_sharable_mutex<false, file_lock_lock_test_wrapper>();
+ std::remove(test::get_process_id_name());
+
+ return 0;
+}
+
+#include <boost/interprocess/detail/config_end.hpp>

Modified: trunk/libs/interprocess/test/list_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/list_test.cpp (original)
+++ trunk/libs/interprocess/test/list_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -26,6 +26,9 @@
 typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
 typedef list<int, ShmemAllocator> MyList;
 
+typedef allocator<volatile int, managed_shared_memory::segment_manager> ShmemVolatileAllocator;
+typedef list<volatile int, ShmemVolatileAllocator> MyVolatileList;
+
 typedef allocator<test::movable_int, managed_shared_memory::segment_manager> ShmemMoveAllocator;
 typedef list<test::movable_int, ShmemMoveAllocator> MyMoveList;
 
@@ -37,6 +40,9 @@
    if(test::list_test<managed_shared_memory, MyList, true>())
       return 1;
 
+ if(test::list_test<managed_shared_memory, MyVolatileList, true>())
+ return 1;
+
    if(test::list_test<managed_shared_memory, MyMoveList, true>())
       return 1;
 

Added: trunk/libs/interprocess/test/multi_index_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/test/multi_index_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,149 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2007. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/managed_shared_memory.hpp>
+#include <boost/interprocess/allocators/allocator.hpp>
+#include <boost/interprocess/allocators/adaptive_pool.hpp>
+#include <boost/interprocess/allocators/cached_adaptive_pool.hpp>
+#include <boost/interprocess/allocators/private_adaptive_pool.hpp>
+#include <boost/interprocess/allocators/node_allocator.hpp>
+#include <boost/interprocess/allocators/cached_node_allocator.hpp>
+#include <boost/interprocess/allocators/private_node_allocator.hpp>
+
+#include <boost/interprocess/containers/string.hpp>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+using namespace boost::interprocess;
+namespace bmi = boost::multi_index;
+
+typedef managed_shared_memory::allocator<char>::type char_allocator;
+typedef basic_string<char, std::char_traits<char>, char_allocator>shm_string;
+
+//Data to insert in shared memory
+struct employee
+{
+ int id;
+ int age;
+ shm_string name;
+ employee( int id_
+ , int age_
+ , const char *name_
+ , const char_allocator &a)
+ : id(id_), age(age_), name(name_, a)
+ {}
+};
+
+//Tags
+struct id{};
+struct age{};
+struct name{};
+
+// Explicit instantiations to catch compile-time errors
+template class bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ allocator<employee,managed_shared_memory::segment_manager>
+>;
+
+// Explicit instantiations to catch compile-time errors
+template class bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ adaptive_pool<employee,managed_shared_memory::segment_manager>
+>;
+/*
+// Explicit instantiations to catch compile-time errors
+template class bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ cached_adaptive_pool<employee,managed_shared_memory::segment_manager>
+>;
+
+// Explicit instantiations to catch compile-time errors
+template class bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ private_adaptive_pool<employee,managed_shared_memory::segment_manager>
+>;
+*/
+// Explicit instantiations to catch compile-time errors
+template class bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ node_allocator<employee,managed_shared_memory::segment_manager>
+>;
+/*
+// Explicit instantiations to catch compile-time errors
+template class bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ cached_node_allocator<employee,managed_shared_memory::segment_manager>
+>;
+
+// Explicit instantiations to catch compile-time errors
+template class bmi::multi_index_container<
+ employee,
+ bmi::indexed_by<
+ bmi::ordered_unique
+ <bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>,
+ bmi::ordered_non_unique<
+ bmi::tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>,
+ bmi::ordered_non_unique
+ <bmi::tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >,
+ private_node_allocator<employee,managed_shared_memory::segment_manager>
+>;
+*/
+int main ()
+{
+ return 0;
+}
+
+#include <boost/interprocess/detail/config_end.hpp>

Modified: trunk/libs/interprocess/test/shared_memory_mapping_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/shared_memory_mapping_test.cpp (original)
+++ trunk/libs/interprocess/test/shared_memory_mapping_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -13,6 +13,7 @@
 #include <iostream>
 #include <boost/interprocess/shared_memory_object.hpp>
 #include <boost/interprocess/mapped_region.hpp>
+#include <boost/interprocess/anonymous_shared_memory.hpp>
 #include <string>
 #include "get_process_id_name.hpp"
 
@@ -113,6 +114,28 @@
             }
          }
       }
+ {
+ //Now check anonymous mapping
+ mapped_region region(anonymous_shared_memory(FileSize));
+
+ //Write pattern
+ unsigned char *pattern = static_cast<unsigned char*>(region.get_address());
+ for(std::size_t i = 0
+ ;i < FileSize
+ ;++i, ++pattern){
+ *pattern = static_cast<unsigned char>(i);
+ }
+
+ //Check pattern
+ pattern = static_cast<unsigned char*>(region.get_address());
+ for(std::size_t i = 0
+ ;i < FileSize
+ ;++i, ++pattern){
+ if(*pattern != static_cast<unsigned char>(i)){
+ return 1;
+ }
+ }
+ }
    }
    catch(std::exception &exc){
       shared_memory_object::remove(test::get_process_id_name());

Modified: trunk/libs/interprocess/test/tree_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/tree_test.cpp (original)
+++ trunk/libs/interprocess/test/tree_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -61,7 +61,7 @@
 //Customize managed_shared_memory class
 typedef basic_managed_shared_memory
    <char,
- simple_seq_fit<mutex_family, void*>,
+ simple_seq_fit<mutex_family, offset_ptr<void> >,
     map_index
> my_managed_shared_memory;
 

Added: trunk/libs/interprocess/test/unordered_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/interprocess/test/unordered_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,94 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2008. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/managed_shared_memory.hpp>
+#include <boost/interprocess/allocators/allocator.hpp>
+#include "get_process_id_name.hpp"
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+
+#include <functional> //std::equal_to
+#include <boost/functional/hash.hpp> //boost::hash
+
+namespace bip = boost::interprocess;
+
+typedef bip::allocator<int, bip::managed_shared_memory::segment_manager> ShmemAllocator;
+typedef boost::unordered_set<int, boost::hash<int>, std::equal_to<int>, ShmemAllocator> MyUnorderedSet;
+typedef boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>, ShmemAllocator> MyUnorderedMultiSet;
+
+//Explicit instantiation to catch compile-time errors
+template class boost::unordered_set<int, boost::hash<int>, std::equal_to<int>, ShmemAllocator>;
+template class boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>, ShmemAllocator>;
+
+int main()
+{
+ //Remove any other old shared memory from the system
+ bip::shared_memory_object::remove(bip::test::get_process_id_name());
+ try {
+ bip::managed_shared_memory shm(bip::create_only, bip::test::get_process_id_name(), 65536);
+
+ //Elements to be inserted in unordered containers
+ const int elements[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ const int elements_size = sizeof(elements)/sizeof(elements[0]);
+
+ MyUnorderedSet *myset =
+ shm.construct<MyUnorderedSet>(bip::anonymous_instance)
+ ( elements_size
+ , MyUnorderedSet::hasher()
+ , MyUnorderedSet::key_equal()
+ , shm.get_allocator<int>());
+ MyUnorderedMultiSet *mymset =
+ shm.construct<MyUnorderedMultiSet>(bip::anonymous_instance)
+ ( elements_size
+ , MyUnorderedSet::hasher()
+ , MyUnorderedSet::key_equal()
+ , shm.get_allocator<int>());
+
+ //Insert elements and check sizes
+ myset->insert((&elements[0]), (&elements[elements_size]));
+ myset->insert((&elements[0]), (&elements[elements_size]));
+ mymset->insert((&elements[0]), (&elements[elements_size]));
+ mymset->insert((&elements[0]), (&elements[elements_size]));
+
+ if(myset->size() != (unsigned int)elements_size)
+ return 1;
+ if(mymset->size() != (unsigned int)elements_size*2)
+ return 1;
+
+ //Destroy elements and check sizes
+ myset->clear();
+ mymset->clear();
+
+ if(!myset->empty())
+ return 1;
+ if(!mymset->empty())
+ return 1;
+
+ //Destroy elements and check if memory has been deallocated
+ shm.destroy_ptr(myset);
+ shm.destroy_ptr(mymset);
+
+ shm.shrink_to_fit_indexes();
+ if(!shm.all_memory_deallocated())
+ return 1;
+
+ }
+ catch(...){
+ //Remove shared memory from the system
+ bip::shared_memory_object::remove(bip::test::get_process_id_name());
+ throw;
+ }
+ //Remove shared memory from the system
+ bip::shared_memory_object::remove(bip::test::get_process_id_name());
+ return 0;
+}
+
+#include <boost/interprocess/detail/config_end.hpp>

Modified: trunk/libs/interprocess/test/vector_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/vector_test.cpp (original)
+++ trunk/libs/interprocess/test/vector_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -44,7 +44,16 @@
 
    if(!test::test_all_expand_bwd<int_vector>())
       return 1;
+/*
+ //First raw volatile ints
+ typedef test::expand_bwd_test_allocator<volatile int>
+ volatile_int_allocator_type;
+ typedef vector<volatile int, volatile_int_allocator_type>
+ volatile_int_vector;
 
+ if(!test::test_all_expand_bwd<volatile_int_vector>())
+ return 1;
+*/
    //Now user defined wrapped int
    typedef test::expand_bwd_test_allocator<test::int_holder>
       int_holder_allocator_type;
@@ -72,6 +81,9 @@
    typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
    typedef vector<int, ShmemAllocator> MyVector;
 
+ //typedef allocator<volatile int, managed_shared_memory::segment_manager> ShmemVolatileAllocator;
+ //typedef vector<volatile int, ShmemVolatileAllocator> MyVolatileVector;
+
    typedef allocator<test::movable_int, managed_shared_memory::segment_manager> ShmemMoveAllocator;
    typedef vector<test::movable_int, ShmemMoveAllocator> MyMoveVector;
 
@@ -81,6 +93,9 @@
    if(test::vector_test<managed_shared_memory, MyVector>())
       return 1;
 
+ //if(test::vector_test<managed_shared_memory, MyVolatileVector>())
+ //return 1;
+
    if(test::vector_test<managed_shared_memory, MyMoveVector>())
       return 1;
 

Modified: trunk/libs/interprocess/test/windows_shared_memory_mapping_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/windows_shared_memory_mapping_test.cpp (original)
+++ trunk/libs/interprocess/test/windows_shared_memory_mapping_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -23,98 +23,93 @@
 
 int main ()
 {
- std::string process_name;
- test::get_process_id_name(process_name);
-
    try{
- const std::size_t FileSize = 99999*2;
- //Create shared memory and file mapping
- windows_shared_memory mapping(create_only, process_name.c_str(), read_write, FileSize);
-
+ const char *names[2] = { test::get_process_id_name(), 0 };
+ for(unsigned int i = 0; i < sizeof(names)/sizeof(names[0]); ++i)
       {
+ const std::size_t FileSize = 99999*2;
          //Create a file mapping
- windows_shared_memory mapping(open_only, process_name.c_str(), read_write);
+ windows_shared_memory mapping
+ (create_only, names[i], read_write, FileSize);
 
- //Create two mapped regions, one half of the file each
- mapped_region region (mapping
- ,read_write
- ,0
- ,FileSize/2
- ,0);
-
- mapped_region region2(mapping
- ,read_write
- ,FileSize/2
- ,FileSize - FileSize/2
- ,0);
-
- //Fill two regions with a pattern
- unsigned char *filler = static_cast<unsigned char*>(region.get_address());
- for(std::size_t i = 0
- ;i < FileSize/2
- ;++i){
- *filler++ = static_cast<unsigned char>(i);
- }
+ {
 
- filler = static_cast<unsigned char*>(region2.get_address());
- for(std::size_t i = FileSize/2
- ;i < FileSize
- ;++i){
- *filler++ = static_cast<unsigned char>(i);
- }
- }
+ //Create two mapped regions, one half of the file each
+ mapped_region region (mapping
+ ,read_write
+ ,0
+ ,FileSize/2
+ ,0);
+
+ mapped_region region2(mapping
+ ,read_write
+ ,FileSize/2
+ ,FileSize - FileSize/2
+ ,0);
+
+ //Fill two regions with a pattern
+ unsigned char *filler = static_cast<unsigned char*>(region.get_address());
+ for(std::size_t i = 0
+ ;i < FileSize/2
+ ;++i){
+ *filler++ = static_cast<unsigned char>(i);
+ }
 
- //See if the pattern is correct in the file using two mapped regions
- {
- //Create a file mapping
- windows_shared_memory mapping(open_only, process_name.c_str(), read_write);
- mapped_region region(mapping, read_write, 0, FileSize/2, 0);
- mapped_region region2(mapping, read_write, FileSize/2, 0/*FileSize - FileSize/2*/, 0);
-
- unsigned char *checker = (unsigned char*)region.get_address();
- //Check pattern
- for(std::size_t i = 0
- ;i < FileSize/2
- ;++i){
- if(*checker++ != static_cast<unsigned char>(i)){
- return 1;
+ filler = static_cast<unsigned char*>(region2.get_address());
+ for(std::size_t i = FileSize/2
+ ;i < FileSize
+ ;++i){
+ *filler++ = static_cast<unsigned char>(i);
             }
          }
 
- //Check second half
- checker = (unsigned char *)region2.get_address();
+ //See if the pattern is correct in the file using two mapped regions
+ {
+ mapped_region region (mapping, read_only, 0, FileSize/2, 0);
+ mapped_region region2(mapping, read_only, FileSize/2, FileSize - FileSize/2, 0);
+
+ unsigned char *checker = (unsigned char*)region.get_address();
+ //Check pattern
+ for(std::size_t i = 0
+ ;i < FileSize/2
+ ;++i){
+ if(*checker++ != static_cast<unsigned char>(i)){
+ return 1;
+ }
+ }
+
+ //Check second half
+ checker = (unsigned char *)region2.get_address();
 
- //Check pattern
- for(std::size_t i = FileSize/2
- ;i < FileSize
- ;++i){
- if(*checker++ != static_cast<unsigned char>(i)){
- return 1;
+ //Check pattern
+ for(std::size_t i = FileSize/2
+ ;i < FileSize
+ ;++i){
+ if(*checker++ != static_cast<unsigned char>(i)){
+ return 1;
+ }
             }
          }
- }
-
- //Now check the pattern mapping a single read only mapped_region
- {
- //Create a file mapping
- windows_shared_memory mapping(open_only, process_name.c_str(), read_only);
 
- //Create a single regions, mapping all the file
- mapped_region region (mapping
- ,read_only);
-
- //Check pattern
- unsigned char *pattern = static_cast<unsigned char*>(region.get_address());
- for(std::size_t i = 0
- ;i < FileSize
- ;++i, ++pattern){
- if(*pattern != static_cast<unsigned char>(i)){
- return 1;
+ //Now check the pattern mapping a single read only mapped_region
+ {
+ //Create a single regions, mapping all the file
+ mapped_region region (mapping, read_only);
+
+ //Check pattern
+ unsigned char *pattern = static_cast<unsigned char*>(region.get_address());
+ for(std::size_t i = 0
+ ;i < FileSize
+ ;++i, ++pattern){
+ if(*pattern != static_cast<unsigned char>(i)){
+ return 1;
+ }
             }
          }
       }
    }
    catch(std::exception &exc){
+ //shared_memory_object::remove(test::get_process_id_name());
       std::cout << "Unhandled exception: " << exc.what() << std::endl;
       return 1;
    }

Modified: trunk/libs/interprocess/test/windows_shared_memory_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/windows_shared_memory_test.cpp (original)
+++ trunk/libs/interprocess/test/windows_shared_memory_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -68,6 +68,7 @@
       std::cout << ex.what() << std::endl;
       return 1;
    }
+
    return 0;
 }
 

Modified: trunk/libs/intrusive/doc/intrusive.qbk
==============================================================================
--- trunk/libs/intrusive/doc/intrusive.qbk (original)
+++ trunk/libs/intrusive/doc/intrusive.qbk 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -528,7 +528,25 @@
    small for user classes (usually the size of two pointers). Many operations have
    constant time complexity.
 
-* [*set/multiset]: A `std::set/std::multiset` like intrusive associative containers.
+* [*set/multiset/rbtree]: A `std::set/std::multiset` like intrusive associative containers
+ based on red-black trees.
+ The size overhead is moderate for user classes (usually the size of three pointers).
+ Many operations have logarithmic time complexity.
+
+* [*avl_set/avl_multiset/avltree]: A `std::set/std::multiset` like intrusive associative
+ containers based on AVL trees.
+ The size overhead is moderate for user classes (usually the size of three pointers).
+ Many operations have logarithmic time complexity.
+
+* [*splay_set/splay_multiset/splaytree]: A `std::set/std::multiset` like intrusive associative
+ containers based on splay trees. Splay trees have no constant operations, but they
+ have some interesting caching properties.
+ The size overhead is moderate for user classes (usually the size of three pointers).
+ Many operations have logarithmic time complexity.
+
+* [*sg_set/sg_multiset/sgtree]: A `std::set/std::multiset` like intrusive associative
+ containers based on scapegoat trees. Scapegoat can be configured with the desired
+ balance factor to achieve the desised rebalancing frequency/search time compromise.
    The size overhead is moderate for user classes (usually the size of three pointers).
    Many operations have logarithmic time complexity.
 
@@ -539,7 +557,7 @@
    The size overhead is moderate for user classes (an average of two pointers per element).
    Many operations have an amortized constant time complexity.
 
-Each of these intrusive containers can be configured with constant or linear time
+Most of these intrusive containers can be configured with constant or linear time
 size:
 
 * [*Linear time size]: The intrusive container doesn't hold a size member that it's
@@ -753,7 +771,7 @@
 only provides forward iterators.
 
 For most cases, a doubly linked list is preferrable because it offers more
-constant-time functions with a slightly bigger overhead.
+constant-time functions with a slightly bigger size overhead.
 However, for some applications like
 constructing more elaborated containers, singly linked lists are essential
 because of their low size overhead.
@@ -784,7 +802,8 @@
    it [classref boost::intrusive::slist slist]-compatible.
 
 [classref boost::intrusive::slist_base_hook slist_base_hook] and
-[classref boost::intrusive::slist_member_hook slist_member_hook] receive the same options explained in
+[classref boost::intrusive::slist_member_hook slist_member_hook]
+receive the same options explained in
 the section [link intrusive.usage How to use Boost.Intrusive]:
 
 * [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
@@ -807,7 +826,7 @@
    template <class T, class ...Options>
    class slist;
 
-[classref boost::intrusive::slist slist] receives the same options explained in
+[classref boost::intrusive::slist slist] receives the options explained in
 the section [link intrusive.usage How to use Boost.Intrusive]:
 
 * [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
@@ -819,7 +838,23 @@
    Default: `constant_time_size<true>`
 
 * [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
- of the container. Default: `size_type<std::size_t>`
+ of the container. Default: `size_type<std::size_t>`.
+
+[classref boost::intrusive::slist slist] can receive additional options:
+
+* [*`linear<bool Enable>`]: the singly linked list is implemented as a
+ null-terminated list instead of a circular list. This allows `O(1)` swap,
+ but losses some operations like `container_from_end_iterator`.
+* [*`cache_last<bool Enable>`]: the singly linked also stores a pointer to the
+ last element of the singly linked list. This allows `O(1)` swap,
+ `splice_after(iterator, slist &)` and makes the list offer new functions
+ like `push_back(reference)` and `back()`. Logically, the size an empty list is
+ increased in `sizeof(void_pointer)` and the the cached last node pointer must
+ be updated in every operation, and that might incur in a slight performance impact.
+
+`auto_unlink` hooks are not usable if `linear<true>` and/or `cache_last<true>` options are
+used. If `auto_unlink` hooks are used and those options are specified, a static
+assertion will be raised.
 
 [endsect]
 
@@ -1151,6 +1186,11 @@
    rehashing is frequent or hashing the value is a slow operation.
    Default: `store_hash<false>`.
 
+* [*`optimize_multikey<bool Enabled>`]: This option reserves additional space in
+ the hook that will be used to group equal elements in unordered multisets,
+ improving significantly the performance when many equal values are inserted
+ in these containers. Default: `optimize_multikey<false>`.
+
 [endsect]
 
 [section:unordered_set_unordered_multiset_containers unordered_set and unordered_multiset containers]
@@ -1210,7 +1250,7 @@
 * [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
    of the container. Default: `size_type<std::size_t>`
 
-And they also can receive two additional options:
+And they also can receive additional options:
 
 * [*`equal<class Equal>`]: Equality function for the objects to be inserted
    in containers. Default: `equal< std::equal_to<T> >`
@@ -1228,7 +1268,14 @@
    modulo operations and for some applications modulo operations can impose
    a considerable overhead. In debug mode an assertion will be raised if the user
    provides a bucket length that is not power of two.
- Default: `constant_time_size<false>`.
+ Default: `power_2_buckets<false>`.
+
+* [*`cache_begin<bool Enabled>`]: Due to its internal structure, finding the first
+ element of an unordered container (`begin()` operation) is
+ amortized constant-time. It's possible to speed up `begin()` and other operations
+ related to it (like `clear()`) if the container caches internally the position
+ of the first element. This imposes the overhead of one pointer to the size
+ of the container. Default: `cache_begin<false>`.
 
 [endsect]
 
@@ -1301,13 +1348,13 @@
 balanced binary trees (such as red-black trees).
 
 The caching effect offered by splay trees comes with a cost: the tree must be
-rebalanced when a element is searched. This disallows const versions of search
+rebalanced when an element is searched. This disallows const versions of search
 functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`,
 `count()`...
 
 Because of this, splay-tree based associative containers are not drop-in
 replacements of [classref boost::intrusive::set set]/
-[classref boost::intrusive::splay_set splay_set].
+[classref boost::intrusive::multiset multiset].
 
 Apart from this, if element searches are randomized, the tree will be rebalanced
 without taking advantage of the cache effect, so splay trees can offer worse
@@ -1565,22 +1612,22 @@
 search tree.
 
 A binary search tree is said to be weight balanced if half the nodes are on the left
-of the root, and half on the right. An α-height-balanced tree is defined with defined
+of the root, and half on the right. An a-height-balanced tree is defined with defined
 with the following equation:
 
-[*['height(tree) <= log1/α(tree.size())]]
+[*['height(tree) <= log1/a(tree.size())]]
 
-* [*['α == 1]]: A tree forming a linked list is considered balanced.
-* [*['α == 0.5]]: Only a perfectly balanced binary is considered balanced.
+* [*['a == 1]]: A tree forming a linked list is considered balanced.
+* [*['a == 0.5]]: Only a perfectly balanced binary is considered balanced.
 
-Scapegoat trees are loosely ['α-height-balanced] so:
+Scapegoat trees are loosely ['a-height-balanced] so:
 
-[*['height(tree) <= log1/α(tree.size()) + 1]]
+[*['height(tree) <= log1/a(tree.size()) + 1]]
 
-Scapegoat trees support any α between 0.5 and 1. If α is higher, the tree is rebalanced
+Scapegoat trees support any a between 0.5 and 1. If a is higher, the tree is rebalanced
 less often, obtaining quicker insertions but slower searches. Lower
-α values improve search times. Scapegoat-trees implemented in [*Boost.Intrusive] offer the possibility of
-[*changing α at run-time] taking advantage of the flexibility of scapegoat trees.
+a values improve search times. Scapegoat-trees implemented in [*Boost.Intrusive] offer the possibility of
+[*changing a at run-time] taking advantage of the flexibility of scapegoat trees.
 For more information on scapegoat trees see [@http://en.wikipedia.org/wiki/Scapegoat_tree Wikipedia entry].
 
 Scapegoat trees also have downsides:
@@ -1591,7 +1638,7 @@
    tree is also considerably increased.
 
 * The operations needed to determine if the tree is unbalanced require floating-point
- operations like ['log1/α]. If the system has no floating point operations (like some
+ operations like ['log1/a]. If the system has no floating point operations (like some
    embedded systems), scapegoat tree operations might become slow.
 
 [*Boost.Intrusive] offers 3 containers based on scapegoat trees:
@@ -1689,9 +1736,9 @@
 
 * [*`floating_point<bool Enable>`]:
    When this option is deactivated, the scapegoat tree loses the ability to change
- the balance factor α at run-time, but the size of an empty container is reduced
+ the balance factor a at run-time, but the size of an empty container is reduced
    and no floating point operations are performed, normally increasing container
- performance. The fixed α factor that is used when this option is activated
+ performance. The fixed a factor that is used when this option is activated
    is ['1/sqrt(2) ~ 0,70711]. Default: `floating_point<true>`
 
 [endsect]
@@ -2523,6 +2570,63 @@
 
 [endsect]
 
+[/
+/
+/[section:sgtree_algorithms Intrusive sg tree algorithms]
+/
+/
+/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms] have the same
+/interface as [classref boost::intrusive::rbtree_algorithms rbtree_algorithms].
+/
+/[c++]
+/
+/ template<class NodeTraits>
+/ struct sgtree_algorithms;
+/
+/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms]
+/is configured with a NodeTraits class, which encapsulates
+/the information about the node to be manipulated. NodeTraits must support the
+/following interface:
+/
+/[*Typedefs]:
+/
+/* `node`: The type of the node that forms the circular sgtree
+/
+/* `node_ptr`: The type of a pointer to a node (usually node*)
+/
+/* `const_node_ptr`: The type of a pointer to a const node (usually const node*)
+/
+/[*Static functions]:
+/
+/* `static node_ptr get_parent(const_node_ptr n);`:
+/ Returns a pointer to the parent node stored in "n".
+/
+/* `static void set_parent(node_ptr n, node_ptr p);`:
+/ Sets the pointer to the parent node stored in "n" to "p".
+/
+/* `static node_ptr get_left(const_node_ptr n);`:
+/ Returns a pointer to the left node stored in "n".
+/
+/* `static void set_left(node_ptr n, node_ptr l);`:
+/ Sets the pointer to the left node stored in "n" to "l".
+/
+/* `static node_ptr get_right(const_node_ptr n);`:
+/ Returns a pointer to the right node stored in "n".
+/
+/* `static void set_right(node_ptr n, node_ptr r);`:
+/ Sets the pointer to the right node stored in "n" to "r".
+/
+/Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
+/with our nodes:
+/
+/[import ../example/doc_sgtree_algorithms.cpp]
+/[doc_sgtree_algorithms_code]
+/
+/For a complete list of functions see
+/[classref boost::intrusive::sgtree_algorithms sgtree_algorithms reference].
+/
+/[endsect]
+/]
 [endsect]
 
 [section:value_traits Containers with custom ValueTraits]
@@ -3104,7 +3208,7 @@
 These are the results:
 
 [table Reverse times for Visual C++ 7.1 / Windows XP
- [[Container] [Time in us/iteration (small object / big object)] [Normalized time (small object / big object) (small object / big object)]]
+ [[Container] [Time in us/iteration (small object / big object)] [Normalized time (small object / big object)]]
     [[`normal_link` intrusive list] [2656 / 10625] [1 / 1.83]]
     [[`safe_link` intrusive list] [2812 / 10937] [1.05 / 1.89]]
     [[`auto_unlink` intrusive list] [2710 / 10781] [1.02 / 1.86]]
@@ -3310,18 +3414,18 @@
 
 [endsect]
 
-[section:disabling_exceptions Disabling exceptions support]
+[section:release_notes Release Notes]
+
+[section:release_notes_boost_1_36_00 Boost 1.36 Release]
 
-[*Boost.Intrusive] might be useful in environments where exceptions are not available
-or recommendable (like embedded or real-time systems). [*Boost.Intrusive] uses the
-global Boost mechanism to disable exception handling, so that if the compiler
-configuration disables exceptions, `BOOST_NO_EXCEPTIONS` is defined and exception
-handling is disabled.
-
-This mechanism is a global mechanism to disable exceptions. If for any reason,
-the user wants to disable exception handling [*only] in [*Boost.Intrusive],
-`BOOST_INTRUSIVE_DISABLE_EXCEPTION_HANDLING` can be defined to disable
-exception handling in the library.
+* Added `linear<>` and `cache_last<>` options to singly linked lists.
+* Added `optimize_multikey<>` option to unordered container hooks.
+* Optimized unordered containers when `store_hash` option is used in the hook.
+* Implementation changed to be exception agnostic so that it can be used
+ in environments without exceptions.
+* Added `container_from_iterator` function to tree-based containers.
+
+[endsect]
 
 [endsect]
 
@@ -3331,13 +3435,13 @@
 
 * Visual 7.1/WinXP
 * Visual 8.0/WinXP
+* Visual 9.0/WinXP
 * GCC 4.1.1/MinGW
 * GCC 3.4.4/Cygwin
 * Intel 9.1/WinXP
 * GCC 4.1.2/Linux
 * GCC 3.4.3/Solaris 11
 * GCC 4.0/Mac Os 10.4.1
-* SunCC 5.8/Solaris 11
 
 [endsect]
 

Modified: trunk/libs/intrusive/index.html
==============================================================================
--- trunk/libs/intrusive/index.html (original)
+++ trunk/libs/intrusive/index.html 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -4,6 +4,6 @@
 </head>
 <body>
 Automatic redirection failed, please go to
-../../doc/html/intrusive.html
+../../doc/html/intrusive
 </body>
 </html>

Modified: trunk/libs/intrusive/perf/perf_list.cpp
==============================================================================
--- trunk/libs/intrusive/perf/perf_list.cpp (original)
+++ trunk/libs/intrusive/perf/perf_list.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -23,7 +23,7 @@
 //[perf_list_value_type
 //Iteration and element count defines
 const int NumIter = 100;
-const int NumElements = 100000;
+const int NumElements = 50000;
 
 using namespace boost::intrusive;
 

Modified: trunk/libs/intrusive/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj
==============================================================================
--- trunk/libs/intrusive/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj (original)
+++ trunk/libs/intrusive/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -154,10 +154,7 @@
                                 RelativePath="..\..\..\..\..\boost\intrusive\options.hpp">
                         </File>
                         <File
- RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_2_bits.hpp">
- </File>
- <File
- RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bit.hpp">
+ RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bits.hpp">
                         </File>
                         <File
                                 RelativePath="..\..\..\..\..\boost\intrusive\rbtree.hpp">
@@ -241,9 +238,6 @@
                                         RelativePath="..\..\..\..\..\boost\intrusive\detail\mpl.hpp">
                                 </File>
                                 <File
- RelativePath="..\..\..\..\..\boost\intrusive\detail\no_exceptions_support.hpp">
- </File>
- <File
                                         RelativePath="..\..\..\..\..\boost\intrusive\detail\parent_from_member.hpp">
                                 </File>
                                 <File

Added: trunk/libs/intrusive/proj/vc7ide/to-do.txt
==============================================================================
--- (empty file)
+++ trunk/libs/intrusive/proj/vc7ide/to-do.txt 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -0,0 +1,11 @@
+Add resize() to list
+Implement incremental hashing
+Add invariants to slist and test them after every operation
+Create a generic hook that will work with all containers
+Take advantage of store_hash in lookups: Instead of comparing objects, just
+ compare hashes. This will improve equality for expensive objects.
+
+Improve the use of cache_begin to unordered containers:
+-> Speed up rehash
+
+

Modified: trunk/libs/intrusive/test/avl_set_test.cpp
==============================================================================
--- trunk/libs/intrusive/test/avl_set_test.cpp (original)
+++ trunk/libs/intrusive/test/avl_set_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -108,7 +108,6 @@
 
 int main( int, char* [] )
 {
-
    test_main_template<void*, false>()();
    test_main_template<boost::intrusive::smart_ptr<void>, false>()();
    test_main_template<void*, true>()();

Modified: trunk/libs/intrusive/test/generic_assoc_test.hpp
==============================================================================
--- trunk/libs/intrusive/test/generic_assoc_test.hpp (original)
+++ trunk/libs/intrusive/test/generic_assoc_test.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -52,9 +52,38 @@
    static void test_rebalance(std::vector<value_type>& values);
    static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::true_type);
    static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::false_type);
+ static void test_container_from_iterator(std::vector<value_type>& values);
 };
 
 template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
+void test_generic_assoc<ValueTraits, ContainerDefiner>::
+ test_container_from_iterator(std::vector<value_type>& values)
+{
+ typedef typename ContainerDefiner
+ < value_type
+ , value_traits<ValueTraits>
+ , constant_time_size<value_type::constant_time_size>
+ >::type assoc_type;
+
+ assoc_type testset(values.begin(), values.end());
+ typedef typename assoc_type::iterator it_type;
+ typedef typename assoc_type::const_iterator cit_type;
+ typedef typename assoc_type::size_type sz_type;
+ sz_type sz = testset.size();
+ for(it_type b(testset.begin()), e(testset.end()); b != e; ++b)
+ {
+ assoc_type &s = assoc_type::container_from_iterator(b);
+ const assoc_type &cs = assoc_type::container_from_iterator(cit_type(b));
+ BOOST_TEST(&s == &cs);
+ BOOST_TEST(&s == &testset);
+ s.erase(b);
+ BOOST_TEST(testset.size() == (sz-1));
+ s.insert(*b);
+ BOOST_TEST(testset.size() == sz);
+ }
+}
+
+template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
 void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst()
 {
    typedef typename ValueTraits::value_type value_type;
@@ -103,12 +132,14 @@
 template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
 void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(std::vector<typename ValueTraits::value_type>& values)
 {
+ typedef typename ValueTraits::value_type value_type;
    test_clone(values);
    test_container_from_end(values);
    test_splay_up(values);
    test_splay_down(values);
    test_rebalance(values);
    test_insert_erase_burst();
+ test_container_from_iterator(values);
 }
 
 template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>

Modified: trunk/libs/intrusive/test/generic_set_test.hpp
==============================================================================
--- trunk/libs/intrusive/test/generic_set_test.hpp (original)
+++ trunk/libs/intrusive/test/generic_set_test.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -35,6 +35,7 @@
    static void test_impl();
 };
 
+
 template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
 void test_generic_set<ValueTraits, ContainerDefiner>::test_all()
 {

Modified: trunk/libs/intrusive/test/itestvalue.hpp
==============================================================================
--- trunk/libs/intrusive/test/itestvalue.hpp (original)
+++ trunk/libs/intrusive/test/itestvalue.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -126,20 +126,30 @@
 struct uset_auto_base_hook_type
 {
    typedef unordered_set_base_hook
- < link_mode<auto_unlink>, void_pointer<VoidPointer>
- , tag<my_tag>, store_hash<true> > type;
+ < link_mode<auto_unlink>
+ , void_pointer<VoidPointer>
+ , tag<my_tag>
+ , store_hash<true>
+ > type;
 };
 
 template<class VoidPointer>
 struct uset_member_hook_type
-{ typedef unordered_set_member_hook<void_pointer<VoidPointer> > type; };
+{
+ typedef unordered_set_member_hook
+ < void_pointer<VoidPointer>
+ , optimize_multikey<true>
+ > type;
+};
 
 template<class VoidPointer>
 struct uset_auto_member_hook_type
 {
    typedef unordered_set_member_hook
       < link_mode<auto_unlink>, void_pointer<VoidPointer>
- , store_hash<true> > type;
+ , store_hash<true>
+ , optimize_multikey<true>
+ > type;
 };
 
 template<class VoidPointer, bool ConstantTimeSize>
@@ -318,6 +328,49 @@
       slist_auto_node_.swap_nodes(other.slist_auto_node_);
    }
 
+ bool is_linked() const
+ {
+ //Set
+ return set_base_hook_t::is_linked() ||
+ set_auto_base_hook_t::is_linked() ||
+ set_node_.is_linked() ||
+ set_auto_node_.is_linked() ||
+
+ //SplaySet
+ splay_set_base_hook_t::is_linked() ||
+ splay_set_auto_base_hook_t::is_linked() ||
+ splay_set_node_.is_linked() ||
+ splay_set_auto_node_.is_linked() ||
+
+ //ScapeoatSet
+ bs_set_base_hook_t::is_linked() ||
+ sg_set_node_.is_linked() ||
+
+ //AvlSet
+ avl_set_base_hook_t::is_linked() ||
+ avl_set_auto_base_hook_t::is_linked() ||
+ avl_set_node_.is_linked() ||
+ avl_set_auto_node_.is_linked() ||
+
+ //Unordered set
+ unordered_set_base_hook_t::is_linked() ||
+ unordered_set_auto_base_hook_t::is_linked() ||
+ unordered_set_node_.is_linked() ||
+ unordered_set_auto_node_.is_linked() ||
+
+ //List
+ list_base_hook_t::is_linked() ||
+ list_auto_base_hook_t::is_linked() ||
+ list_node_.is_linked() ||
+ list_auto_node_.is_linked() ||
+
+ //Slist
+ slist_base_hook_t::is_linked() ||
+ slist_auto_base_hook_t::is_linked() ||
+ slist_node_.is_linked() ||
+ slist_auto_node_.is_linked();
+ }
+
    ~testvalue()
    {}
 

Modified: trunk/libs/intrusive/test/smart_ptr.hpp
==============================================================================
--- trunk/libs/intrusive/test/smart_ptr.hpp (original)
+++ trunk/libs/intrusive/test/smart_ptr.hpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -12,8 +12,7 @@
 #define BOOST_INTRUSIVE_SMART_PTR_HPP
 
 #include <boost/iterator.hpp>
-#include <boost/intrusive/pointer_plus_bit.hpp>
-#include <boost/intrusive/pointer_plus_2_bits.hpp>
+#include <boost/intrusive/pointer_plus_bits.hpp>
 
 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
 # pragma once
@@ -109,7 +108,7 @@
    public: //Public Functions
 
    //!Constructor from raw pointer (allows "0" pointer conversion). Never throws.
- smart_ptr(pointer ptr = 0)
+ explicit smart_ptr(pointer ptr = 0)
       : m_ptr(ptr)
    {}
 
@@ -351,67 +350,34 @@
 //for intrusive containers, saving space
 namespace intrusive {
 
-template<std::size_t N>
-struct has_pointer_plus_bit<smart_ptr<void>, N>
+template<std::size_t Alignment>
+struct max_pointer_plus_bits<smart_ptr<void>, Alignment>
 {
- static const bool value = has_pointer_plus_bit<void*, N>::value;
+ static const std::size_t value = max_pointer_plus_bits<void*, Alignment>::value;
 };
 
-//Specialization
-template<class T>
-struct pointer_plus_bit<smart_ptr<T> >
-{
- typedef smart_ptr<T> pointer;
-
- static pointer get_pointer(const pointer &n)
- { return pointer_plus_bit<T*>::get_pointer(n.get()); }
-
- static void set_pointer(pointer &n, pointer p)
- {
- T *raw_n = n.get();
- pointer_plus_bit<T*>::set_pointer(raw_n, p.get());
- n = raw_n;
- }
-
- static bool get_bit(const pointer &n)
- { return pointer_plus_bit<T*>::get_bit(n.get()); }
-
- static void set_bit(pointer &n, bool c)
- {
- T *raw_n = n.get();
- pointer_plus_bit<T*>::set_bit(raw_n, c);
- n = raw_n;
- }
-};
-
-template<std::size_t N>
-struct has_pointer_plus_2_bits<smart_ptr<void>, N>
-{
- static const bool value = has_pointer_plus_2_bits<void*, N>::value;
-};
-
-template<class T>
-struct pointer_plus_2_bits<smart_ptr<T> >
+template<class T, std::size_t NumBits>
+struct pointer_plus_bits<smart_ptr<T>, NumBits>
 {
    typedef smart_ptr<T> pointer;
 
    static pointer get_pointer(const pointer &n)
- { return pointer_plus_2_bits<T*>::get_pointer(n.get()); }
+ { return pointer_plus_bits<T*, NumBits>::get_pointer(n.get()); }
 
    static void set_pointer(pointer &n, pointer p)
    {
       T *raw_n = n.get();
- pointer_plus_2_bits<T*>::set_pointer(raw_n, p.get());
+ pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.get());
       n = raw_n;
    }
 
    static std::size_t get_bits(const pointer &n)
- { return pointer_plus_2_bits<T*>::get_bits(n.get()); }
+ { return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); }
 
    static void set_bits(pointer &n, std::size_t c)
    {
       T *raw_n = n.get();
- pointer_plus_2_bits<T*>::set_bits(raw_n, c);
+ pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c);
       n = raw_n;
    }
 };

Modified: trunk/libs/intrusive/test/unordered_multiset_test.cpp
==============================================================================
--- trunk/libs/intrusive/test/unordered_multiset_test.cpp (original)
+++ trunk/libs/intrusive/test/unordered_multiset_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -18,6 +18,7 @@
 #include "smart_ptr.hpp"
 #include "common_functors.hpp"
 #include <vector>
+#include <algorithm> //std::sort std::find
 #include <set>
 #include <boost/detail/lightweight_test.hpp>
 #include "test_macros.hpp"
@@ -27,7 +28,7 @@
 
 static const std::size_t BucketSize = 11;
 
-template<class ValueTraits>
+template<class ValueTraits, bool CacheBegin>
 struct test_unordered_multiset
 {
    typedef typename ValueTraits::value_type value_type;
@@ -41,14 +42,15 @@
    static void test_clone(std::vector<value_type>& values);
 };
 
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>::test_all (std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_multiset
- <value_type
+ < value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    {
       typedef typename unordered_multiset_type::bucket_traits bucket_traits;
@@ -76,14 +78,15 @@
 }
 
 //test case due to an error in tree implementation:
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>::test_impl()
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>::test_impl()
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_multiset
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    typedef typename unordered_multiset_type::bucket_traits bucket_traits;
 
@@ -106,14 +109,15 @@
 }
 
 //test: constructor, iterator, clear, reverse_iterator, front, back, size:
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>::test_sort(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_multiset
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    typedef typename unordered_multiset_type::bucket_traits bucket_traits;
 
@@ -127,104 +131,187 @@
 }
   
 //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>::test_insert(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_multiset
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    typedef typename unordered_multiset_type::bucket_traits bucket_traits;
+ typedef typename unordered_multiset_type::iterator iterator;
+ {
+ typename unordered_multiset_type::bucket_type buckets [BucketSize];
+ unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
 
- typename unordered_multiset_type::bucket_type buckets [BucketSize];
- unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
-
- testset.insert(&values[0] + 2, &values[0] + 5);
-
- const unordered_multiset_type& const_testset = testset;
- { int init_values [] = { 1, 4, 5 };
- TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
+ testset.insert(&values[0] + 2, &values[0] + 5);
 
- typename unordered_multiset_type::iterator i = testset.begin();
- BOOST_TEST (i->value_ == 1);
+ const unordered_multiset_type& const_testset = testset;
+ { int init_values [] = { 1, 4, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
+
+ typename unordered_multiset_type::iterator i = testset.begin();
+ BOOST_TEST (i->value_ == 1);
+
+ i = testset.insert (values[0]);
+ BOOST_TEST (&*i == &values[0]);
+
+ i = testset.iterator_to (values[2]);
+ BOOST_TEST (&*i == &values[2]);
+ testset.erase(i);
 
- i = testset.insert (values[0]);
- BOOST_TEST (&*i == &values[0]);
-
- i = testset.iterator_to (values[2]);
- BOOST_TEST (&*i == &values[2]);
- testset.erase(i);
-
- { int init_values [] = { 1, 3, 5 };
- TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
- testset.clear();
- testset.insert(&values[0], &values[0] + values.size());
+ { int init_values [] = { 1, 3, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
+ testset.clear();
+ testset.insert(&values[0], &values[0] + values.size());
 
- { int init_values [] = { 1, 2, 2, 3, 4, 5 };
- TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
+ { int init_values [] = { 1, 2, 2, 3, 4, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
 
- BOOST_TEST (testset.erase(1) == 1);
- BOOST_TEST (testset.erase(2) == 2);
- BOOST_TEST (testset.erase(3) == 1);
- BOOST_TEST (testset.erase(4) == 1);
- BOOST_TEST (testset.erase(5) == 1);
- BOOST_TEST (testset.empty() == true);
-
- //Now with a single bucket
- typename unordered_multiset_type::bucket_type single_bucket[1];
- unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
- testset2.insert(&values[0], &values[0] + values.size());
- BOOST_TEST (testset2.erase(5) == 1);
- BOOST_TEST (testset2.erase(2) == 2);
- BOOST_TEST (testset2.erase(1) == 1);
- BOOST_TEST (testset2.erase(4) == 1);
- BOOST_TEST (testset2.erase(3) == 1);
- BOOST_TEST (testset2.empty() == true);
+ BOOST_TEST (testset.erase(1) == 1);
+ BOOST_TEST (testset.erase(2) == 2);
+ BOOST_TEST (testset.erase(3) == 1);
+ BOOST_TEST (testset.erase(4) == 1);
+ BOOST_TEST (testset.erase(5) == 1);
+ BOOST_TEST (testset.empty() == true);
+
+ //Now with a single bucket
+ typename unordered_multiset_type::bucket_type single_bucket[1];
+ unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
+ testset2.insert(&values[0], &values[0] + values.size());
+ BOOST_TEST (testset2.erase(5) == 1);
+ BOOST_TEST (testset2.erase(2) == 2);
+ BOOST_TEST (testset2.erase(1) == 1);
+ BOOST_TEST (testset2.erase(4) == 1);
+ BOOST_TEST (testset2.erase(3) == 1);
+ BOOST_TEST (testset2.empty() == true);
+ }
+ {
+ //Now erase just one per loop
+ const int random_init[] = { 3, 2, 4, 1, 5, 2, 2 };
+ const unsigned int random_size = sizeof(random_init)/sizeof(random_init[0]);
+ typename unordered_multiset_type::bucket_type single_bucket[1];
+ for(unsigned int i = 0, max = random_size; i != max; ++i){
+ std::vector<typename ValueTraits::value_type> data (random_size);
+ for (unsigned int j = 0; j < random_size; ++j)
+ data[j].value_ = random_init[j];
+ unordered_multiset_type testset_new(bucket_traits(single_bucket, 1));
+ testset_new.insert(&data[0], &data[max]);
+ testset_new.erase(testset_new.iterator_to(data[i]));
+ BOOST_TEST (testset_new.size() == (max -1));
+ }
+ }
+ {
+ typename unordered_multiset_type::bucket_type buckets [BucketSize];
+ const unsigned int NumBucketSize = BucketSize;
+ const unsigned int LoadFactor = 3;
+ const unsigned int NumIterations = NumBucketSize*LoadFactor;
+ std::vector<value_type> random_init(NumIterations);//Preserve memory
+ std::vector<value_type> set_tester;
+ set_tester.reserve(NumIterations);
+
+ //Initialize values
+ for (unsigned int i = 0; i < NumIterations; ++i){
+ random_init[i].value_ = i*2;//(i/LoadFactor)*LoadFactor;
+ }
+
+ for(unsigned int initial_pos = 0; initial_pos != (NumIterations+1); ++initial_pos){
+ for(unsigned int final_pos = initial_pos; final_pos != (NumIterations+1); ++final_pos){
+
+ //Create intrusive container inserting values
+ unordered_multiset_type testset
+ ( &random_init[0]
+ , &random_init[0] + random_init.size()
+ , bucket_traits(buckets, NumBucketSize));
+
+ BOOST_TEST (testset.size() == random_init.size());
+
+ //Obtain the iterator range to erase
+ iterator it_beg_pos = testset.begin();
+ for(unsigned int it_beg_pos_num = 0; it_beg_pos_num != initial_pos; ++it_beg_pos_num){
+ ++it_beg_pos;
+ }
+ iterator it_end_pos(it_beg_pos);
+ for(unsigned int it_end_pos_num = 0; it_end_pos_num != (final_pos - initial_pos); ++it_end_pos_num){
+ ++it_end_pos;
+ }
+
+ //Erase the same values in both the intrusive and original vector
+ std::size_t erased_cnt = std::distance(it_beg_pos, it_end_pos);
+
+ //Erase values from the intrusive container
+ testset.erase(it_beg_pos, it_end_pos);
+
+ BOOST_TEST (testset.size() == (random_init.size()-(final_pos - initial_pos)));
+
+ //Now test...
+ BOOST_TEST ((random_init.size() - erased_cnt) == testset.size());
+
+ //Create an ordered copy of the intrusive container
+ set_tester.insert(set_tester.end(), testset.begin(), testset.end());
+ std::sort(set_tester.begin(), set_tester.end());
+ {
+ typename std::vector<value_type>::iterator it = set_tester.begin(), itend = set_tester.end();
+ typename std::vector<value_type>::iterator random_init_it(random_init.begin());
+ for( ; it != itend; ++it){
+ while(!random_init_it->is_linked())
+ ++random_init_it;
+ BOOST_TEST(*it == *random_init_it);
+ ++random_init_it;
+ }
+ }
+ set_tester.clear();
+ }
+ }
+ }
 }
 
 //test: insert (seq-version), swap, erase (seq-version), size:
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>::test_swap(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_multiset
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    typedef typename unordered_multiset_type::bucket_traits bucket_traits;
-
    typename unordered_multiset_type::bucket_type buckets [BucketSize];
- typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
- unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
- unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
-
- testset2.insert (&values[0] + 2, &values[0] + 6);
- testset1.swap (testset2);
+ {
+ typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
+ unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
+ unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
 
- { int init_values [] = { 1, 2, 4, 5 };
- TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
+ testset2.insert (&values[0] + 2, &values[0] + 6);
+ testset1.swap (testset2);
 
- { int init_values [] = { 2, 3 };
- TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
+ { int init_values [] = { 1, 2, 4, 5 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
 
- testset1.erase (testset1.iterator_to(values[5]), testset1.end());
- BOOST_TEST (testset1.size() == 1);
- // BOOST_TEST (&testset1.front() == &values[3]);
- BOOST_TEST (&*testset1.begin() == &values[3]);
+ { int init_values [] = { 2, 3 };
+ TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
+ testset1.erase (testset1.iterator_to(values[5]), testset1.end());
+ BOOST_TEST (testset1.size() == 1);
+ // BOOST_TEST (&testset1.front() == &values[3]);
+ BOOST_TEST (&*testset1.begin() == &values[3]);
+ }
 }
 
 //test: rehash:
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_multiset
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    typedef typename unordered_multiset_type::bucket_traits bucket_traits;
 
@@ -261,14 +348,15 @@
 }
 
 //test: find, equal_range (lower_bound, upper_bound):
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>::test_find(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_multiset
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    typedef typename unordered_multiset_type::bucket_traits bucket_traits;
 
@@ -293,8 +381,8 @@
 }
 
 
-template<class ValueTraits>
-void test_unordered_multiset<ValueTraits>
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_multiset<ValueTraits, CacheBegin>
    ::test_clone(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
@@ -302,6 +390,7 @@
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_multiset_type;
    typedef typename unordered_multiset_type::bucket_traits bucket_traits;
    {
@@ -373,6 +462,7 @@
                   < value_type
                   , typename value_type::unordered_set_base_hook_t
>::type
+ , true
>::test_all(data);
 
       test_unordered_multiset < typename detail::get_member_value_traits
@@ -382,6 +472,7 @@
                                , &value_type::unordered_set_node_
>
>::type
+ , false
>::test_all(data);
 
       return 0;
@@ -404,6 +495,7 @@
                   < value_type
                   , typename value_type::unordered_set_base_hook_t
>::type
+ , true
>::test_all(data);
 
       test_unordered_multiset < typename detail::get_member_value_traits
@@ -413,12 +505,14 @@
                                , &value_type::unordered_set_node_
>
>::type
+ , false
>::test_all(data);
 
       test_unordered_multiset < typename detail::get_base_value_traits
                   < value_type
                   , typename value_type::unordered_set_auto_base_hook_t
>::type
+ , true
>::test_all(data);
 
       test_unordered_multiset < typename detail::get_member_value_traits
@@ -428,6 +522,7 @@
                                , &value_type::unordered_set_auto_node_
>
>::type
+ , false
>::test_all(data);
       return 0;
    }

Modified: trunk/libs/intrusive/test/unordered_set_test.cpp
==============================================================================
--- trunk/libs/intrusive/test/unordered_set_test.cpp (original)
+++ trunk/libs/intrusive/test/unordered_set_test.cpp 2008-04-27 11:03:06 EDT (Sun, 27 Apr 2008)
@@ -26,7 +26,7 @@
 
 static const std::size_t BucketSize = 11;
 
-template<class ValueTraits>
+template<class ValueTraits, bool CacheBegin>
 struct test_unordered_set
 {
    typedef typename ValueTraits::value_type value_type;
@@ -40,14 +40,15 @@
    static void test_clone(std::vector<value_type>& values);
 };
 
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>::test_all(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_set
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
    {
@@ -75,14 +76,15 @@
 }
 
 //test case due to an error in tree implementation:
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>::test_impl()
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>::test_impl()
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_set
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
 
@@ -103,14 +105,15 @@
 }
 
 //test: constructor, iterator, clear, reverse_iterator, front, back, size:
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>::test_sort(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_set
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
 
@@ -126,14 +129,15 @@
 }
   
 //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>::test_insert(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_set
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
 
@@ -161,14 +165,15 @@
 }
 
 //test: insert (seq-version), swap, erase (seq-version), size:
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>::test_swap(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_set
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
 
@@ -192,14 +197,15 @@
 }
 
 //test: rehash:
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_set
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
 
@@ -237,14 +243,15 @@
 
 
 //test: find, equal_range (lower_bound, upper_bound):
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>::test_find(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
    typedef unordered_set
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
 
@@ -267,8 +274,8 @@
    BOOST_TEST (testset.find (cmp_val) == testset.end());
 }
 
-template<class ValueTraits>
-void test_unordered_set<ValueTraits>
+template<class ValueTraits, bool CacheBegin>
+void test_unordered_set<ValueTraits, CacheBegin>
    ::test_clone(std::vector<typename ValueTraits::value_type>& values)
 {
    typedef typename ValueTraits::value_type value_type;
@@ -276,6 +283,7 @@
       <value_type
       , value_traits<ValueTraits>
       , constant_time_size<value_type::constant_time_size>
+ , cache_begin<CacheBegin>
> unordered_set_type;
    typedef typename unordered_set_type::bucket_traits bucket_traits;
    {
@@ -347,6 +355,7 @@
                   < value_type
                   , typename value_type::unordered_set_base_hook_t
>::type
+ , true
>::test_all(data);
       test_unordered_set < typename detail::get_member_value_traits
                   < value_type
@@ -355,6 +364,7 @@
                                , &value_type::unordered_set_node_
>
>::type
+ , false
>::test_all(data);
 
       return 0;
@@ -377,6 +387,7 @@
                   < value_type
                   , typename value_type::unordered_set_base_hook_t
>::type
+ , true
>::test_all(data);
 
       test_unordered_set < typename detail::get_member_value_traits
@@ -386,12 +397,14 @@
                                , &value_type::unordered_set_node_
>
>::type
+ , false
>::test_all(data);
 
       test_unordered_set < typename detail::get_base_value_traits
                   < value_type
                   , typename value_type::unordered_set_auto_base_hook_t
>::type
+ , true
>::test_all(data);
 
       test_unordered_set < typename detail::get_member_value_traits
@@ -401,6 +414,7 @@
                                , &value_type::unordered_set_auto_node_
>
>::type
+ , false
>::test_all(data);
       return 0;
    }


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