Compare commits

...

7 Commits

Author SHA1 Message Date
joaquintides b6a0722f11 documented incompatibility of safe mode with containers in shared memory (closes #95) 2026-06-27 20:25:10 +02:00
joaquintides fbeaf88056 extended fancy pointer support for iterators (#100)
* added memory relocatability test
* added missing #includes
* avoided C++14 std::make_unique
* added hashed index local iterators to the test
* made all iterators store allocator-provided pointers to the nodes
* updated docs
2026-06-27 19:41:10 +02:00
joaquintides 19237f650a allowed deprecated node 20 (#99)
* updated to actions/checkout@v5
* reverted and set ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION
2026-06-18 13:30:09 +02:00
Jonathan Wakely 0356be0f6f Convert example/hashed.cpp to UTF-8 (#98)
This makes the file slightly larger, but that seems preferable because
almost all other Boost source files are encoded as UTF-8 these days.
2026-06-18 09:31:35 +02:00
joaquintides 1f61ddc1ec avoided bogus unitialized warnings in GCC 16.1, plus additional warning silencing (#97)
* added gcc-15, gcc-16
* explicitly constructed bfm_header everywhere
* reverted, silenced uninitialized warning
* moved silencing pragma inside header body
* made silencing pragma enclose entire multi_index_container definition
* abandoned pragma, deinlined header()
* tried an even more convoluted workaround
* type-erased member in header_holder
* s/static_cast/reinterpret_cast
* reverted, passed allocator and header explicitly in construction
* used passed header in construction rather than header()
* investigated if hit by https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119321
* documented GCC 16.1 flag
* avoided VS warning
2026-06-01 19:15:24 +02:00
joaquintides 0d48b7d14b documented #94 2026-04-24 11:45:18 +02:00
kraldan ac4971abc2 [bug] Fix severe performance bug caused by usage of float (#94)
* Replace `float` with `double` in hashed_index.hpp

* Fix formatting indents

* Reset changes

* Add fix from PR comment

comment: https://github.com/boostorg/multi_index/pull/94#issuecomment-4283474290

* forced both args of std::max to the same type

---------

Co-authored-by: Daniel Kral <daniel.kral@recombee.com>
Co-authored-by: joaquintides <joaquin.lopezmunoz@gmail.com>
2026-04-24 10:35:24 +02:00
27 changed files with 408 additions and 140 deletions
+13
View File
@@ -11,6 +11,7 @@ on:
env:
UBSAN_OPTIONS: print_stacktrace=1
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
jobs:
posix:
@@ -79,6 +80,18 @@ jobs:
os: ubuntu-24.04
install: g++-14-multilib
address-model: 32,64
- toolset: gcc-15
cxxstd: "11,14,17,20,23,2c"
container: ubuntu:26.04
os: ubuntu-latest
install: g++-15-multilib
address-model: 32,64
- toolset: gcc-16
cxxstd: "11,14,17,20,23,2c"
container: ubuntu:26.04
os: ubuntu-latest
install: g++-16-multilib
address-model: 32,64
- toolset: clang
compiler: clang++-3.9
cxxstd: "11,14"
+5 -2
View File
@@ -552,8 +552,11 @@ scheme outlined in the
<code>p</code> shall dereference to <code>*p</code>.
</li>
</ul>
<code>multi_index_container</code>s and all their iterators do not store references
to allocated elements other than through the allocator's pointer type.
</li>
</ol>
Indices of a given <code>multi_index_container</code> instantiation cannot have
duplicate <a href="indices.html#tags">tags</a>, either within a single
index or in two different indices.
@@ -1069,9 +1072,9 @@ Index reference
<br>
<p>Revised October 25th 2025</p>
<p>Revised June 27th 2026</p>
<p>&copy; Copyright 2003-2025 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2026 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+19 -2
View File
@@ -30,6 +30,7 @@ Acknowledgements
<h2>Contents</h2>
<ul>
<li><a href="#boost_1_92">Boost 1.92 release</a></li>
<li><a href="#boost_1_91">Boost 1.91 release</a></li>
<li><a href="#boost_1_85">Boost 1.85 release</a></li>
<li><a href="#boost_1_84">Boost 1.84 release</a></li>
@@ -73,6 +74,22 @@ Acknowledgements
<li><a href="#boost_1_33">Boost 1.33 release</a></li>
</ul>
<h2><a name="boost_1_92">Boost 1.92 release</a></h2>
<p>
<ul>
<li>Fancy pointer support has been extended so that <code>multi_index_container</code>
iterators now store references to the elements through the allocator's pointer type.
In particular, this means that iterators can now be placed in shared memory using
<a href="../../interprocess/index.html">Boost.Interprocess</a> allocators.
</li>
<li>Fixed a performance issue with hashed indices when rehashing at very large
container sizes (<a href="https://github.com/boostorg/multi_index/pull/94">PR#94</a>).
Contributed by Daniel Kr&aacute;l.
</li>
</ul>
</p>
<h2><a name="boost_1_91">Boost 1.91 release</a></h2>
<p>
@@ -846,9 +863,9 @@ Acknowledgements
<br>
<p>Revised November 7th 2025</p>
<p>Revised June 27th 2026</p>
<p>&copy; Copyright 2003-2025 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2026 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+3 -3
View File
@@ -201,7 +201,7 @@ than strictly required by the C++ standard, as explained in detail in the
An important type of non-standard allocators supported are those provided by the
<a href="../../../interprocess/index.html">Boost Interprocess Library</a>;
this opens up the possibility of placing <code>multi_index_container</code>s
in shared memory.
and their iterators in shared memory.
</p>
<blockquote><pre>
@@ -340,9 +340,9 @@ Debugging support
<br>
<p>Revised July 17th 2007</p>
<p>Revised June 27th 2026</p>
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2026 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+23 -2
View File
@@ -34,6 +34,7 @@ Techniques
<li><a href="#safe_mode">Safe mode</a>
<ul>
<li><a href="#serialization_and_safe_mode">Serialization and safe mode</a></li>
<li><a href="#shared_memory_and_safe_mode">Containers placed in shared memory</a></li>
</ul>
</li>
<li><a href="#invariant_check">Invariant-checking mode</a></li>
@@ -199,6 +200,26 @@ checked value by using the following workaround:
<span class=identifier>it</span><span class=special>=</span><span class=identifier>es</span><span class=special>.</span><span class=identifier>project</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
</pre></blockquote>
<h3><a name="shared_memory_and_safe_mode">Containers placed in shared memory</a></h3>
<p>
In general, safe mode <b>can't be used</b> when placing <code>multi_index_container</code>s
in shared memory for interprocess communication
(as in <a href="../examples.html#example12">this example</a>).
There are some fundamental reasons for this limitation:
<ul>
<li>
Operations from one process may invalidate or change ownership for iterators
living in non-shared memory within another process: safe-mode machinery can't
access those for bookkeeping.
</li>
<li>
Safe mode uses internal mutexes not suitable for interprocess
synchronization or persistence to a memory-mapped file.
</li>
</ul>
</p>
<h2><a name="invariant_check">Invariant-checking mode</a></h2>
<p>
@@ -240,9 +261,9 @@ Techniques
<br>
<p>Revised May 9th 2020</p>
<p>Revised June 27th 2026</p>
<p>&copy; Copyright 2003-2020 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2026 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+12 -12
View File
@@ -66,23 +66,23 @@ int main()
std::string text=
"En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha "
"mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga "
"antigua, rocín flaco y galgo corredor. Una olla de algo más vaca que "
"carnero, salpicón las más noches, duelos y quebrantos los sábados, "
"lantejas los viernes, algún palomino de añadidura los domingos, "
"consumían las tres partes de su hacienda. El resto della concluían sayo "
"mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga "
"antigua, rocín flaco y galgo corredor. Una olla de algo más vaca que "
"carnero, salpicón las más noches, duelos y quebrantos los sábados, "
"lantejas los viernes, algún palomino de añadidura los domingos, "
"consumían las tres partes de su hacienda. El resto della concluían sayo "
"de velarte, calzas de velludo para las fiestas, con sus pantuflos de lo "
"mesmo, y los días de entresemana se honraba con su vellorí de lo más "
"fino. Tenía en su casa una ama que pasaba de los cuarenta, y una "
"mesmo, y los días de entresemana se honraba con su vellorí de lo más "
"fino. Tenía en su casa una ama que pasaba de los cuarenta, y una "
"sobrina que no llegaba a los veinte, y un mozo de campo y plaza, que "
"así ensillaba el rocín como tomaba la podadera. Frisaba la edad de "
"nuestro hidalgo con los cincuenta años; era de complexión recia, seco "
"así ensillaba el rocín como tomaba la podadera. Frisaba la edad de "
"nuestro hidalgo con los cincuenta años; era de complexión recia, seco "
"de carnes, enjuto de rostro, gran madrugador y amigo de la caza. "
"Quieren decir que tenía el sobrenombre de Quijada, o Quesada, que en "
"Quieren decir que tenía el sobrenombre de Quijada, o Quesada, que en "
"esto hay alguna diferencia en los autores que deste caso escriben; "
"aunque, por conjeturas verosímiles, se deja entender que se llamaba "
"aunque, por conjeturas verosímiles, se deja entender que se llamaba "
"Quejana. Pero esto importa poco a nuestro cuento; basta que en la "
"narración dél no se salga un punto de la verdad.";
"narración dél no se salga un punto de la verdad.";
/* feed the text into the container */
+1 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of use of Boost.Interprocess allocators.
*
* Copyright 2003-2025 Joaquin M Lopez Munoz.
* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -10,7 +10,6 @@
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
@@ -1,4 +1,4 @@
/* Copyright 2003-2023 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -14,6 +14,7 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/detail/raw_ptr.hpp>
#include <boost/operators.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -77,7 +78,7 @@ public:
template<class Archive>
void save(Archive& ar,const unsigned int)const
{
node_base_type* bnode=node;
node_base_type* bnode=get_node();
ar<<core::make_nvp("pointer",bnode);
}
@@ -86,7 +87,7 @@ public:
{
node_base_type* bnode;
ar>>core::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
node=typename Node::pointer(static_cast<Node*>(bnode));
}
#endif
@@ -94,10 +95,10 @@ public:
typedef Node node_type;
Node* get_node()const{return node;}
Node* get_node()const{return raw_ptr<Node*>(node);}
private:
Node* node;
typename Node::pointer node;
};
template<typename Node>
@@ -1,4 +1,4 @@
/* Copyright 2003-2023 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -14,6 +14,7 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/detail/raw_ptr.hpp>
#include <boost/operators.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -76,7 +77,7 @@ public:
template<class Archive>
void save(Archive& ar,const unsigned int)const
{
node_base_type* bnode=node;
node_base_type* bnode=get_node();
ar<<core::make_nvp("pointer",bnode);
}
@@ -92,7 +93,7 @@ public:
{
node_base_type* bnode;
ar>>core::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
node=typename Node::pointer(static_cast<Node*>(bnode));
if(version<1){
BucketArray* throw_away; /* consume unused ptr */
ar>>core::make_nvp("pointer",throw_away);
@@ -105,13 +106,13 @@ public:
{
node_base_type* bnode;
ar>>core::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
node=typename Node::pointer(static_cast<Node*>(bnode));
if(version<1){
BucketArray* buckets;
ar>>core::make_nvp("pointer",buckets);
if(buckets&&node&&node->impl()==buckets->end()->prior()){
if(buckets&&bnode&&node->impl()==buckets->end()->prior()){
/* end local_iterators used to point to end node, now they are null */
node=0;
node=typename Node::pointer(0);
}
}
}
@@ -121,7 +122,7 @@ public:
typedef Node node_type;
Node* get_node()const{return node;}
Node* get_node()const{return raw_ptr<Node*>(node);}
private:
@@ -135,7 +136,7 @@ private:
Node::template increment_local<IndexCategory>(node);
}
Node* node;
typename Node::pointer node;
};
template<
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -712,6 +712,13 @@ public:
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
typedef typename trampoline::difference_type difference_type;
typedef allocator_rebind_t<
typename trampoline::impl_allocator_type,
hashed_index_node> final_allocator_type;
typedef allocator_pointer_t<
final_allocator_type> pointer;
typedef allocator_const_pointer_t<
final_allocator_type> const_pointer;
template<typename Category>
struct node_alg{
@@ -754,15 +761,15 @@ public:
/* interoperability with hashed_index_iterator */
template<typename Category>
static void increment(hashed_index_node*& x)
static void increment(pointer& x)
{
x=from_impl(node_alg<Category>::type::after(x->impl()));
x=pointer(from_impl(node_alg<Category>::type::after(x->impl())));
}
template<typename Category>
static void increment_local(hashed_index_node*& x)
static void increment_local(pointer& x)
{
x=from_impl(node_alg<Category>::type::after_local(x->impl()));
x=pointer(from_impl(node_alg<Category>::type::after_local(x->impl())));
}
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -85,10 +85,16 @@ private:
typedef allocator_size_type_t<Allocator> size_type;
protected:
explicit index_base(const ctor_args_list&,const Allocator&){}
explicit index_base(
const ctor_args_list&,const Allocator&,index_node_type*){}
index_base(
const index_base<Value,IndexSpecifierList,Allocator>&,
const Allocator&,index_node_type*){}
index_base(
const index_base<Value,IndexSpecifierList,Allocator>&,
const Allocator&,index_node_type*,
do_not_copy_elements_tag)
{}
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -707,8 +707,10 @@ public:
}
protected:
ordered_index_impl(const ctor_args_list& args_list,const allocator_type& al):
super(args_list.get_tail(),al),
ordered_index_impl(
const ctor_args_list& args_list,
const allocator_type& al,index_node_type* h):
super(args_list.get_tail(),al,h),
key(tuples::get<0>(args_list.get_head())),
comp_(tuples::get<1>(args_list.get_head()))
@@ -722,8 +724,9 @@ protected:
ordered_index_impl(
const ordered_index_impl<
KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x):
super(x),
KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
const allocator_type& al,index_node_type* h):
super(x,al,h),
key(x.key),
comp_(x.comp_)
@@ -740,8 +743,9 @@ protected:
ordered_index_impl(
const ordered_index_impl<
KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
const allocator_type& al,index_node_type* h,
do_not_copy_elements_tag):
super(x,do_not_copy_elements_tag()),
super(x,al,h,do_not_copy_elements_tag()),
key(x.key),
comp_(x.comp_)
@@ -1512,6 +1516,10 @@ class ordered_index:
SuperMeta,TagList,Category,AugmentPolicy
>
>::type super;
protected:
typedef typename super::index_node_type index_node_type;
public:
typedef typename super::ctor_args_list ctor_args_list;
typedef typename super::allocator_type allocator_type;
@@ -1537,13 +1545,18 @@ public:
protected:
ordered_index(
const ctor_args_list& args_list,const allocator_type& al):
super(args_list,al){}
const ctor_args_list& args_list,
const allocator_type& al,index_node_type* h):
super(args_list,al,h){}
ordered_index(const ordered_index& x):super(x){}
ordered_index(
const ordered_index& x,const allocator_type& al,index_node_type* h):
super(x,al,h){}
ordered_index(const ordered_index& x,do_not_copy_elements_tag):
super(x,do_not_copy_elements_tag()){}
ordered_index(
const ordered_index& x,const allocator_type& al,index_node_type* h,
do_not_copy_elements_tag):
super(x,al,h,do_not_copy_elements_tag()){}
};
#if defined(BOOST_MSVC)
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -131,6 +131,7 @@ struct ordered_index_node_compressed_base
{
typedef ordered_index_node_traits<
AugmentPolicy,Allocator> node_traits;
typedef typename node_traits::allocator node_allocator;
typedef ordered_index_node_impl<
AugmentPolicy,Allocator>* pointer;
typedef const ordered_index_node_impl<
@@ -608,6 +609,14 @@ public:
typedef typename trampoline::const_pointer const_impl_pointer;
typedef typename trampoline::difference_type difference_type;
typedef typename trampoline::size_type size_type;
typedef allocator_rebind_t<
typename trampoline::node_allocator,
ordered_index_node> final_allocator_type;
typedef allocator_pointer_t<
final_allocator_type> pointer;
typedef allocator_const_pointer_t<
final_allocator_type> const_pointer;
impl_color_ref color(){return trampoline::color();}
ordered_index_color color()const{return trampoline::color();}
@@ -646,20 +655,24 @@ public:
raw_ptr<const impl_type*>(x)));
}
/* interoperability with bidir_node_iterator */
/* Interoperability with bidir_node_iterator and index impl.
* Templated for raw-pointer/non-raw-pointer versions.
*/
static void increment(ordered_index_node*& x)
template<typename NodePtr>
static void increment(NodePtr& x)
{
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
x=NodePtr(from_impl(xi));
}
static void decrement(ordered_index_node*& x)
template<typename NodePtr>
static void decrement(NodePtr& x)
{
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
x=NodePtr(from_impl(xi));
}
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -215,11 +215,18 @@ private:
typedef random_access_index_node_trampoline<Super> trampoline;
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
typedef typename trampoline::difference_type difference_type;
typedef typename trampoline::ptr_pointer impl_ptr_pointer;
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
typedef typename trampoline::difference_type difference_type;
typedef typename trampoline::ptr_pointer impl_ptr_pointer;
typedef allocator_rebind_t<
typename trampoline::node_allocator,
random_access_index_node> final_allocator_type;
typedef allocator_pointer_t<
final_allocator_type> pointer;
typedef allocator_const_pointer_t<
final_allocator_type> const_pointer;
impl_ptr_pointer& up(){return trampoline::up();}
impl_ptr_pointer up()const{return trampoline::up();}
@@ -254,25 +261,25 @@ public:
/* interoperability with rnd_node_iterator */
static void increment(random_access_index_node*& x)
static void increment(pointer& x)
{
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
x=pointer(from_impl(xi));
}
static void decrement(random_access_index_node*& x)
static void decrement(pointer& x)
{
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
x=pointer(from_impl(xi));
}
static void advance(random_access_index_node*& x,difference_type n)
static void advance(pointer& x,difference_type n)
{
impl_pointer xi=x->impl();
trampoline::advance(xi,n);
x=from_impl(xi);
x=pointer(from_impl(xi));
}
static difference_type distance(
@@ -1,4 +1,4 @@
/* Copyright 2003-2023 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -14,6 +14,7 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/multi_index/detail/raw_ptr.hpp>
#include <boost/operators.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -87,7 +88,7 @@ public:
template<class Archive>
void save(Archive& ar,const unsigned int)const
{
node_base_type* bnode=node;
node_base_type* bnode=get_node();
ar<<core::make_nvp("pointer",bnode);
}
@@ -96,7 +97,7 @@ public:
{
node_base_type* bnode;
ar>>core::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
node=typename Node::pointer(static_cast<Node*>(bnode));
}
#endif
@@ -104,10 +105,10 @@ public:
typedef Node node_type;
Node* get_node()const{return node;}
Node* get_node()const{return raw_ptr<Node*>(node);}
private:
Node* node;
typename Node::pointer node;
};
template<typename Node>
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -158,6 +158,13 @@ public:
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
typedef typename trampoline::difference_type difference_type;
typedef allocator_rebind_t<
typename trampoline::node_allocator,
sequenced_index_node> final_allocator_type;
typedef allocator_pointer_t<
final_allocator_type> pointer;
typedef allocator_const_pointer_t<
final_allocator_type> const_pointer;
impl_pointer& prior(){return trampoline::prior();}
impl_pointer prior()const{return trampoline::prior();}
@@ -192,20 +199,24 @@ public:
raw_ptr<const impl_type*>(x)));
}
/* interoperability with bidir_node_iterator */
/* Interoperability with bidir_node_iterator and index impl.
* Templated for raw-pointer/non-raw-pointer versions.
*/
static void increment(sequenced_index_node*& x)
template<typename NodePtr>
static void increment(NodePtr& x)
{
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
x=NodePtr(from_impl(xi));
}
static void decrement(sequenced_index_node*& x)
template<typename NodePtr>
static void decrement(NodePtr& x)
{
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
x=NodePtr(from_impl(xi));
}
};
+18 -10
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -735,12 +735,14 @@ public:
}
protected:
hashed_index(const ctor_args_list& args_list,const allocator_type& al):
super(args_list.get_tail(),al),
hashed_index(
const ctor_args_list& args_list,
const allocator_type& al,index_node_type* h):
super(args_list.get_tail(),al,h),
key(tuples::get<1>(args_list.get_head())),
hash_(tuples::get<2>(args_list.get_head())),
eq_(tuples::get<3>(args_list.get_head())),
buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
buckets(al,h->impl(),tuples::get<0>(args_list.get_head())),
mlf(1.0f)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
@@ -752,12 +754,13 @@ protected:
}
hashed_index(
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
super(x),
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
const allocator_type& al,index_node_type* h):
super(x,al,h),
key(x.key),
hash_(x.hash_),
eq_(x.eq_),
buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
buckets(al,h->impl(),x.buckets.size()),
mlf(x.mlf),
max_load(x.max_load)
@@ -773,12 +776,13 @@ protected:
hashed_index(
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
const allocator_type& al,index_node_type* h,
do_not_copy_elements_tag):
super(x,do_not_copy_elements_tag()),
super(x,al,h,do_not_copy_elements_tag()),
key(x.key),
hash_(x.hash_),
eq_(x.eq_),
buckets(x.get_allocator(),header()->impl(),0),
buckets(al,h->impl(),0),
mlf(1.0f)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
@@ -1432,7 +1436,11 @@ private:
if(n>max_load){
size_type bc =(std::numeric_limits<size_type>::max)();
float fbc=1.0f+static_cast<float>(n)/mlf;
if(bc>fbc)bc =static_cast<size_type>(fbc);
if(bc>fbc){
bc =(std::max)(
static_cast<size_type>(fbc),
static_cast<size_type>(bucket_count()+1));
}
unchecked_rehash(bc);
}
}
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -741,9 +741,10 @@ public:
protected:
random_access_index(
const ctor_args_list& args_list,const allocator_type& al):
super(args_list.get_tail(),al),
ptrs(al,header()->impl(),0)
const ctor_args_list& args_list,
const allocator_type& al,index_node_type* h):
super(args_list.get_tail(),al,h),
ptrs(al,h->impl(),0)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
,safe(*this)
@@ -752,9 +753,11 @@ protected:
{
}
random_access_index(const random_access_index<SuperMeta,TagList>& x):
super(x),
ptrs(x.get_allocator(),header()->impl(),x.size())
random_access_index(
const random_access_index<SuperMeta,TagList>& x,
const allocator_type& al,index_node_type* h):
super(x,al,h),
ptrs(al,h->impl(),x.size())
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
,safe(*this)
@@ -766,9 +769,11 @@ protected:
}
random_access_index(
const random_access_index<SuperMeta,TagList>& x,do_not_copy_elements_tag):
super(x,do_not_copy_elements_tag()),
ptrs(x.get_allocator(),header()->impl(),0)
const random_access_index<SuperMeta,TagList>& x,
const allocator_type& al,index_node_type* h,
do_not_copy_elements_tag):
super(x,al,h,do_not_copy_elements_tag()),
ptrs(al,h->impl(),0)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
,safe(*this)
+12 -7
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -165,14 +165,19 @@ public:
}
protected:
ranked_index(const ranked_index& x):super(x){};
ranked_index(const ranked_index& x,do_not_copy_elements_tag):
super(x,do_not_copy_elements_tag()){};
ranked_index(
const ranked_index& x,const allocator_type& al,index_node_type* h):
super(x,al,h){};
ranked_index(
const ctor_args_list& args_list,const allocator_type& al):
super(args_list,al){}
const ranked_index& x,const allocator_type& al,index_node_type* h,
do_not_copy_elements_tag):
super(x,al,h,do_not_copy_elements_tag()){};
ranked_index(
const ctor_args_list& args_list,
const allocator_type& al,index_node_type* h):
super(args_list,al,h){}
private:
template<typename LowerBounder,typename UpperBounder>
+13 -7
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2025 Joaquin M Lopez Munoz.
/* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -655,8 +655,10 @@ public:
}
protected:
sequenced_index(const ctor_args_list& args_list,const allocator_type& al):
super(args_list.get_tail(),al)
sequenced_index(
const ctor_args_list& args_list,
const allocator_type& al,index_node_type* h):
super(args_list.get_tail(),al,h)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
,safe(*this)
@@ -666,8 +668,10 @@ protected:
empty_initialize();
}
sequenced_index(const sequenced_index<SuperMeta,TagList>& x):
super(x)
sequenced_index(
const sequenced_index<SuperMeta,TagList>& x,
const allocator_type& al,index_node_type* h):
super(x,al,h)
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
,safe(*this)
@@ -678,8 +682,10 @@ protected:
}
sequenced_index(
const sequenced_index<SuperMeta,TagList>& x,do_not_copy_elements_tag):
super(x,do_not_copy_elements_tag())
const sequenced_index<SuperMeta,TagList>& x,
const allocator_type& al,index_node_type* h,
do_not_copy_elements_tag):
super(x,al,h,do_not_copy_elements_tag())
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
,safe(*this)
+18 -18
View File
@@ -1,6 +1,6 @@
/* Multiply indexed container.
*
* Copyright 2003-2025 Joaquin M Lopez Munoz.
* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -156,7 +156,7 @@ public:
multi_index_container():
bfm_allocator(allocator_type()),
super(ctor_args_list(),bfm_allocator::member),
super(ctor_args_list(),bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
@@ -166,7 +166,7 @@ public:
const ctor_args_list& args_list,
const allocator_type& al=allocator_type()):
bfm_allocator(al),
super(args_list,bfm_allocator::member),
super(args_list,bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
@@ -174,7 +174,7 @@ public:
explicit multi_index_container(const allocator_type& al):
bfm_allocator(al),
super(ctor_args_list(),bfm_allocator::member),
super(ctor_args_list(),bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
@@ -186,7 +186,7 @@ public:
const ctor_args_list& args_list=ctor_args_list(),
const allocator_type& al=allocator_type()):
bfm_allocator(al),
super(args_list,bfm_allocator::member),
super(args_list,bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
@@ -210,7 +210,7 @@ public:
const ctor_args_list& args_list=ctor_args_list(),
const allocator_type& al=allocator_type()):
bfm_allocator(al),
super(args_list,bfm_allocator::member),
super(args_list,bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
@@ -236,8 +236,7 @@ public:
bfm_allocator(
allocator_select_on_container_copy_construction(
x.bfm_allocator::member)),
bfm_header(),
super(x),
super(x,bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
copy_construct_from(x);
@@ -245,8 +244,9 @@ public:
multi_index_container(multi_index_container&& x):
bfm_allocator(std::move(x.bfm_allocator::member)),
bfm_header(),
super(x,detail::do_not_copy_elements_tag()),
super(
x,bfm_allocator::member,&*bfm_header::member,
detail::do_not_copy_elements_tag()),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
@@ -258,8 +258,7 @@ public:
const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
const allocator_type& al):
bfm_allocator(al),
bfm_header(),
super(x),
super(x,bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
copy_construct_from(x);
@@ -268,8 +267,9 @@ public:
multi_index_container(
multi_index_container&& x,const allocator_type& al):
bfm_allocator(al),
bfm_header(),
super(x,detail::do_not_copy_elements_tag()),
super(
x,bfm_allocator::member,&*bfm_header::member,
detail::do_not_copy_elements_tag()),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
@@ -492,8 +492,7 @@ protected:
const allocator_type& al,
detail::unequal_alloc_move_ctor_tag):
bfm_allocator(al),
bfm_header(),
super(x),
super(x,bfm_allocator::member,&*bfm_header::member),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
@@ -524,8 +523,9 @@ protected:
const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
detail::do_not_copy_elements_tag):
bfm_allocator(x.bfm_allocator::member),
bfm_header(),
super(x,detail::do_not_copy_elements_tag()),
super(
x,bfm_allocator::member,&*bfm_header::member,
detail::do_not_copy_elements_tag()),
node_count(0)
{
BOOST_MULTI_INDEX_CHECK_INVARIANT;
+6 -2
View File
@@ -1,6 +1,6 @@
# Boost.MultiIndex tests Jamfile
#
# Copyright 2003-2025 Joaquín M López Muñoz.
# Copyright 2003-2026 Joaquín M López Muñoz.
# 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)
@@ -37,6 +37,7 @@ project
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
<toolset>msvc:<define>_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
<toolset>msvc:<cxxflags>/wd4494
<toolset>gcc-16:<cxxflags>-fno-thread-jumps # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119321
;
obj boost_multi_index_key_supported : check_bmi_key_supported.cpp ;
@@ -52,7 +53,7 @@ test-suite "multi_index" :
[ run test_copy_assignment.cpp test_copy_assignment_main.cpp ]
[ run test_hash_ops.cpp test_hash_ops_main.cpp ]
[ run test_iterators.cpp test_iterators_main.cpp
/boost/foreach//boost_foreach ]
/boost/foreach//boost_foreach ]
[ run test_key.cpp test_key_main.cpp
: : :
[ check-target-builds boost_multi_index_key_supported
@@ -60,6 +61,9 @@ test-suite "multi_index" :
: : <build>no ] ]
[ run test_key_extractors.cpp test_key_extractors_main.cpp ]
[ run test_list_ops.cpp test_list_ops_main.cpp ]
[ run test_mmap.cpp test_mmap_main.cpp
/boost/interprocess//boost_interprocess
/boost/uuid//boost_uuid ]
[ run test_modifiers.cpp test_modifiers_main.cpp ]
[ run test_mpl_ops.cpp test_mpl_ops_main.cpp ]
[ run test_node_handling.cpp test_node_handling_main.cpp ]
+3 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test suite.
*
* Copyright 2003-2020 Joaquin M Lopez Munoz.
* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -21,6 +21,7 @@
#include "test_key.hpp"
#include "test_key_extractors.hpp"
#include "test_list_ops.hpp"
#include "test_mmap.hpp"
#include "test_modifiers.hpp"
#include "test_mpl_ops.hpp"
#include "test_node_handling.hpp"
@@ -49,6 +50,7 @@ int main()
test_key();
test_key_extractors();
test_list_ops();
test_mmap();
test_modifiers();
test_mpl_ops();
test_node_handling();
+2 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for allocator awareness.
*
* Copyright 2003-2025 Joaquin M Lopez Munoz.
* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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)
@@ -115,7 +115,7 @@ void test_allocator_awareness_for()
BOOST_TEST(element_transfer==(&*c3.begin()==pfirst));
BOOST_TEST(!element_transfer==(c3.begin()->move_cted));
}
if(Propagate||AlwaysEqual){
BOOST_IF_CONSTEXPR(Propagate||AlwaysEqual){
container c2(c);
const move_tracker* pfirst=&*c2.begin();
container c3(root2);
+95
View File
@@ -0,0 +1,95 @@
/* Boost.MultiIndex test for memory relocatability.
*
* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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/multi_index for library home page.
*/
#include "test_mmap.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/lightweight_test.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ranked_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <iterator>
#include <memory>
#include <string>
void test_mmap()
{
using namespace boost::multi_index;
namespace bip=boost::interprocess;
using container=multi_index_container<
int,
indexed_by<
ordered_unique<identity<int>>,
hashed_unique<identity<int>>,
ranked_unique<identity<int>>,
sequenced<>,
random_access<>
>,
bip::allocator<int,bip::managed_mapped_file::segment_manager>
>;
using iterator0=nth_index<container,0>::type::iterator;
using iterator1=nth_index<container,1>::type::iterator;
using local_iterator1=nth_index<container,1>::type::local_iterator;
using iterator2=nth_index<container,2>::type::iterator;
using iterator3=nth_index<container,3>::type::iterator;
using iterator4=nth_index<container,4>::type::iterator;
constexpr auto container_name="container";
static auto file_name_str=
std::string("./test_mmap_")+
to_string(boost::uuids::random_generator()());
static auto file_name=file_name_str.c_str();
bip::file_mapping::remove(file_name);
std::unique_ptr<bip::managed_mapped_file> pseg1(
new bip::managed_mapped_file(bip::create_only,file_name,65536));
container& c1=*pseg1->construct<container>(container_name)(
container::ctor_args_list(),
container::allocator_type(pseg1->get_segment_manager()));
for(int i=0;i<100;++i)c1.insert(i);
auto v0=**pseg1->construct<iterator0>("it0")(c1.get<0>().begin());
auto v1=**pseg1->construct<iterator1>("it1")(c1.get<1>().begin());
auto lv1=**pseg1->construct<local_iterator1>("lit1")(c1.get<1>().begin(0));
auto v2=**pseg1->construct<iterator2>("it2")(c1.get<2>().begin());
auto v3=**pseg1->construct<iterator3>("it3")(c1.get<3>().begin());
auto v4=**pseg1->construct<iterator4>("it4")(c1.get<4>().begin());
bip::managed_mapped_file seg2(bip::open_only,file_name);
pseg1=nullptr;
container& c2=*seg2.find<container>(container_name).first;
auto it0=*seg2.find<iterator0>("it0").first;
auto it1=*seg2.find<iterator1>("it1").first;
auto lit1=*seg2.find<local_iterator1>("lit1").first;
auto it2=*seg2.find<iterator2>("it2").first;
auto it3=*seg2.find<iterator3>("it3").first;
auto it4=*seg2.find<iterator4>("it4").first;
BOOST_TEST_EQ(*it0,v0);
BOOST_TEST_EQ(std::distance(it0,c2.get<0>().end()),c2.size());
BOOST_TEST_EQ(*it1,v1);
BOOST_TEST_EQ(std::distance(it1,c2.get<1>().end()),c2.size());
BOOST_TEST_EQ(*lit1,lv1);
BOOST_TEST_EQ(
std::distance(lit1,c2.get<1>().end(0)),c2.get<1>().bucket_size(0));
BOOST_TEST_EQ(*it2,v2);
BOOST_TEST_EQ(std::distance(it2,c2.get<2>().end()),c2.size());
BOOST_TEST_EQ(*it3,v3);
BOOST_TEST_EQ(std::distance(it3,c2.get<3>().end()),c2.size());
BOOST_TEST_EQ(*it4,v4);
BOOST_TEST_EQ(std::distance(it4,c2.get<4>().end()),c2.size());
}
+11
View File
@@ -0,0 +1,11 @@
/* Boost.MultiIndex test for memory relocatability.
*
* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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/multi_index for library home page.
*/
void test_mmap();
+19
View File
@@ -0,0 +1,19 @@
/* Boost.MultiIndex test for memory relocatability.
*
* Copyright 2003-2026 Joaquin M Lopez Munoz.
* 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/multi_index for library home page.
*/
#include <boost/detail/lightweight_test.hpp>
#include "test_mmap.hpp"
int main()
{
test_mmap();
return boost::report_errors();
}