Boost logo

Boost :

From: Daryle Walker (dwalker07_at_[hidden])
Date: 2003-08-27 00:06:40


On Monday, August 25, 2003, at 2:57 PM, Peter Dimov wrote:

> E. Gladyshev wrote:
>> --- Peter Dimov <pdimov_at_[hidden]> wrote:
>>
>>> In this context, an allocator parameter is only an excuse for
>>> implementors to avoid doing the necessary work to make function<>
>>> useful out of the box. "You can always use a custom allocator",
>>> right?
>>
>> Considering the variety of real life requirements and platforms, it
>> is not practical to make a library that work out of the box.
>
> The danger in that statement is that it looks obvious, but it's not.
> It is true in some sotuations (not as frequent as is generally
> believed) and false in others, and when it doesn't really hold but is
> axiomatically accepted as truth, it serves as exactly the excuse I was
> talking about. "It is not practical to make a library that works out
> of the box, so users should be happy that they are getting a library
> that can be made to work with a "small" additional investment. Of
> course we'll gladly sell you the additional bits and pieces."

That's an invalid argument, since the STL containers give you a default
value for the allocator argument, which makes containers work out of
the box, and the default is "for free."

> It is interesting to compare the C++ approach with the Java approach
> to memory management in this context. C++ "pragmatically" accepts that
> the shipped malloc is often inadequate and provides several types of
> hooks that you can use to work around the problem. Java does not. If
> the JVM has a broken memory manager you lose and can do nothing about
> it. This gives C++ a short term advantage, but in the long term Java
> wins, since JVM implementors have no choice but to optimize their
> memory managers till they are blue in the face.
>
> Bugs that have no workarounds are always fixed first. :-)

You're making a worse assumption here. Who says that the need for a
different allocator class is because the default one
has-bugs/is-slow/plain-old-sucks? There can be an orthogonal need for
a different allocator class, which no improvement on the default one
can fix.

In this case, the Java user is 100% screwed since they can't change the
memory manager at all. Or at least, can't change the manager without
changing it everywhere. (Allocator policies allow mix-and-match.)

>> That is why STL has allocators. In one project, if STL did not have
>> allocators, I would have to implement my own containers. I was so
>> happy that I didn't have to do it.
>
> So far my experience indicates that people only bother with allocators
> when std::allocator is inadequate, i.e. slow. Your case may, of
> course, be different. It happens sometimes.
>
>> At least a library should be consistent about memory management.
>
> This is an arbitrary requirement.

Taking a quick look at the Standard Library, all of the direct
containers that use dynamic memory take an allocator argument, except
for the maligned std::valarray<>.

>> The issue is how consistent boost is about it (STL is very
>> consistent)? It seems that boost doesn't have any idea about how it
>> manages its memory.
>
> A fairly aggressive way to state it, but I see your point. It is true
> that Boost does not impose any requirements on how the particular
> libraries obtain and manage their memory. But you need to realize that
> "do nothing" can be a conscious design decision. Lack of strict
> requirements means more freedom for the implementations to do what
> they consider best.

This last sentence is probably why std::valarray<> keeps its memory
policy private.

> As an example, consider a hypothetical std::vector<T> that does not
> have an allocator argument and "has no idea how it manages its
> memory." Do you see the implications of that?
>
> 1. vector::resize and vector::reserve can now realloc in place since
> they can talk directly to the memory manager.
>
> 2. On many implementations, vector<T> can now be made as efficient as
> new T[], since new T[] often stores the equivalent of size() and
> capacity() anyway to allow delete[] to do the right thing.
>
>> For example if a boost class X uses std::list, does it have to expose
>> the std::list<> allocator or should it use the standard
>>
>> std::allocator<>.
>> template<typename T>
>> struct X
>> {
>> std::list<T> l;
>> };
>>
>> OR
>>
>> template<typename T, typename A=stl::allocator<T> >
>> struct X
>> {
>> std::list<T, A> l;
>> };
>>
>> Which definition is more friendly to boost?
>
> The correct answer depends on X's interface. Your toy example is not a
> good illustration as this kind of "interface" is rarely seen.
>
>> Is it allowed for a boost libarary to use global new/delete? If so,
>> should it be documented?
>
> Boost libraries are allowed to use the C++ language without
> restrictions.


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