Giter Club home page Giter Club logo

intrusive's Introduction

Boost.Intrusive

Boost.Intrusive, part of collection of the Boost C++ Libraries, is a library presenting intrusive containers to the world of C++. Intrusive containers are special containers that offer better performance and exception safety guarantees than non-intrusive containers (like STL containers). The performance benefits of intrusive containers makes them ideal as a building block to efficiently construct complex data structures like multi-index containers or to design high performance code like memory allocation algorithms.

While intrusive containers were and are widely used in C, they became more and more forgotten in C++ due to the presence of the standard containers which don't support intrusive techniques.Boost.Intrusive wants to push intrusive containers usage encapsulating the implementation in STL-like interfaces. Hence anyone familiar with standard containers can easily use Boost.Intrusive.

License

Distributed under the Boost Software License, Version 1.0.

Properties

  • C++03
  • Header-Only

Build Status

Branch Travis Appveyor Coverity Scan codecov.io Deps Docs Tests
master Build Status Build status Coverity Scan Build Status codecov Deps Documentation Enter the Matrix
develop Build Status Build status Coverity Scan Build Status codecov Deps Documentation Enter the Matrix

Directories

Name Purpose
doc documentation
example examples
include headers
proj ide projects
test unit tests

More information

  • Ask questions
  • Report bugs: Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well.
  • Submit your patches as pull requests against develop branch. Note that by submitting patches you agree to license your modifications under the Boost Software License, Version 1.0.
  • Discussions about the library are held on the Boost developers mailing list. Be sure to read the discussion policy before posting and add the [intrusive] tag at the beginning of the subject line.

intrusive's People

Contributors

bad-ed avatar beman avatar danieljames avatar douggregor avatar gongminmin avatar grafikrobot avatar igaztanaga avatar imikejackson avatar je4d avatar jewillco avatar jhellrung avatar jzmaddock avatar lastique avatar ldionne avatar marcelraad avatar mateidavid avatar mclow avatar mike-devel avatar olk avatar pdimov avatar sdarwin avatar sigmundvik avatar slymz avatar steveire avatar stgates avatar straszheim avatar swatanabe avatar theidexisted avatar timblechmann avatar tomerv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

intrusive's Issues

MSVC-12 ICE after 1.70

This manifests as compilation errors in Boost.Log, for example:

C:\src\boost\boost/intrusive/list_hook.hpp(92) : fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'msc1.cpp', line 1325)
 To work around this problem, try simplifying or changing the program near the locations listed above.
Please choose the Technical Support command on the Visual C++ 
 Help menu, or open the Technical Support help file for more information
        C:\src\boost\boost/log/sinks/block_on_overflow.hpp(60) : see reference to class template instantiation 'boost::intrusive::list_base_hook<boost::intrusive::link_mode<auto_unlink>>' being compiled
Internal Compiler Error in C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\amd64\cl.exe.  You will be prompted to send an error report to Microsoft later.

    call "bin.v2\standalone\msvc\msvc-12.0\address-model-64\architecture-x86\msvc-setup.bat" amd64 >nul
 cl /Zm800 -nologo @"bin.v2\libs\log\test\~hdr-sinks~hpp.test\msvc-12.0\debug\address-model-64\link-static\threadapi-win32\threading-multi\~hdr-sinks~hpp.obj.rsp" 

https://ci.appveyor.com/project/Lastique/log/builds/24810593/job/bb94dmla8d0a5a5b#L739

Reproduces with MSVC-12 x86 and x64 but not other MSVC versions.

Checking out boost-1.70.0 of Boost.Intrusive and keeping everything else unchanged resolves these errors.

Bug: Rehashing an empty unordered_set with `cache_begin` set to true hits an assert

Creating a boost::intrusive::make_unordered_set with cache_begin set to true and immediately rehashing will hit an assert. The assert that's hit is here:

BOOST_INTRUSIVE_INVARIANT_ASSERT(insertion_bucket < this->bucket_hash_type::priv_bucket_count());

If cache_begin is set to false, or the collection is not empty, the assert is not hit.

Here is a gist of a small program that will reproduce the issue: https://gist.github.com/seelabs/c91655d1a3516f854b17145faac7db25

Licensing question for math.hpp

In math.hpp, the floor_log2 functions implementation seems to be copied from a Stack Overflow thread (the SO thread is linked in the Boost source file). If I understand the Stack Overflow licensing notice correctly, that code is licensed under CC BY-SA 3.0 (snippet initially posted on Jul 9 2012). I'm not a jurist (at all!) but couldn't that be incompatible with Boost.Intrusive being licensed under Boost Software License? Not sure how it can be mitigated if it is though...

pointer_rebinder does not support types of the form template<class T, int N>

This leads e.g.

#include <boost/container/small_vector.hpp>

template<typename T, std::size_t X = 32>
struct alloc
{ 
  using value_type = T;
  void* allocate(std::size_t n);
  void deallocate(void* p, std::size_t n);
};

boost::container::small_vector<int, 16, alloc<int>> vec;

to fail to build (just removing std::size_t X = 32 makes it work).

This is because

https://github.com/boostorg/intrusive/blob/develop/include/boost/intrusive/pointer_rebind.hpp#L99

does not work - and sadly there's no absolutely generic way in C++ to match all type & non type template arguments.

Would it be possible to at least add an overload for things with a single non-type parameter ?

constexpr

I am using intrusive now for a very long time. From a memory managment perspective it maybe possible to make intrusie constexpr? Ofc reinterpret_cast or void* may be a problem.

Stateful node_traits for rbtree

Hi!

Are there any plans on making a possibility to have a stateful node_traits class?

Then one can store not pointers, but indices in his custom node_traits and when there is a need for a conversion, node_traits state can be used. It is ok if there is a need to copy node_traits instance from time to time.

Kind regards,
Dmitriy

Extend traits class to support custom logic after swaps and rotations

Hi,

The Ygg library of intrusive data structures (https://github.com/tinloaf/ygg) allows custom logic to be called after node swaps and rotations by implementing the node traits class interface. For example:

Do you see it possible to allow similar functionality in Boost.Instrusive by extending the traits class interface similarly to as in Ygg?

Modular Boost C++ Libraries Request

We are in the process of making B2 build changes to all of the B2 build files
to support "modular" consumption of the Boost Libraries by users. See this list
post for some details: https://lists.boost.org/Archives/boost/2024/01/255704.php

The process requires making a variety of changes to make each Boost library
independent of the super-project structure. But the changes do not remove the
super-project structure or the comprehensive Boost release. The changes make
solely make it possible, optionally, for users, like package manages, to easily
consume libraries individually.

Generally the changes include:

  • Adding a libroot/build.jam.
  • Porting any functionality from libroot/jamfile to libroot/build.jam.
  • Moving boost-install declaration from libroot/build/jamfile is applicable.
  • Adjusting other B2 build files in the library, like test/jamfile, as needed.
  • Possible changes to C++ source files to remove includes relative to the
    super-project boostroot location.

Some examples of such changes:

We are asking how you would like us to handle the changes. We would prefer if
you allow the owners of the Boost.org GitHub project to make changes to B2
build files, as needed, to accomplish the changes. But understand
that you may want to manage the proposed changes yourself.

We previously sent emails to all known maintainers to fill out a form with their
preference. We are contacting you in this issue as we have not gotten a response
to that email. You can see the ongoing responses for that form and the responses
to these issues here https://github.com/users/grafikrobot/projects/1/views/6

We are now asking if you can reply directly to this issue to indicate your
preference of handling the changes. Please supply a response to this question
and close the issue (so that we can verify you are a maintainer).

How would you like the build changes to be processed?

  1. Pull request, reviewed and merged by a BOOSTORG OWNER.
  2. Pull request, reviewed and merged by YOU.
  3. Other. (please specify details in the reply)

Also please indicate any special instructions you want us to consider. Or other
information you want us to be aware of.

Thanks you, René

Latest commit `01b4f62` breaks Interprocess, Unordered

Link to commit: 01b4f62

I'm maintaining Unordered and this broke our CI.

Running locally using VS 2019 and clang-win 12.0.0:

C:\Users\cmaza\cpp\boost-root\libs\unordered>b2 -aq -j3 test//scoped_allocator cxxstd=14 variant=release address-model=32 toolset=clang-win embed-manifest-via=linker

we see:

====== BEGIN OUTPUT ======
Compiler: Clang version 12.0.0
Library: Dinkumware standard library version 650
__cplusplus: 201402

BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: 1
BOOST_UNORDERED_EMPLACE_LIMIT: 10
BOOST_UNORDERED_CXX11_CONSTRUCTION: 1

Running scoped_allocator

EXIT STATUS: -1073741819
====== END OUTPUT ======

I don't have a stacktrace at the moment but the easiest way of replicating this is to simply update all the submodules and then try running Unordered's and/or Interprocess' test suite.

This issue does not happen when using commit 56291fa

treap: Same type for priority and key comparison leads to ambiguous base class error

Using the same type for priority and key comparison leads to an ambiguous base class error.

A fix for this issue is in my pull request #37, which added a type tag to ebo_functor_holder.

Also note that when the key/priority comparison types are the same, the size of the class may increase by one word because the two empty base classes need distinct addresses. This is possibly worth mentioning in the documentation because this is a case where the size might be larger than expected.

With my testing, the extra word is only allocated when constant_time_size<false> is used. My testing was on "Apple LLVM version 10.0.0 (clang-1000.11.45.5)", I haven't tried other compilers/platforms yet.

For example:

#include <boost/intrusive/treap_set.hpp>

using namespace boost::intrusive;

class Test : public bs_set_base_hook<>
{
public:
    Test(int priority, int key) :
	m_priority(priority), m_key(key)
    {
    }

    int priority() const { return m_priority; }
    int key() const { return m_key; }

private:
    int m_priority;
    int m_key;
};

struct PriorityOfValue
{
    using type = int;

    type operator()(Test const& v) const {
	return v.priority();
    }
};

struct KeyOfValue
{
    using type = int;

    int operator()(Test const& v) const {
	return v.key();
    }
};

int main()
{
    Test t1(1, 2);

    treap_set<
	Test,
	key_of_value<KeyOfValue>,
	priority_of_value<PriorityOfValue>,
	priority<std::less<int>>,
	compare<std::less<int>>
    > s;

    s.insert(t1);
}

Gives this error Xcode clang:

In file included from less.cpp:1:
In file included from /Users/janm/Builds/boost_1_69_0/boost/intrusive/treap_set.hpp:17:
/Users/janm/Builds/boost_1_69_0/boost/intrusive/treap.hpp:161:38: error: 
      ambiguous conversion from derived class
      'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, KeyOfValue, std::__1::less<int>,
      PriorityOfValue, std::__1::less<int>, unsigned long, true, void>' to base
      class 'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, KeyOfValue, std::__1::less<int>,
      PriorityOfValue, std::__1::less<int>, unsigned long, true,
      void>::prio_base' (aka 'ebo_functor_holder<std::__1::less<int> >'):
    class boost::intrusive::treap_impl<struct boost::intrusive::bhtraits<class Test, struct boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link, struct boost::intrusive::dft_tag, 6>, struct KeyOfValue, struct std::__1::less<int>, struct PriorityOfValue, struct std::__1::less<int>, unsigned long, true, void> -> bstree_impl<struct boost::intrusive::bhtraits<class Test, struct boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link, struct boost::intrusive::dft_tag, 6>, struct KeyOfValue, struct std::__1::less<int>, unsigned long, true, BsTreeAlgorithms, void> -> bstbase<struct boost::intrusive::bhtraits<class Test, struct boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link, struct boost::intrusive::dft_tag, 6>, struct KeyOfValue, struct std::__1::less<int>, true, unsigned long, (enum boost::intrusive::algo_types)4U, void> -> bstbase_hack<struct boost::intrusive::bhtraits<class Test, struct boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link, struct boost::intrusive::dft_tag, 6>, struct KeyOfValue, struct std::__1::less<int>, true, unsigned long, (enum boost::intrusive::algo_types)4U, void> -> bstbase2<struct boost::intrusive::bhtraits<class Test, struct boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link, struct boost::intrusive::dft_tag, 6>, struct KeyOfValue, struct std::__1::less<int>, (enum boost::intrusive::algo_types)4U, void> -> detail::ebo_functor_holder<typename bst_key_types<typename bhtraits<Test, tree_node_traits<void *>, boost::intrusive::safe_link, dft_tag, 6>::pointer, KeyOfValue, less<int> >::value_compare> -> struct boost::intrusive::tree_value_compare<class Test *, struct std::__1::less<int>, struct KeyOfValue, _Bool, false> -> boost::intrusive::detail::ebo_functor_holder<less<int> >
    class boost::intrusive::treap_impl<struct boost::intrusive::bhtraits<class Test, struct boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link, struct boost::intrusive::dft_tag, 6>, struct KeyOfValue, struct std::__1::less<int>, struct PriorityOfValue, struct std::__1::less<int>, unsigned long, true, void> -> detail::ebo_functor_holder<typename treap_prio_types<typename bhtraits<Test, tree_node_traits<void *>, boost::intrusive::safe_link, dft_tag, 6>::pointer, PriorityOfValue, less<int> >::priority_compare>
   {  return static_cast<prio_base&>(*this).get();  }
                                     ^~~~~
/Users/janm/Builds/boost_1_69_0/boost/intrusive/treap.hpp:601:75: note: in
      instantiation of member function
      'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, KeyOfValue, std::__1::less<int>,
      PriorityOfValue, std::__1::less<int>, unsigned long, true,
      void>::priv_pcomp' requested here
  ...this->insert_unique_check(key, this->key_comp(), prio, this->priv_pcomp(...
                                                                  ^
/Users/janm/Builds/boost_1_69_0/boost/intrusive/treap.hpp:515:45: note: in
      instantiation of member function
      'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, KeyOfValue, std::__1::less<int>,
      PriorityOfValue, std::__1::less<int>, unsigned long, true,
      void>::insert_unique_check' requested here
      std::pair<iterator, bool> ret = this->insert_unique_check(key_of_v...
                                            ^
/Users/janm/Builds/boost_1_69_0/boost/intrusive/treap_set.hpp:241:25: note: in
      instantiation of member function
      'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, KeyOfValue, std::__1::less<int>,
      PriorityOfValue, std::__1::less<int>, unsigned long, true,
      void>::insert_unique' requested here
   {  return tree_type::insert_unique(value);  }
                        ^
less.cpp:57:7: note: in instantiation of member function
      'boost::intrusive::treap_set_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, KeyOfValue, std::__1::less<int>,
      PriorityOfValue, std::__1::less<int>, unsigned long, true, void>::insert'
      requested here
    s.insert(t1);
      ^
1 error generated.

Feature: `constexpr` default constructor

Although in an older issue, it was concluded that general constexpr may be difficult to achieve, I believe there would be considerable benefit in just a constexpr default constructor for the container types and the hooks. Since C++20, we have the constinit specifier for global variables, which means the global can be initialised without running code, which is desirable especially in bare-metal/kernel scenarios, where there is little one can rely on during early boot. However, constinit requires a constexpr constructor, for obvious reasons. Global containers in bare-metal scenarios usually start-off empty, so a default constructor that is constexpr would already go a long way.

[Feature request] punch hole hook for aggregates

Let's take a look at a synthetic example of an aggregate structure taken from my head:

struct Foo
{
    char ch;
    int64_t value;
    char ch1;
    int64_t value1;
    char ch2;
    char ch3;
    short sh;
    short sh2;
};

In my platform size of this structure is 40 bytes, where 24 bytes - real occupied by fields, but 16 bytes - its just a padding (proofs here: https://godbolt.org/z/cEbYe8ozo)

The main idea behind this issue is why don't we start exploiting these padded bytes? For example, on the x64 architecture 16 bytes would be enough to place 2 pointers in them, respectively, we can declare an intrusive list without adding list_member_hook<> or list_base_hook<> to structure.

I see it like that:

//This option will configure "list" to use the punch hole hook
typedef punch_hole_hook<Foo> PunchHoleHookOption;

//This list will use the punch hole hook
typedef list<Foo, PunchHoleHookOption> FooList;

//An object to be inserted in the list
Foo foo_object;
FooList list;

list.push_back(object);

assert(&list.front() == &foo_object);

FAQ:

  1. How we can implement this?

In my opinion, for this task, it is enough to implement punch_hole_hook<> template class. If interested, I can prepare a drafted PR. This class can be implemented using the boost.pfr library(new reflection library from Antony Polukhin)

  1. Why is this needed?

This is useful in some exotic cases to get the maximum memory optimization without reordering the structure fields.

  1. What are the disadvantages of this approach?
  • Non-portable code
  • Low speed of iterating over the elements of the list, due to the fact that the pointer to the next or prev element has to be unmarshalled from padded bytes
  • Low speed of add or delete operations by the list, due to the fact that the pointer to the next or prev element has to be marshalled into padded bytes
  • ??

nop splice removes element

Calling boost::intrusive::list<>::splice()
void splice(const_iterator p, list_impl&x, const_iterator f, const_iterator e)
with e == p will not leave the list unchanged as it should be.

  template<class T>
  using ilist = boost::intrusive::list<T, boost::intrusive::base_hook<ilist_node>,
       boost::intrusive::constant_time_size<false> >;
  ilist<S> blist;
  S s1( 1 );
  S s2( 2 );
  S s3( 3 );
  blist.push_back( s1 );
  blist.push_back( s2 );
  blist.push_back( s3 );
  blist.splice( next(blist.begin()), blist, blist.begin(), next(blist.begin()) );
  for( auto& s : blist )
    std::cout << s.val << std::endl;

Results in "2 3" and not "1 2 3" as it should be.

Move constructor of list hook is missing

Currently, list hooks do not declare a move constructor. When moved, the copy constructor is called instead, resulting the moved-from hook still linked and the moved-to hook unlinked (https://godbolt.org/z/zKqqhbxz5). An consequence is that objects containing list hooks cannot be safely put inside some STL containers like std::vector (https://godbolt.org/z/vq765G5n5). Furthermore, it is not alway possible to implement a desired move constructor for the class containing list hooks, since link / unlink cannot be performed without the list object if the list has constant time size().

I think making the following changes to list hooks would make them safer and more broadly useful:

  • declare the move constructor as deleted
  • enabled with an option, add a move constructor that unlinks the moved-from hook and link the moved-to hook in its place

Invalid casting in BOOST_INTRUSIVE_BSR_INTRINSIC

Discovered with Boost.Container bug: 159 (boostorg/container#159).

In

BOOST_INTRUSIVE_BSR_INTRINSIC( &log2, (unsigned long)x );
, function floor_log2, there is a bad cast in the second argument that truncates 64 bit values:

BOOST_INTRUSIVE_BSR_INTRINSIC( &log2, (unsigned long)x );

it should be simply:

BOOST_INTRUSIVE_BSR_INTRINSIC( &log2, x );

as BOOST_INTRUSIVE_BSR_INTRINSIC will be _BitScanReverse64 in 64 bit builds, which takes unsigned __int64 as argument.

Add noexcept support to the library

Why doesn't the library use noexcept anywhere? I work in an environment with no exceptions, so intrusive containers are exactly what I need, but when using Boost.Intrusive, there are some problems due to the complete lack of noexcept.

Uninitialized variable warning pointer_plus_bits.hpp:76

Brand new clone of master on Ubuntu Trusty with gcc-7.2 installed, this warning appeared in the build:

Command: ./b2 address-model=64 link=shared threading=multi toolset=gcc-7 variant=release -q -j5
Output:

gcc.compile.c++ bin.v2/libs/log/build/gcc-gnu-7/release/threadapi-pthread/threading-multi/attribute_name.o
In file included from ./boost/intrusive/detail/rbtree_node.hpp:29:0,
                 from ./boost/intrusive/set_hook.hpp:20,
                 from ./boost/intrusive/rbtree.hpp:21,
                 from ./boost/intrusive/set.hpp:20,
                 from libs/log/src/attribute_name.cpp:25:
./boost/intrusive/pointer_plus_bits.hpp: In static member function ‘static boost::log::v2_mt_posix::attribute_name::id_type boost::log::v2_mt_posix::attribute_name::get_id_from_string(const char*)’:
./boost/intrusive/pointer_plus_bits.hpp:76:48: warning: ‘<anonymous>’ may be used uninitialized in this function [-Wmaybe-uninitialized]
       n = pointer(uintptr_t(p) | (uintptr_t(n) & Mask));
                                  ~~~~~~~~~~~~~~^~~~~~~

key_of_value on treap_set seems to be broken in 1.69

The code below fails to compile with Boost 1.69. It works fine with 1.59.

It looks a lot like key_of_value is not handled correctly, unless I am missing something obvious.

#include <boost/intrusive/treap_set.hpp>
#include <string>

using namespace boost::intrusive;

class Test : public bs_set_base_hook<>
{
public:
    Test(int priority, std::string key) :
	m_priority(priority), m_key(std::move(key))
    {
    }

    int priority() const { return m_priority; }
    std::string const& key() const { return m_key; }

private:
    int m_priority;
    std::string m_key;
};

struct PriorityOrder
{
    bool operator()(Test const& lhs, Test const& rhs) const {
	return lhs.priority() < rhs.priority();
    }
};

struct StringKey
{
    using type = std::string;

    type const& operator()(Test const& v) const {
	return v.key();
    }
};

int main()
{
    treap_set<Test, key_of_value<StringKey>, priority<PriorityOrder>> s;

    Test t1(1, "hello");

    s.insert(t1);
}

Compiler output on Xcode clang:

janm@jmmacpro: amt5-api $ c++ -std=c++14 -I /usr/local/include/boost-1_69 jan.cpp
In file included from jan.cpp:1:
In file included from /usr/local/include/boost-1_69/boost/intrusive/treap_set.hpp:17:
In file included from /usr/local/include/boost-1_69/boost/intrusive/treap.hpp:20:
In file included from /usr/local/include/boost-1_69/boost/intrusive/bstree.hpp:33:
In file included from /usr/local/include/boost-1_69/boost/intrusive/detail/key_nodeptr_comp.hpp:26:
/usr/local/include/boost-1_69/boost/intrusive/detail/tree_value_compare.hpp:101:14: error: 
      no matching function for call to object of type 'const
      boost::intrusive::tree_value_compare<Test *, PriorityOrder, StringKey,
      bool, false>::key_compare' (aka 'const PriorityOrder')
   {  return this->key_comp()(key1, KeyOfValue()(value2));  }
             ^~~~~~~~~~~~~~~~
/usr/local/include/boost-1_69/boost/intrusive/detail/key_nodeptr_comp.hpp:110:14: note: 
      in instantiation of member function
      'boost::intrusive::tree_value_compare<Test *, PriorityOrder, StringKey,
      bool, false>::operator()' requested here
   {  return base()(t1, *traits_->to_value_ptr(t2));  }
             ^
/usr/local/include/boost-1_69/boost/intrusive/treap_algorithms.hpp:651:33: note: 
      in instantiation of function template specialization
      'boost::intrusive::detail::key_nodeptr_comp<PriorityOrder,
      boost::intrusive::bhtraits<Test, boost::intrusive::tree_node_traits<void
      *>, boost::intrusive::safe_link, boost::intrusive::dft_tag, 6>,
      StringKey>::operator()<std::__1::basic_string<char>, const
      boost::intrusive::tree_node<void *> *>' requested here
      while(upnode != header && pcomp(k, upnode)){
                                ^
/usr/local/include/boost-1_69/boost/intrusive/treap_algorithms.hpp:493:10: note: 
      in instantiation of function template specialization
      'boost::intrusive::treap_algorithms<boost::intrusive::tree_node_traits<void
      *> >::rebalance_after_insertion_check<std::__1::basic_string<char>,
      boost::intrusive::detail::key_nodeptr_comp<PriorityOrder,
      boost::intrusive::bhtraits<Test, boost::intrusive::tree_node_traits<void
      *>, boost::intrusive::safe_link, boost::intrusive::dft_tag, 6>, StringKey>
      >' requested here
         rebalance_after_insertion_check(header, commit_data.node, key, ...
         ^
/usr/local/include/boost-1_69/boost/intrusive/treap.hpp:662:28: note: in
      instantiation of function template specialization
      'boost::intrusive::treap_algorithms<boost::intrusive::tree_node_traits<void
      *> >::insert_unique_check<std::__1::basic_string<char>,
      boost::intrusive::detail::key_nodeptr_comp<std::__1::less<std::__1::basic_string<char>
      >, boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, StringKey>,
      boost::intrusive::detail::key_nodeptr_comp<PriorityOrder,
      boost::intrusive::bhtraits<Test, boost::intrusive::tree_node_traits<void
      *>, boost::intrusive::safe_link, boost::intrusive::dft_tag, 6>, StringKey>
      >' requested here
         (node_algorithms::insert_unique_check
                           ^
/usr/local/include/boost-1_69/boost/intrusive/treap.hpp:585:20: note: in
      instantiation of function template specialization
      'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, StringKey, void, PriorityOrder, unsigned
      long, true, void>::insert_unique_check<std::__1::basic_string<char>,
      std::__1::less<std::__1::basic_string<char> >, PriorityOrder>' requested
      here
   {  return this->insert_unique_check(key, this->key_comp(), this->priv...
                   ^
/usr/local/include/boost-1_69/boost/intrusive/treap.hpp:499:45: note: in
      instantiation of member function
      'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, StringKey, void, PriorityOrder, unsigned
      long, true, void>::insert_unique_check' requested here
      std::pair<iterator, bool> ret = this->insert_unique_check(key_of_v...
                                            ^
/usr/local/include/boost-1_69/boost/intrusive/treap_set.hpp:240:25: note: in
      instantiation of member function
      'boost::intrusive::treap_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, StringKey, void, PriorityOrder, unsigned
      long, true, void>::insert_unique' requested here
   {  return tree_type::insert_unique(value);  }
                        ^
jan.cpp:44:7: note: in instantiation of member function
      'boost::intrusive::treap_set_impl<boost::intrusive::bhtraits<Test,
      boost::intrusive::tree_node_traits<void *>, boost::intrusive::safe_link,
      boost::intrusive::dft_tag, 6>, StringKey, void, PriorityOrder, unsigned
      long, true, void>::insert' requested here
    s.insert(t1);
      ^
jan.cpp:24:10: note: candidate function not viable: no known conversion from
      'const boost::intrusive::tree_value_compare<Test *, PriorityOrder,
      StringKey, bool, false>::key_type' (aka 'const basic_string<char,
      char_traits<char>, allocator<char> >') to 'const Test' for 1st argument
    bool operator()(Test const& lhs, Test const& rhs) const {
         ^
1 error generated.

unordered_set rehash breaks insert_commit_data

Since boost 1.80.0 there is an issue performing insert_check, rehash and then insert_commit. The bucket_idx in insert_commit_data can become invalid. This was changed in commit 3c5c8ce.

The documentation explicitly states that this is allowed:

After a successful rehashing insert_commit_data remains valid.

This worked in Boost 1.79.0.

Example program:

#include <boost/intrusive/unordered_set.hpp>

struct MyClass : boost::intrusive::unordered_set_base_hook<>
{
    int n_;

    MyClass(int n) : n_(n) { }

    friend bool operator==(const MyClass &a, const MyClass &b)
        { return a.n_ == b.n_; }
    friend std::size_t hash_value(const MyClass &value)
        { return std::size_t(value.n_); }
};

int main()
{
    using Set = boost::intrusive::unordered_set<MyClass>;

    MyClass value(101);
    Set::bucket_type buckets100[100];
    Set::bucket_type buckets200[200];

    Set set(Set::bucket_traits(buckets100, 100));

    Set::insert_commit_data commitData;
    set.insert_check(value, commitData);

    set.rehash(Set::bucket_traits(buckets200, 200));

    set.insert_commit(value, commitData);

    assert(1 == set.count(101));

    return 0;
}

Unnecessary qualified inheritance causes MSVC ICE

In the base-specifier-list of slist_impl::data_t the qualification slist_impl:: is unnecessary:

: public slist_impl::value_traits
This causes an ICE in MSVC https://developercommunity.visualstudio.com/content/problem/352789/c1001-in-compiler-file-msc1cpp-line-1518-with-inhe.html when the following code is compiled:

#include <boost/intrusive/slist.hpp>
#include <boost/concept_check.hpp>
template<class> struct Concept { BOOST_CONCEPT_USAGE(Concept) {} };
template<class> struct Node : boost::intrusive::slist_base_hook<> {};
template<class T> struct H {
    using Y = int;
    boost::intrusive::slist<Node<T>> x;
};
BOOST_CONCEPT_ASSERT((Concept<H<int>::Y>));

Please consider removing this qualification as a workaround. Obviously it will continue to be required within struct data_t.

typedef typename slist_impl::value_traits value_traits;

<functional> might not be included soon enough when building treap_multiset_test.cpp

Working with a set of proprietary C++ headers derived from Dinkum, building the treap_multiset_test.cpp test fails due to the definition of std::greater<T> not being visible yet at the point in generic_multiset_test.hpp where it is used.

In this environment the header does not appear to be included at that point yet, although it is included later.
Adding

#include <functional>

immediately after the include of <typeinfo> in generic_multiset_test.hpp, appears to fix the problem.

*set.rbegin() looks like O(log(N))

This commit from 2015 flipped its implementation, but the commit message does not seem relevant. So we can indeed support O(1) back()-like operation, but there's no dedicated back() and this one became O(log(N)). I'm not sure whether that's an intentional change to conform to other changes, or just a mistake?

(The diagram comment says the header's right child always points to rightmost node.)

natvis error

It looks like an intrusive structure was changed, but the .natvis file was not updated:

Natvis: C:\USERS\VINNIE\APPDATA\LOCAL\MICROSOFT\VISUALSTUDIO\15.0_9E383727\EXTENSIONS\2LQQCEYY.5SD\Visualizers\boost_IntrusiveContainers.natvis(48,29): Error: class "boost::intrusive::list_impl<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator >::element,boost::intrusive::list_node_traits<void *>,0,boost::intrusive::dft_tag,1>,unsigned int,0,void>::root_plus_size" has no member "size_"
Error while evaluating 'data_.root_plus_size_.size_' in the context of type 'lounge-server.exe!boost::intrusive::list_impl<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator >::element,boost::intrusive::list_node_traits<void *>,0,boost::intrusive::dft_tag,1>,unsigned int,0,void>'.
Natvis: C:\USERS\VINNIE\APPDATA\LOCAL\MICROSOFT\VISUALSTUDIO\15.0_9E383727\EXTENSIONS\2LQQCEYY.5SD\Visualizers\boost_IntrusiveContainers.natvis(35,29): Error: class "boost::intrusive::list_impl<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator >::element,boost::intrusive::list_node_traits<void *>,0,boost::intrusive::dft_tag,1>,unsigned int,0,void>::root_plus_size" has no member "size_"
Error while evaluating 'data_.root_plus_size_.size_' in the context of type 'lounge-server.exe!boost::intrusive::list_impl<boost::intrusive::bhtraits<boost::beast::http::basic_fields<std::allocator >::element,boost::intrusive::list_node_traits<void *>,0,boost::intrusive::dft_tag,1>,unsigned int,0,void>'.
The program '[23136] lounge-server.exe' has exited with code 0 (0x0).

One test fails to compile due to errors C2976 C3203 C2516 C2039 C3646 C4430 C2873 C2131 with latset reversion on boost master branch

Environment:
VS2019+Windows Server 2019

Issue description:
Found \boost\libs\intrusive build errors C2976 C3203 C2516 C2039 C3646 C4430 C2873 C2131 in MSVC, this issue can be reproduced on boostorg/boost@b5639bd. Could you please take a look?

Reproduce steps:
1.git clone -c core.autocrlf=true --recursive ​https://github.com/boostorg/boost.git F:\gitP\boostorg\boost
2.open a VS 2019 x64 command prompt and browse to F:\gitP\boostorg\boost
3..\bootstrap
4..\b2 headers variant=release --build-dir=..\out\amd64rel address-model=64
5..\b2 variant=release --build-dir=..\out\amd64rel address-model=64
6..\b2 -j16 variant=release --build-dir=F:\gitP\boostorg\boost\out\amd64rel libs\intrusive\test address-model=64

ErrorMessage:
.\boost/intrusive/hashtable.hpp(1599): error C2976: 'boost::intrusive::bucket_hash_equal_t': too few template arguments
.\boost/intrusive/hashtable.hpp(1793): error C3203: 'bucket_hash_equal_t': unspecialized class template can't be used as a template argument for template parameter 'DeriveFrom', expected a real type
.\boost/intrusive/hashtable.hpp(1760): error C2516: 'DeriveFrom': is not a legal base class
.\boost/intrusive/hashtable.hpp(1820): error C2039: 'key_equal': is not a member of 'boost::intrusive::hashtable_size_wrapper<int,SizeType,false>'
.\boost/intrusive/hashtable.hpp(1820): error C3646: 'key_equal': unknown override specifier
.\boost/intrusive/hashtable.hpp(1820): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/intrusive/hashtable.hpp(1885): error C2873: 'priv_clear_buckets': symbol cannot be used in a using-declaration
'boost::intrusive::hashtable_size_wrapper<boost::intrusive::hashdata_internal<ValueTraits,VoidOrKeyOfValue,VoidOrKeyHash,VoidOrKeyEqual,BucketTraits,SizeType,1>,SizeType,true>'
.\boost/intrusive/hashtable.hpp(2214): error C3646: 'const_siterator': unknown override specifier
.\boost/intrusive/hashtable.hpp(2214): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/intrusive/hashtable.hpp(2276): error C2039: 'bucket_overhead': is not a member of 'boost::intrusive::hashtable_size_wrapper<boost::intrusive::hashdata_internal<ValueTraits,VoidOrKeyOfValue,VoidOrKeyHash,VoidOrKeyEqual,BucketTraits,SizeType,1>,SizeType,true>'
.\boost/intrusive/hashtable.hpp(2276): error C2065: 'bucket_overhead': undeclared identifier
.\boost/intrusive/hashtable.hpp(2276): error C2131: expression did not evaluate to a constant
.\boost/intrusive/hashtable.hpp(2214): error C2039: 'const_siterator': is not a member of
libs\intrusive\test\custom_bucket_traits_test.cpp(125): error C2660: 'boost::intrusive::hashdata_internal<ValueTraits,VoidOrKeyOfValue,VoidOrKeyHash,VoidOrKeyEqual,BucketTraits,SizeType,5>::cend': function does not take 0 arguments

log:
test.log
test.log.59.txt

boost/intrusive/hashtable.hpp: build failure (undeclared indentifier)

Hi,

With commit 05bb580, major changes were implemented in intrusive/hashtable.cpp.

The changed code was published with Boost 1.80, and starting with this release, build errors can be observed due to an undeclared identifier in line 222 of hashtable.cpp:

In file included from /home/data/test/autobuild/host/mips64-buildroot-linux-gnu/sysroot/usr/include/boost/intrusive/unordered_set.hpp:18,
                 from ../src/RemoteTagCache.hxx:29,
                 from ../src/Instance.cxx:30:
/home/data/test/autobuild/host/mips64-buildroot-linux-gnu/sysroot/usr/include/boost/intrusive/hashtable.hpp: In static member function ‘static std::size_t boost::intrusive::prime_list_holder<Dummy>::position(std::size_t, std::size_t)’:
/home/data/test/autobuild/host/mips64-buildroot-linux-gnu/sysroot/usr/include/boost/intrusive/hashtable.hpp:222:69: error: ‘sizes’ was not declared in this scope; did you mean ‘size’?
  222 |          return fastmod_u32(hash, inv_sizes32[size_index], uint32_t(sizes[size_index]));
      |                                                                     ^~~~~
      |                                                                     size

There is no fix in master or development branch yet.

Kind regards,
Andreas

deprecation warning

See: https://wandbox.org/permlink/zsA9pNqip1v6bZod

/opt/wandbox/boost-1.68.0/gcc-head/include/boost/intrusive/detail/tree_iterator.hpp:73:32: note: because 'boost::intrusive::tree_iterator<boost::intrusive::mhtraits<boost::beast::http::basic_fields<std::allocator<char> >::value_type, boost::intrusive::set_member_hook<boost::intrusive::link_mode<boost::intrusive::normal_link> >, &boost::beast::http::basic_fields<std::allocator<char> >::value_type::set_hook_>, false>' has user-provided 'boost::intrusive::tree_iterator<ValueTraits, IsConst>::tree_iterator(const boost::intrusive::tree_iterator<typename boost::intrusive::iiterator<ValueTraits, IsConst, std::bidirectional_iterator_tag>::value_traits, false>&) [with ValueTraits = boost::intrusive::mhtraits<boost::beast::http::basic_fields<std::allocator<char> >::value_type, boost::intrusive::set_member_hook<boost::intrusive::link_mode<boost::intrusive::normal_link> >, &boost::beast::http::basic_fields<std::allocator<char> >::value_type::set_hook_>; bool IsConst = false; typename boost::intrusive::iiterator<ValueTraits, IsConst, std::bidirectional_iterator_tag>::value_traits = boost::intrusive::mhtraits<boost::beast::http::basic_fields<std::allocator<char> >::value_type, boost::intrusive::set_member_hook<boost::intrusive::link_mode<boost::intrusive::normal_link> >, &boost::beast::http::basic_fields<std::allocator<char> >::value_type::set_hook_>]'
   73 |    BOOST_INTRUSIVE_FORCEINLINE tree_iterator(tree_iterator<value_traits, false> const& other)
      |                                ^~~~~~~~~~~~~

Problem with MSVC 19.26.28806

With fully updated MSVC (cl.exe version 19.26.28806)
The below example produces an access violation.

If the list template alias declaration is inside a the class the program crashes since it apparently incorrectly computes the offset of the list member hook, so adding g1 to the list overwrites its vtbl.

On the other hand if the alias declaration appears outside the class after it has been declared it works OK.
It also works OK if the alias declaration is inside Gadget class.

I am not an expert on C++ standard but this seems like a compiler bug.
I reported it to Microsoft:
https://developercommunity.visualstudio.com/content/problem/1103773/problem-with-code-using-boost-intrusive-list.html

#include <iostream>
#include <boost/intrusive/list.hpp>

class Widget {
public:  
    virtual ~Widget() {}
    virtual void foo() = 0;

    boost::intrusive::list_member_hook<
        boost::intrusive::link_mode<boost::intrusive::normal_link>>
        listHook_;

    using List = boost::intrusive::list<
        Widget,
        boost::intrusive::member_hook<Widget, decltype(Widget::listHook_), &Widget::listHook_>>;
};

class Gadget : public Widget {
public:
    Gadget() {}
    void foo() {   
        puts("hello");
    }
};


using List = boost::intrusive::list<
    Widget, 
    boost::intrusive::member_hook<Widget, decltype(Widget::listHook_), &Widget::listHook_>>;

int main()
{
    Gadget g,g1;   
    Widget::List the_list_bad;
    List the_list;
    the_list.push_back(g);
    the_list_bad.push_back(g1); //overwrites vtbl
    auto& gl1 = the_list.front();
    auto& gl2 = the_list_bad.front(); 
    gl1.foo();
    gl2.foo(); //crashes
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.