2

boost::any:

I tried to compile and run the following code to test this:

#include <boost/any.hpp>
#include <boost/pool/object_pool.hpp>

int main()
{
  boost::object_pool<boost::any> pool;
  boost::any *i = pool.malloc();
  *i = 1;

  boost::any *j = pool.construct(2);

  pool.destroy(i);
  pool.destroy(j);
}

But it gets a segfault in the boost::any destructor.

boost::variant:

Trying to compile and run the following:

#include <boost/any.hpp>
#include <boost/pool/object_pool.hpp>
#include <boost/variant.hpp>

int main()
{
  typedef boost::variant<int, double> my_variant;

  boost::object_pool<my_variant> pool;
  my_variant *i = pool.malloc();
  *i = 1;

  my_variant *j = pool.construct(2);

  pool.destroy(i);
  pool.destroy(j);
}

And I got the following error:

a.out: visitation_impl.hpp:207: typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VPCV, mpl_::true_, NBF, W*, S*) [with W = mpl_::int_<20>; S = boost::detail::variant::visitation_impl_step, boost::mpl::l_iter >; Visitor = boost::detail::variant::invoke_visitor

; VPCV = void*; NBF = boost::variant::has_fallback_type_; typename Visitor::result_type = bool; mpl_::true_ = mpl_::bool_]: Assertion `false' failed. Aborted (core dumped)

Is this expected behavior? Does the boost::pool only work for simple C++ types like int, doble, float, etc?

wizurd
  • 3,541
  • 3
  • 33
  • 50

1 Answers1

2

Yes, boost pool works with both. You're simply using it wrong.

CAVEAT: There's really no use at all to use a pool allocator with boost::any because it will dynamically allocate the held value outside of the pool.

But this doesn't mean that you can't if you use it right.

malloc only allocates uninitialized memory. It's your error to expect to be able to assign to it as if it were a fully functional instance of the object type that the point implies.

T *i = pool.malloc();
new (i) T();

This fixes it:

Live On Coliru

#include <boost/pool/object_pool.hpp>
#include <boost/any.hpp>
#include <boost/variant.hpp>

template <typename T>
void run_test() {
    boost::object_pool<T> pool;

    T *i = pool.malloc();
    new (i) T();
    *i = 1;

    T *j = pool.construct(2);

    pool.destroy(i);
    pool.destroy(j);
}

int main() {
    run_test<boost::variant<int, double> >();
    run_test<boost::any>();
}

This also runs clean under asan/ubsan and valgrind.

Bonus Question

Is this expected behavior? Does the boost::pool only work for simple C++ types like int, doble, float, etc?

For POD types or trivial types you could get away with eliding the constructor, much like the C++ compiler is allowed to elide them in those cases.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Is your caveat saying th at theres still no point using boost::any in the pool, even with your correction? – wizurd Feb 11 '18 at 01:54
  • That's literally what I said, yes. Depends on what your use is, obviously. If you're gonna leave them all empty, you can improve allocation efficiency. If you expect all your allocations to be within the pool, then no. The same goes partially for `boost::variant` but only when using `boost::recursive_wrapper<>` (or any other explicit dynamic pointer like `unique_ptr<>` but I'll assume that was self-evident). – sehe Feb 11 '18 at 01:55
  • I have a finite set of types that I new up in vectors over and over and over(mostly the same sized vectors) inside performance critical code, where new is the current bottleneck. Can you think of any way initialize/re-use this memory faster than new? boost::pool just seemed like a generic solution to my problem... – wizurd Feb 11 '18 at 02:26
  • Doesn't sound like you're using `any` then. `variant` could be fine, but also look at at [Boost PolyCollection](http://www.boost.org/doc/libs/master/doc/html/poly_collection.html) – sehe Feb 11 '18 at 02:30
  • variant could be fine for use with boost::pool? or were you referring to Boost PolyCollection? – wizurd Feb 11 '18 at 02:35
  • Note also I said ***nothing*** against Boost Pool - for trivially destructibles you could even use [pool](http://www.boost.org/doc/libs/1_66_0/libs/pool/doc/html/boost_pool/pool/interfaces.html#boost_pool.pool.interfaces.interfaces.pool) which forgoes destructions. I'm not sure why you suggestively say "boost::pool just seemed like a generic solution to my problem..." - the main issues to pay attention to are nested dynamic allocations (like with `any`) and non-trivial types. – sehe Feb 11 '18 at 02:36