Boost logo

Boost Users :

From: Joaquín Mª López Muñoz (joaquin_at_[hidden])
Date: 2007-02-22 02:25:24


Boris ha escrito:

> On Wed, 21 Feb 2007 23:17:28 +0200, JOAQUIN LOPEZ MU?Z <joaquin_at_[hidden]>
> wrote:
>
> > [...]At the end of the day, the problem is not whether we
> > can have a reliable implementation of refresh(): you
> > enter into the realm of undefined behavior once you
> > modify an element externally to the container. By the
> > time you are to call refresh(), you have already
> > performed an illegal action.
>
> Thanks for all your explanations! They will help me definitly to build a
> more robust program around multi_index_container.
>
> If I understand you correctly it all comes down to what is explained in
> the documentation anyway: Use replace() and not modify() if you want to be
> safe?

Umm, no, sorry, I think I haven't explained myself clearly... Both replace()
and modify() are safe if used correctly --the difference is that replace()
keeps
the original content if the modification is incompatible with the uniqueness
constraints of the container.

What I'm referring to is: consider the following piece of code:

  typedef multi_index_container<
    shared_ptr<int>,
    indexed_by<...>
> mic_t;
  ...
  mic_t m;
  m.insert(shared_ptr<int>(new int(0)));
  mic_t::iterator it=m.begin();
  **it=3; // A
  m.modify(it,null_modifier()); // B

OK, this exemplifies the "resync" trick we were discussing a couple of posts
ago. Although this works in practice, the problem is that line A
is *illegal* as far as the semantics of Boost.MultiIndex (or STL associative
containers for that matter) go: you are not allowed to externally modify
an element if such modification results in a violation of the container
invariant, namely that the elements are kept in ascending order. So,
although //B restores the invariant, strictly speaking the code is illegal
because of //A. When both //B is executed right after //A you are
in practical terms safe, but *only* in practical terms, the formal
specification
of Boost.MultiIndex does not accept the sequence //A,//B as a valid
operation.

If the null_modifier trick is illegal but safe in practice, going further than

that --doing massive external modifications-- is equally illegal and besides
highly dangerous, that's why it's sensible not to consider a refresh()
function
that would in principle ratify massive external modifications.

The subject is a little tricky as it deals with safety in practical and
theoretical
terms, so if anything's still not clear enough please do not hesitate to come
back to me.

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net