Boost logo

Boost :

Subject: Re: [boost] [interprocess][multi_index] emplace() is not sufficient for maps
From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 2009-09-24 18:29:43


On Sep 24, 2009, at 4:26 PM, Ion Gaztañaga wrote:

> Howard Hinnant escribió:
>
>> This is effectively the same thing as:
>> typedef ... map;
>> map m;
>> map::node_ptr p = m.remove(m.emplace_hint(m.begin(),
>> my_special_cheap_key_value, mv1, mv2));
>> p->first = modify( p->second );
>> m.insert( boost::move(p) );
>
> Removing something just after inserting it seems a bit useless. Even
> if we insert in the first position we need to do a comparison to
> make sure the hint is correct.Why not:
>
> map::node_ptr p = m.create_node(my_special_cheap_key_value, mv1, mv2);
> //We would need to unconst-cast...
> const_cast<Key&>(p->first) = modify( p->second );
> m.insert( boost::move(p) );

One could do that but the node allocation and construction is
typically the expensive part of the insertion. Once you've got that
done, and if especially if your hint is correct, the insertion is very
fast. So it seems to me like m.create_node would be interface aimed
at a very rare use case and for an optimization that is going to be
quite minor (percent-wise), perhaps not even measurable.

<shrug> There's always a tradeoff between sizeof interface and
functionality. It might be smart to code it all up, performance test
it, and then decide if create_node actually offers sufficient benefit
to warrant its existence (do that before you release it, lest you have
to keep it for backwards compatibility reasons). For example if I did
that and measured that using create_node was 2x faster than using
remove(emplace_hint(good_hint)), I'd jump up and down in favor of it.
If I measured that it was only 1% faster, I wouldn't include it. In
the dirty real world it will probably fall somewhere between those two
and it'll be time to drag out the good 'ol engineering judgement
(that's why you get the big bucks! :-)).

Btw, I don't think you'll want to design node_ptr such that you'll
need the const_cast. The whole point of node_ptr is to get const-free
access to the key. So it's up to node_ptr to do that const_cast
(actually I think it ends up being a reinterpret_cast, or even just a
C cast) internally.

    typedef pair<Key, T> value_type;
    ...
    value_type* operator->() const
    {
        return (value_type*)addressof(node_->__value_);
    }

The node_ptr for set shouldn't have to be quite as ugly. ;-)

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk