Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread E. Gladyshev

--- Gregory Colvin [EMAIL PROTECTED] wrote:
[...]
 Apropos of which, I now think that the Boost UserAllocator requirements
 should be the default for components that parameterize how they use
 memory, with the Standard Allocator requirements being used only for
 components that need what they offer: a potentially very efficient way
 to allocate large numbers of small objects of known type, and/or a
 way to access storage via proxied pointers.

Perhaps the boost allocator requirements should just combine 
both, the UserAllocator and StandardAllocator requirements.
In a way, StandardAllocators can be considered as 
an extension of UserAllocators.

Eugene


__
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread E. Gladyshev

--- David Abrahams [EMAIL PROTECTED] wrote:
  But indeed allocate/construct/deallocate/destroy is more work than
^^^^
  Oyeah.  These two absolutely don't belong in allocator, period.  Do
  any implementations even use them?  Allocators exist to provide a
  point of customization for users, but you cannot/should not customize
  these.
[...]
 The class getting constructed/destroyed has full control over that or
 the language is utterly bustificated.

I think construct/destroy can be implemented as non-customizable 
static functions in boost just for convinence.

static template typename A 
typename A::pointer construct( A a, size_t n )
{
   typename A::pointer p = a.allocate(n)
   try
   {
 p = new(p) A::value_type[n];
   }
   catch(...)
   {
 a.deallocate( p, n );
   }
   return p;
}

Eugene


__
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 05:42 America/Denver, David Abrahams wrote:
Gregory Colvin [EMAIL PROTECTED] writes:

On Monday, Sep 1, 2003, at 14:48 America/Denver, David Abrahams wrote:
Gregory Colvin [EMAIL PROTECTED] writes:

Conforming containers had better use them.
I'm sorry, but I think that's flat wrong.  What do you suppose that
entry in column 2 of the allocator requirements table (20.1.5) 
means,
after all?
It means any value returned by construct, destroy, or deallocate 
goes
unused.

And once you are down in the coal mine customizing what a pointer
is, I'm not sure you won't need to customize how to construct and
destroy.
The class getting constructed/destroyed has full control over that 
or
the language is utterly bustificated.
Yes, but the allocator may want to do something else as well, and
construct and destroy serve as hooks for whatever that may be.
Regardless, there is absolutely _nothing_ in the standard AFAICT 
which
indicates the containers must use the allocator's construct and
destroy, and several implementations in fact do not.
Well then, I consider the standard broken in that regard.  But we are
off the topic that started this thread.
Apropos of which, I now think that the Boost UserAllocator 
requirements
should be the default for components that parameterize how they use
memory, with the Standard Allocator requirements being used only for
components that need what they offer: a potentially very efficient way
to allocate large numbers of small objects of known type, and/or a
way to access storage via proxied pointers.
I think part of my point was that *nobody* needs what they offer, if
you include construct/destroy.
Or rather that some implementations have failed to use what they
offer, and our standard unfortunately doesn't insist that they do.
Another reason construct is needed is that Allocator::pointer might
be a proxy, with operator* and operator- but not necessarily a
conversion to void* or even T*.
  In fact, construct requires undefined
behavior for non-POD T because you can't copy its T* argument which
points into raw storage.
I don't understand what you mean by this.  Are you claiming that
it is undefined to copy just a pointer to raw storage?  If so,
then how is placement new not undefined?  The standard says:
  a.construct(p,t)
  Effect: new((void*)p) T(t)
I think I would rather see a MPL lambda expression or metafunction
class interface for allocator type parameters.  It makes little sense
for the allocator's user to be choosing its value_type.
Something like:

  some_allocator_1

or

  struct select_allocator
  {
  template class T
  struct apply
  {
  typedef some_allocatorT type;
  };
  };
with some_allocator's interface being like what's required for
std::allocator but not including misplaced interface bits such as
address/construct/destroy, and possibly max_size -- these can be added
by a std::allocator facade wrapper if neccessary.
I'm not sure we need a simple version and a complicated version.
I'm not clear how you intend the above to be used, or what you
intend it to be a replacement for.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams wrote:

Gregory Colvin [EMAIL PROTECTED] writes:

I think part of my point was that *nobody* needs what they offer, if
you include construct/destroy.
Or rather that some implementations have failed to use what they
offer, and our standard unfortunately doesn't insist that they do.
It's not unfortunate if it adds nothing, which is what I believe.

Another reason construct is needed is that Allocator::pointer might
be a proxy, with operator* and operator- but not necessarily a
conversion to void* or even T*.
Doesn't matter; you can always get the address of an object.  See
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#390
So you would rather use this than use construct?

  template typename T T* addressof(T v)
  {
return reinterpret_castT*(
 const_castchar(reinterpret_castconst volatile char 
(v)));
  }

In fact, construct requires undefined behavior for non-POD T
because you can't copy its T* argument which points into raw
storage.
I don't understand what you mean by this.  Are you claiming that
it is undefined to copy just a pointer to raw storage?
Unless the pointer has the right type, yes.
In which case the A::pointer return from A::allocate() is already
undefined behavior?
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams wrote:

Gregory Colvin [EMAIL PROTECTED] writes:
...
Dave:
I think I would rather see a MPL lambda expression or metafunction
class interface for allocator type parameters.  It makes little sense
for the allocator's user to be choosing its value_type.
Something like:

  some_allocator_1

or

  struct select_allocator
  {
  template class T
  struct apply
  {
  typedef some_allocatorT type;
  };
  };
with some_allocator's interface being like what's required for
std::allocator but not including misplaced interface bits such as
address/construct/destroy, and possibly max_size -- these can be 
added
by a std::allocator facade wrapper if neccessary.

I'm not sure we need a simple version and a complicated version.
I'm not clear how you intend the above to be used, or what you
intend it to be a replacement for.
I intend it to be the sort of type parameter that gets passed to our
objects which need custom allocation in place of a standard allocator.
It's ridiculous, IMO, to pass allocatorT to a node-based container
which is *never* going to allocate a T object.
But given rebind() it doesn't really matter.  We could just as
well have specified that all containers take allocatorvoid
arguments.
  The container itself
should decide which type the allocator template gets instantiated on,
via:
mpl::applympl::lambdaS, Node::type

 [
   this is approximately the same as:
 S::template applyU::type == some_allocatorU

   except that it works when S is the lambda expression
   some_allocator_1 as well as when it's the select_allocator
   metafunction class below it.
 ]
Sorry, but I'm still not following this, but that may be
because I don't know much MPL, so I can only guess at what
you are up to.  I probably need a detailed example of how to
write and use one of these thingys to make any sense of your
proposal.
Does your proposal support stateful allocators?

What the rebind requirement in the allocator means for pool
allocation, for example, is that a pool_allocatorT object must
either be stateless (in which case allocator inequality is
meaningless)
Yes, all stateless allocators compare equal, and stateless
allocators are the easiest kind to make compare equal, as
the standard currently requires allocators to do.
or effectively be able to allocate blocks of *any* size
and alignment, rather than just as appropriate for T.
Yes, because node-based containers need to allocate nodes,
perhaps of various kinds, but they don't expose their
node types in their interface.  So you have to pass in
something, and we went with T rather than void or whatever.
It might have been better to have different allocator
interfaces for array-based versus node-based containers,
since array-based containers have no need of rebind(), and
node-based containers have no need of allocatorT.
  It's a conceptual mess.
Alex didn't have MPL when he invented allocators.  So they are
messier than they need to be, but I still say they are not so
bad as you claim, and that it would be easier for the next
standard to repair them than to replace them.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread E. Gladyshev

--- David Abrahams [EMAIL PROTECTED] wrote:
[...]
 Just how do you propose to prevent people from writing their own
 construct/destroy functions?  And if they write an allocator from
 scratch, but *don't* provide construct/destroy manually, where will
 they come from?

What I meant is that if boost allocators won't include constuct/destroy,
all boost developers will probably implement their own construct/destroy
helper functions (outside allocators) to construct/destroy object using
allocators.
In such case, I suggested to include standard 
construct/destroy functions 
in boost (not in allocators).

Eugene


__
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 11:22 America/Denver, David Abrahams wrote:
Gregory Colvin [EMAIL PROTECTED] writes:

On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams 
wrote:

Gregory Colvin [EMAIL PROTECTED] writes:

I think part of my point was that *nobody* needs what they offer, 
if
you include construct/destroy.
Or rather that some implementations have failed to use what they
offer, and our standard unfortunately doesn't insist that they do.
It's not unfortunate if it adds nothing, which is what I believe.

Another reason construct is needed is that Allocator::pointer might
be a proxy, with operator* and operator- but not necessarily a
conversion to void* or even T*.
Doesn't matter; you can always get the address of an object.  See
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html#390
So you would rather use this than use construct?

   template typename T T* addressof(T v)
   {
 return reinterpret_castT*(
  const_castchar(reinterpret_castconst volatile char
  (v)));
   }
As long as it's packaged away and I don't have to look at the
implementation.  A customization point like an allocator should not be
required to supply boilerplate that's always going to be the same.
You are assuming that there was no good reason to allow an allocator
to hook construct and destroy, for instance to do some bookkeeping.
When I need to find out what I need to implement in order to customize
allocation, I don't want to have to read through something which is
50% irrelevant to the task, as the allocator requirements are.
Which is why I'm now suggesting that Boost UserAllocator is a better
default.
But in some cases, like the shared_ptr feature request that got me
thinking on this, what you want is just to have objects allocate
their internals using the same allocator as the container they
are being placed in, in which case you don't need to implement an
allocator, just call get_allocator().
n fact, construct requires undefined behavior for non-POD T
because you can't copy its T* argument which points into raw
storage.
I don't understand what you mean by this.  Are you claiming that
it is undefined to copy just a pointer to raw storage?
Unless the pointer has the right type, yes.
In which case the A::pointer return from A::allocate() is already
undefined behavior?
Wow.  Yes, IIUC.  DR, I guess.
I'm reeling from the implication that the following is undefined
behavior for non-POD T:
	T* p = (T*)malloc(sizeof T);

Are you sure?

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread E. Gladyshev

--- David Abrahams [EMAIL PROTECTED] wrote:
[...]

  I think construct/destroy can be implemented as non-customizable 
  static functions in boost just for convinence.
 
 I think the word static is not what you meant, and is what led me
 to challenge the suggestion.

I used word 'static' because I assumed that construct/destroy 
functions would be implemented in some 'memory' data type
(just to qualify it).

struct memory
{
static template typename A 
typename A::pointer construct( A a, size_t n ) {...}

static template typename A 
void destroy( typename A::pointer ) {...}
};

Eugene



__
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Peter Dimov
Gregory Colvin wrote:

 You are assuming that there was no good reason to allow an allocator
 to hook construct and destroy, for instance to do some bookkeeping.

I'm curious. Have you ever seen such an allocator? I've always assumed that
construct/destroy/pointer are a but someone might need to do that feature
that nobody has ever used. Then again, the Dinkumware implementation
dutifully calls construct and destroy, paying (and forcing me to pay) the
abstraction penalty price... so maybe I'm wrong, and construct/destroy are
useful?

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 11:39 America/Denver, David Abrahams wrote:
Gregory Colvin [EMAIL PROTECTED] writes:

On Tuesday, Sep 2, 2003, at 09:22 America/Denver, David Abrahams 
wrote:
...

I think you're missing my point.  There's no reason that a stateful
allocatorT should have access to the state data required to
allocate U objects, but that's the status quo.
I'm probably missing your point, but the idea is that a container
needs to allocate various kinds of things, and they all get
allocated with the same allocator, either directly or via rebind.
For instance, maybe you are are using memory-mapped files as a
persistent storage.  The Ts and the Us and whatever the container
needs all have to go into the same file, so the allocatorT and
all its rebinds must know which file to use and how.
...
  It's a conceptual mess.
Alex didn't have MPL when he invented allocators.  So they are
messier than they need to be, but I still say they are not so
bad as you claim
Are you saying my factual claims are wrong, or just that all those
issues don't amount to a very important problem?
Just that it doesn't look nearly as messy to me as it does to you.

and that it would be easier for the next standard to repair them
than to replace them.
That may be, but we're here at Boost, talking about the interface we
should be using in Boost components.
Yep.  I still think UserAllocator is a good default, and that where it
doesn't suffice there is some value to playing nicely with STL.
So even when we come up with some beautiful new thing to do the
allocation job better, we will still need adaptors both ways, so that
one can get an allocator from an STL container and turn it in to one
of our new things, or take one of our new things and turn it into an
allocator to use in an STL container.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 12:27 America/Denver, Peter Dimov wrote:

Gregory Colvin wrote:
You are assuming that there was no good reason to allow an allocator
to hook construct and destroy, for instance to do some bookkeeping.
I'm curious. Have you ever seen such an allocator? I've always assumed 
that
construct/destroy/pointer are a but someone might need to do that 
feature
that nobody has ever used.
I've heard allocators described that probably used construct()
to navigate efficiently from a proxy pointer to the raw memory
in which to construct.  But I never saw the code.
 Then again, the Dinkumware implementation
dutifully calls construct and destroy, paying (and forcing me to pay) 
the
abstraction penalty price... so maybe I'm wrong, and construct/destroy 
are
useful?
I don't see that there need be any performance price for what
Dinkumware does, or is that not what you mean by abstraction
penalty?
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 13:00 America/Denver, Peter Dimov wrote:

Gregory Colvin wrote:
On Tuesday, Sep 2, 2003, at 12:27 America/Denver, Peter Dimov wrote:

 Then again, the Dinkumware implementation
dutifully calls construct and destroy, paying (and forcing me to pay)
the abstraction penalty price... so maybe I'm wrong, and
construct/destroy are useful?
I don't see that there need be any performance price for what
Dinkumware does, or is that not what you mean by abstraction
penalty?
I'm not saying that there need be any price in a perfect world. I am 
saying
that in practice, on the compiler I use, there is a price, like 
calling a
non-inline destroy() O(N) times for a value_type that has an inline, 
empty,
nonvirtual destructor. Or even for a built-in value_type.
That is most unfortunate.

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 12:51 America/Denver, David Abrahams wrote:

Gregory Colvin [EMAIL PROTECTED] writes:

On Tuesday, Sep 2, 2003, at 11:22 America/Denver, David Abrahams 
wrote:
Gregory Colvin [EMAIL PROTECTED] writes:

So you would rather use this than use construct?

   template typename T T* addressof(T v)
   {
 return reinterpret_castT*(
  const_castchar(reinterpret_castconst volatile char
  (v)));
   }
As long as it's packaged away and I don't have to look at the
implementation.  A customization point like an allocator should not 
be
required to supply boilerplate that's always going to be the same.
You are assuming that there was no good reason to allow an allocator
to hook construct and destroy, for instance to do some bookkeeping.
The fact that nobody's required to use construct and/or destroy is
testament to that.
Thanks to the weasel-wording nobody's required to use much of
anything besides allocate, deallocate, and rebind.  That doesn't
mean there was no point to all the rest in the original design.
When I need to find out what I need to implement in order to
customize allocation, I don't want to have to read through
something which is 50% irrelevant to the task, as the allocator
requirements are.
Which is why I'm now suggesting that Boost UserAllocator is a better
default.
But in some cases, like the shared_ptr feature request that got me
thinking on this, what you want is just to have objects allocate
their internals using the same allocator as the container they
are being placed in, in which case you don't need to implement an
allocator, just call get_allocator().
Is it enough for all of Boost?
It's probably overkill for some things.

  If so, great!  If not, we still need
to think about what a more-sophisticated interface looks like.
Only if UserAllocator is inadequate?

Also, if shared_ptr only needs to allocate at construction time (I'm
not sure of this) we can avoid storing the allocator at all.
Then how to deallocate?

I'm reeling from the implication that the following is undefined
behavior for non-POD T:
	T* p = (T*)malloc(sizeof T);

Are you sure?
Nope.  3.8/5 shows that I'm wrong.
That's a relief.

 It still doesn't make any sense to
return a T* from allocate since normally with a non-singular T* p,
either p == 0 or *p refers to a constructed T.
The idea was that AllocatorT::pointer might be a proxy type
that cannot be converted to void* and back, so allocate() must
return and construct() must take an AllocatorT::pointer rather
than a void*.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 13:18 America/Denver, E. Gladyshev wrote:
--- Gregory Colvin [EMAIL PROTECTED] wrote:
Yep.  I still think UserAllocator is a good default, and that where it
doesn't suffice there is some value to playing nicely with STL.
So even when we come up with some beautiful new thing to do the
allocation job better, we will still need adaptors both ways, so that
one can get an allocator from an STL container and turn it in to one
of our new things, or take one of our new things and turn it into an
allocator to use in an STL container.
Am I right in trying to summarize your suggestion about UserAllocator?

If you want to parametrize how a boost class manages memory,
use UserAllocator parameter.
Unless you need the standard Allocator interface.

1. The allocator parameter should implement the UserAllocator 
interface.
2. All instances of UserAllocator must be equal and stateless.
The Boost pools use UserAllocator only as a type parameter.  It is not
required to be constructible or comparable.
3. If your class is using STL containers, use boost::memory::allocator
   adapter (see bellow).
Why not just use std::allocator?

4. To construct/destroy objects, use boost::memory::construct/destroy.
See below.

5. Avoid using explicit references to allocators.

... Usage example:
==
template typename T, typename UserAllocator = 
boost::default_user_allocator_new_delete 
class X
{
What if you want X to use the same allocator as some other STL container
constructed with a non-Boost allocator?  That would be difficult unless
you have
  templatetypename T, class StdAllocator = std::allocatorT 
  struct X {
X(const StdAllocator);
Also, it might sometimes be desirable, as it is for shared_ptr, to
defer the choice of allocator until construction time:
  templatetypename T
  struct X {
templateclass StdAllocator = std::allocatorT 
X(const StdAllocator);
Or, if UserAllocator suffices:

  templatetypename T
  struct X {
templateclass UserAllocator X();
T* _p;
Leading underscores are a no-no.

std::vectorT, boost::memory::allocatorT, UserAllocator  _v;

X()
{
_p = boost::memory::constructT, UserAllocator( 1 )
How to pass arguments to T's constructor?  Better just

  p = new(UserAllocator::malloc(sizeof T)) T(...)

}
~X()
{
if( _p )
boost::memory::destroyT, UserAllocator( _p, 1 );
In which case, why not just

  p-~T(), UserAllocator::free(p);

?

}
};
Eugene
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Gregory Colvin
On Tuesday, Sep 2, 2003, at 15:00 America/Denver, David Abrahams wrote:
Gregory Colvin [EMAIL PROTECTED] writes:

Also, if shared_ptr only needs to allocate at construction time (I'm
not sure of this) we can avoid storing the allocator at all.
Then how to deallocate?
Using the custom deleter?
Which will need to store a copy of the allocator, unless one
takes advantage of the weasel wording that lets you instantiate
a new one for the purpose.
...
 It still doesn't make any sense to
return a T* from allocate since normally with a non-singular T* p,
either p == 0 or *p refers to a constructed T.
The idea was that AllocatorT::pointer might be a proxy type
that cannot be converted to void* and back, so allocate() must
return and construct() must take an AllocatorT::pointer rather
than a void*.
Wow, creepy.
Yes.  But unless you grant the desire to support such creepy
beasts then not much of Allocator makes any sense.  And such
beasts can do useful work, like persistent stores and shared
memory.
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread Peter Dimov
David Abrahams wrote:
 Gregory Colvin [EMAIL PROTECTED] writes:

 Also, if shared_ptr only needs to allocate at construction time (I'm
 not sure of this) we can avoid storing the allocator at all.

 Then how to deallocate?

 Using the custom deleter?

The deleter takes care of the pointee, but we are talking about the count. I
think.

I still find the

list shared_ptrX 

hypothetical example where everything needs to use the same custom allocator
somewhat artificial. In custom allocator situations I find

vector X* 

a somewhat better choice since it has much less overhead. But I may be
wrong. :-)

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread E. Gladyshev

--- Gregory Colvin [EMAIL PROTECTED] wrote:
[...]

  3. If your class is using STL containers, use boost::memory::allocator
 adapter (see bellow).
 
 Why not just use std::allocator?

Because boost::memory::allocator will use UserAllocator under the covers.
So if you customized UserAllocator parameter, you customized 
how STL allocate their memory as well.

 
  4. To construct/destroy objects, use boost::memory::construct/destroy.
 
 See below.
 
  5. Avoid using explicit references to allocators.
 
  ... Usage example:
  ==
  template typename T, typename UserAllocator = 
  boost::default_user_allocator_new_delete 
  class X
  {
 
 What if you want X to use the same allocator as some other STL container
 constructed with a non-Boost allocator?  That would be difficult unless
 you have [...]

Yes.


  T* _p;
 
 How to pass arguments to T's constructor?  Better just
 
p = new(UserAllocator::malloc(sizeof T)) T(...)
 
  }
  ~X()
  {
  if( _p )
  boost::memory::destroyT, UserAllocator( _p, 1 );
 
 In which case, why not just
 
p-~T(), UserAllocator::free(p);
 
 ?

The boost::memory::construct/destroy are just convinience wrappers
that will do like just that.
They can also handle exceptions properly.

struct memory
{

template typename T, typename A 
static void destroy( T* p )
{
  try
  {
p-~T();
A::free(p);
  }
  catch( ... )
  { 
A::free(p);  //free memory even if the destructor crashes.
throw;
  }
}

};

Eugene



__
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-09-02 Thread E. Gladyshev

--- Gregory Colvin [EMAIL PROTECTED] wrote:
[...]

  T* _p;
 
 Leading underscores are a no-no.

I didn't see it in boost naming convention docs.
Have I missed it?
Some STL implmentations use leading underscores for members.

Eugene



__
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-08-31 Thread Peter Dimov
Gregory Colvin wrote:

[...]

Two small corrections:

 shared_ptr currently uses std::allocator to allocate counts
 regardless.

No, it uses plain new/delete by default. It is possible to get it to use
std::allocator via a #define.

[...]

 versus standard Allocator

Allocator::pointer p = allocator.allocate(sizeof T);
allocator.construct(p,T());
...
allocator.destroy(p);
allocator.deallocate(sizeof T);

allocate(1) and deallocate(p, 1) if I'm not mistaken.

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-08-31 Thread Gregory Colvin
On Sunday, Aug 31, 2003, at 13:13 America/Denver, David Abrahams wrote:
Gregory Colvin [EMAIL PROTECTED] writes:

But indeed allocate/construct/deallocate/destroy is more work than
  ^^^^
Oyeah.  These two absolutely don't belong in allocator, period.  Do
any implementations even use them?  Allocators exist to provide a
point of customization for users, but you cannot/should not customize
these.
Conforming containers had better use them.
I'm sorry, but I think that's flat wrong.  What do you suppose that
entry in column 2 of the allocator requirements table (20.1.5) means,
after all?
It means any value returned by construct, destroy, or deallocate goes 
unused.

And once you are down in the coal mine customizing what a pointer
is, I'm not sure you won't need to customize how to construct and
destroy.
The class getting constructed/destroyed has full control over that or
the language is utterly bustificated.
Yes, but the allocator may want to do something else as well, and
construct and destroy serve as hooks for whatever that may be.
Using allocator is even more work than allocating raw memory with
malloc and doing placement new and explicit destruction, then freeing
the raw memory.  That's my biggest complaint.
It's new/delete

   T* p = new T();
   ...
   delete p;
versus malloc/free

   T* p = (T*)malloc(sizeof T);
When you need

 malloc(sizeof(T) + N)

Allocators get a lot harder to use.
Agreed.


   new(p) T();
   ...
   p-~T();
   free(p);
versus Boost UserAllocator

   T* p = (T*)user_allocator::malloc(sizeof T);
   new(p) T();
   ...
   p-~T();
   user_allocator::free(p);
versus standard Allocator

   Allocator::pointer p = allocator.allocate(sizeof T);
   allocator.construct(p,T());
   ...
   allocator.destroy(p);
   allocator.deallocate(sizeof T);
  

Oops! There's a pointer missing here.
Silly me for not compiling my email.

 Just a small example of why I'm saying it's a harder interface.
Very small.

 Allocator has strange requirements, like p shall not be null.
Another performance optimization.  In most cases there is no way
that p could be null in the first place, so why waste time checking?
  If I need to build a custom one I have to
navigate rebind and the implications of allocator inequality for which
the standard provides little guidance.
Agreed.  The Boost UserAllocator is easier to implement and to use.

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Boost memory management guidelines

2003-08-31 Thread Gregory Colvin
On Sunday, Aug 31, 2003, at 13:51 America/Denver, Peter Dimov wrote:

Gregory Colvin wrote:

[...]

Two small corrections:

shared_ptr currently uses std::allocator to allocate counts
regardless.
No, it uses plain new/delete by default. It is possible to get it to 
use
std::allocator via a #define.
OK.  Anyway, the std::allocator interface is adequate for shared_ptr.

[...]

versus standard Allocator

   Allocator::pointer p = allocator.allocate(sizeof T);
   allocator.construct(p,T());
   ...
   allocator.destroy(p);
   allocator.deallocate(sizeof T);
allocate(1) and deallocate(p, 1) if I'm not mistaken.
You are not.  I shouldn't post uncompiled code late at night.

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost