Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2002-11-19 12:52:19


"Wesley W. Terpstra" <terpstra_at_[hidden]> writes:

> On Tue, Nov 19, 2002 at 10:38:27AM -0500, David Abrahams wrote:
>> "Wesley W. Terpstra" <terpstra_at_[hidden]> writes:
>> > So... I am beginning to lean towards the "don't do that" approach where I
>> > simply don't allow the user to call member methods on items in the
>> > container. (And not let them take pointers) This allows at least the above
>> > optimization and a few others (like *i = *j; -- no deserialize&serialize)
>> > and probably more I don't forsee yet.
>>
>> I haven't been paying attention, but IIUC what you're proposing, these
>> things are no longer conforming iterators.
>>
>> The way to make random access iterators over disk storage is to build
>> an iterator which stores its value_type internally. You can even
>> arrange for it to construct the value_type in its internal storage on
>> demand, so that it doesn't store anything until it is dereferenced.
>
> I assume you mean they are not iterators because operator -> is
> broken?

And operator*.

> Yes I agree. Aside from that however, I believe they do conform to
> iterators.

So what?

> What you are proposing however is flawed for several reasons.
>
> If I stored the value_type internally, this will break:
>
> map::iterator i = ...;
> map::reference x = *i;
> ++i;
> x = ...; // what is x now pointing at? the wrong record.

That code is already broken if it makes any assumptions about what x
refers to after ++i. Sad but true.

> Also, if you have two iterators pointing at the same thing, but keeping
> distinct value_types internally, expressions like:
> i->set_member_a(j->set_member_b(3) + 2);
> will break -- only one of the changes will make it to disk.

You can get around this by dynamically allocating the value_type and
keeping a cache of active values in the container... if it's
important.

<snip>

> The whole question revolves around:
>
> is the overhead of such a table justified by the benefit of
> allowing member methods to be called on objects within the
> container.

It depends on whether you're advertising STL compatibility or not. If
not, do what ever you like and use a large, loud disclaimer when you
write "iterator" (in quotes) in your documentation. If so, you have to
bite the bullet and make the iterators conform.

> There are significant costs:
> the overhead of redundant cache
> (it is already cached at the sector level)
> the overhead of indexing the map
> (considerable if you are just deserializing an int)
>
> My current answer is "not justified". But, I am open to persuasion,
> especially in the form of an optimized solution.

I think it's early to worry about optimization. Make it work first. An
implementation which lies about its "iterators" is broken.

-- 
                       David Abrahams
   dave_at_[hidden] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

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