Topic: STL allocator spec broken?
Author: akv@cacs.usl.edu (Anil Vijendran)
Date: 1995/12/08 Raw View
I'm in violent agreement when someone says arrays are lowlevel and
that their use should be discouraged. I'm certainly not talking about
making a change in the language just so that array objects could be
constructed differently. That wouldn't even be the last item in the
list of things I'd like to see in C++.
>>>>> On 04 Dec 1995 22:38:45 GMT, martelli@cadlab.it (Alex Martelli)
said:
Alex> Well, there's an old Usenet saying, known as Ugol's Law, that
Alex> goes something like "If you ask if you're the only one -- you
Alex> aren't". But the fact that others feel like you does not imply,
Alex> of necessity, that it makes sense:-). Note, for example, how
Alex> horribly having a link between placement-expression and ctor
Alex> would work in the normal usage case that I outline above, where
Alex> I have to use placement new over already-allocated memory (the
Alex> normal kind, taking a void*) BUT I have to tell the object to
Alex> use another allocator (the one that was originally used to
Alex> get the raw-memory, in a *different* point from the placement
Alex> expression I'm now using) for its own allocation purposes...!
Well... Doing non-default construction on a per-object basis for
arrays is ugly by itself. So, to me, this doesn't seem like a good
argument against implicit arguments being passed to constructors.
Let me rewind a li'l bit.
Why was this syntax invented?
X* ptr = new (allocator) X;
Because
void* raw = allocator.alloc(sizeof(X));
X* ptr = new (raw) X;
is clumsy (error prone?).
(I find the former easier to read/write. But I'm not very sure if it
is just a question of one line vs two lines. I'd like to know what
y'all think about the importance of support for the former.)
If `X' does allocation for its members then there is no language
supported way for `X' to get the allocator. IMHO, that doesn't sound
too good.
1. It is none of the users' business to even think about how the
constructor allocates memory (or whatever) for its members.
2. He has already said where the object has to be allocated.
(Things like:
data_member_ptr = allocator_map[this]->alloc(...);
are not portable and might (I'm not sure) not be thread safe, 'cos
least of all the allocator_map has to be a global variable. Mr Paul
Wilson was talking about this kinda stuff.)
There is atleast one important advantage that I can see to having
support for this:
X::X(implicit Allocator& al = nullAllocator, int args)
// `implicit' is a new keyword ;-)
// could be replaced by `from_new' or some such.
{
}
X* xptr = new (allocator) X(5); // `allocator' becomes implicit
// argument to constructor
X xobject(5); // `nullAllocator' becomes implicit argument to
// constructor, indicating to the constructor
// that the object is not allocated on the
// heap.
X* xptr = new X(5); // `defaultSystemAllocator' becomes implicit
// argument to the constructor.
This way, an object gets to know more about how it was created--
dynamic or on stack. That could give the object a chance to do
somethings more efficiently.
Without support for such implicit arguments, any class that follows
this kind of an allocation paradigm ( new (allocator) X(allocator); )
automatically outlaws itself from array support.
Wouldn't this be a useful thing? Wouldn't this be a decent scheme--
simple to implement, orthogonal etc? I'm sure someone would've thought
about it and discarded it. I want to know WHY!
TIA for digging into this with me.
--
Peace.... +<:-)
Anil
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: akv@cacs.usl.edu (Anil Vijendran)
Date: 1995/12/01 Raw View
>>>>> On 30 Nov 1995 17:52:37 GMT, martelli@cadlab.it (Alex Martelli)
said:
Alex> shape *s = new(pstore) shape(pstore);
Alex> Basically, while it _might_ perhaps be nice to have syntax sugar to
Alex> avoid having to write pstore twice in this way, I do not think there
Alex> is really any burning need for such sugar...
I'm not that much of syntactic-sugar guy, but tell me how you would do
this if you needed to allocate an array of objects?
Doesn't anyone else feel there needs to be a link between the
placement-expression and the constructor? I'm curious 'cos I get the
feeling I'm missing something...
--
Peace.... +<:-)
Anil
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: martelli@cadlab.it (Alex Martelli)
Date: 1995/12/04 Raw View
akv@cacs.usl.edu (Anil Vijendran) writes:
...
> Alex> shape *s = new(pstore) shape(pstore);
> Alex> Basically, while it _might_ perhaps be nice to have syntax sugar to
> Alex> avoid having to write pstore twice in this way, I do not think there
> Alex> is really any burning need for such sugar...
>I'm not that much of syntactic-sugar guy, but tell me how you would do
>this if you needed to allocate an array of objects?
In the same way as when needing to pass ANY argument whatsoever to
the constructors of objects allocated as part of a new[]'ed builtin
array -- i.e., do without. The draft standard simply does not support
any non-default constructors for this case, and despite all the
arguments one could muster against this decision (and there are
surely more important and cogent cases than the specific example
of passing an allocator), there isn't a snowball's chance in Hell
that the committee will budge on this point, I believe. Apparently,
builtin arrays are, reasonably, perceived as very low-level features,
whose use must NOT be encouraged by any enhancement or new support --
witness the recent discussion about the lack of an auto_ptr for
builtin arrays.
Everybody's supposed to be using nicely packaged templates for
arraylike stuff -- and sweat it out if they're *implementing*
the darned "nicely packaged templates".
So, what one does (perhaps inside the template's guts) everytime
one needs a non-default constructor for array elements, is
something like...:
-- use operator new[]() to allocate raw memory (perhaps in a
suitably overloaded form through an allocator);
-- loop over the raw memory, calling placement new on each
slice (with whatever nondefault args one needs) to turn
the raw bits into a living object.
In particular, if need be, one can pass the reference to the
allocato to use in the placement new statement.
>Doesn't anyone else feel there needs to be a link between the
>placement-expression and the constructor? I'm curious 'cos I get the
>feeling I'm missing something...
Well, there's an old Usenet saying, known as Ugol's Law, that
goes something like "If you ask if you're the only one -- you
aren't". But the fact that others feel like you does not imply,
of necessity, that it makes sense:-). Note, for example, how
horribly having a link between placement-expression and ctor
would work in the normal usage case that I outline above, where
I have to use placement new over already-allocated memory (the
normal kind, taking a void*) BUT I have to tell the object to
use another allocator (the one that was originally used to
get the raw-memory, in a *different* point from the placement
expression I'm now using) for its own allocation purposes...!
Alex
--
DISCLAIMER: these are MY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it -- Phone: +39 (51) 597 313 [Fax: 597 120]
Cad.Lab S.p.A., v. Ronzani 7/29, 40033 Casalecchio (BO), Italia
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: John Max Skaller <maxtal@suphys.physics.su.oz.au>
Date: 1995/11/26 Raw View
102757.1646@compuserve.com (Scott Robert Ladd) wrote:
>>Are you talking about:
>
>> 1) the Working Paper specification, or,
>> 2) The Stepanov/Lee specification?
>
>I guess I'm ignorant here; what the heck is a "Stepanov/Lee
>specification, and what is its relevance to Stnadard C++?
The original document describing STL by Stepanov and Lee
is separately maintained from the specification in the
Working Paper, and presented quite differently. While
they generally agree on most details, this is one they
appear not to on.
>
>>...generally you WILL be writing almost all modern C++ code as templates.
>
>While I certainly use a LOT of templates in my work (heck, I've
>written four books full of template examples), I DON'T see any
>obligation to use them for all code. I've always been a believer in
>using the right tool for the right job; my whole reason for using C++
>is that it offers considerable flexibility. In many cases, template
>are over-used; and I find that templates lead to lazy programming,
>where a "generic" tool is used in place of a tuned,
>application-focused piece of code.
I guess I'm biased, being a library builder rather than
application oriented.
--
John Max Skaller voice: 61-2-566-2189
81 Glebe Point Rd fax: 61-2-660-0850
GLEBE NSW 2037 email: maxtal@suphys.physics.oz.au
AUSTRALIA email: skaller@maxtal.com.au
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/11/28 Raw View
In article fsf@marsh.cacs.usl.edu, akv@cacs.usl.edu (Anil Vijendran) writes:
>I have a question in relation to this... I've seen persistence
>systems/libraries where the allocator or the heap itself is passed
>using the placement syntax... for example,
> ptr = new (pstore) shape;
>I have always been wondering how the constructor of the class could
>allocate its data members on the same heap the top level object was
>placed in.
Give the constructor an additional parameter:
ptr = new (pstore) shape(pstore); // or whatever
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: wilson@cs.utexas.edu (Paul Wilson)
Date: 1995/11/29 Raw View
In article <xg3ohtwl6t0.fsf@marsh.cacs.usl.edu>,
Anil Vijendran <akv@cacs.usl.edu> wrote:
>>>>>> On 18 Nov 1995 22:24:33 GMT, wilson@cs.utexas.edu (Paul Wilson)
>said:
>
>I have a question in relation to this... I've seen persistence
>systems/libraries where the allocator or the heap itself is passed
>using the placement syntax... for example,
>
> ptr = new (pstore) shape;
>
>I have always been wondering how the constructor of the class could
>allocate its data members on the same heap the top level object was
>placed in.
>
>I think the placement syntax when extended to persistent stores and
>such, whatever goes as the placement-expression, should be passed to
>the constructor too.. Or can this be done sans such an extension?
It can be done without an extension, if there's a routine that an
object can use to find out what heap it itself is allocated in.
The Texas persistent store provides such a routine. Every in-use
page of memory is part of a persistent store or a transient
(conventional non-persistent) store, and this routine simply checks
to see what store the page belongs to. So an object can effectively
ask "where am I?" and then "allocate this there too".
This is not necessarily the best way to do it, however, because checking
what store owns a page takes dozens of instructions. Another way of
doing it is for the object to hold onto a pointer to its store, and
use that when allocating its sub-objects. That way the lookup only
happens once.
Yet another way to do it is to capture the pointer to the store object
(essentially an allocator) from the constructor and hold onto it for
later use, so that the lookup doesn't have to be done at all.
We're trying to figure out the most graceful way of making this work
with STL. We haven't yet grokked all of the standardsese in the new
working paper, but it doesn't seem hard. (If it is hard, STL needs
to be fixed. My earlier mail on this topic was based on ignorance
of the new working paper---I didn't realize that the allocator model
had changed from the Stepanov version.)
Does anybody know of a clear description of the current allocator model?
Do the new books on STL---e.g., Nelson's---explain this, or are they out
of date because things have changed very recently?
Is there a standard set of programming style recommendations for
using allocators?
Paul
--
| Paul R. Wilson, Comp. Sci. Dept., U of Texas @ Austin (wilson@cs.utexas.edu)
| Papers on memory allocators, garbage collection, memory hierarchies,
| persistence and Scheme interpreters and compilers available via ftp from
| ftp.cs.utexas.edu, in pub/garbage (or http://www.cs.utexas.edu/users/wilson/)
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: vandevod@cs.rpi.edu (David Vandevoorde)
Date: 1995/11/24 Raw View
>>>>> "SRL" == Scott Robert Ladd <102757.1646@compuserve.com> writes:
>> Are you talking about:
>> 1) the Working Paper specification, or,
>> 2) The Stepanov/Lee specification?
SRL> I guess I'm ignorant here; what the heck is a "Stepanov/Lee
SRL> specification, and what is its relevance to Stnadard C++?
[...]
Alexander Stepanov is widely regarded as the ``father of STL'';
Meng Lee was his assistant while he further developed STL at HP.
The two of them wrote (and maintained) a document with specifications
for STL: that is item `2)' above.
Daveed
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: wilson@cs.utexas.edu (Paul Wilson)
Date: 1995/11/18 Raw View
My current understanding of STL allocators suggests that the standard
is badly designed. I'd be happy to be corrected if I'm wrong.
As I understand it, STL templates can take an allocator argument,
so that you can instantiate the templates to give different types
that use different allocators.
This seems to me the wrong way to go. The allocator should be specified
for particular instances to make the system really useful. That is,
you should be able to allocate instances of exactly the same class
in different ways.
For example, if one of your allocators manages shared memory and another
manages private memory, you'd like to have data structures that can cross
that boundary. Suppose you want to create a private list that is
a prefix of a shared list, or some kind of private tree whose subtrees
are shared. You'd like the instances to be of the same type, so that
you can have pointers from one to the other without krufty special-case
code.
An example that's closer to my heart is that I want to support STL
classes with orthogonal persistence. I'd like it to be possible
for a piece of code to operate on instances of a class irrespective
of whether they're allocated in transient memory, or in a persistent
store.
(E.g., for a database transaction, I may have temporary relations
implemented as collections on the transient heap, but permanent relations
allocated on the persistent heap. I'd like the same code to be able to
operate on either, because the query processing steps don't care about
whether they're operating on intermediate or permanent relations. I'd
also like the transient relations to be able to hold pointers to objects
that may themselves be transient objects generated during query processing,
or persisent objects faulted into memory from the p-store by a search query.)
As I understand it, ObjectSpace STL does support per-instance specification
of allocators, although I'm unclear on the details and whether it actually
works the way I'd like.
Will the STL standard eventually support this?
Am I mistaken that the standard STL allocator model conflicts with what
I want to do? Are instantiations of templates with different allocators
different types, requiring different code to operate on them? I suppose
we could write all of our code as template functions and generate two
versions of everything, but that's ugly and not a complete solution.
(A little background here: by default, our persistent store does not
checkpoint pages of transient memory. If a failure occurs during a
transaction, all transient objects simply disappear, and all changes
to persistent data are lost---i.e., not propagated to the persistent
store. It is assumed that the transaction will be restarted and the
transient data will be regenerated.)
--
| Paul R. Wilson, Comp. Sci. Dept., U of Texas @ Austin (wilson@cs.utexas.edu)
| Papers on memory allocators, garbage collection, memory hierarchies,
| persistence and Scheme interpreters and compilers available via ftp from
| ftp.cs.utexas.edu, in pub/garbage (or http://www.cs.utexas.edu/users/wilson/)
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]