Discussion:
Question about Memory Pool Example in C++ Faq
(too old to reply)
Philip Lawatsch
2003-07-08 16:02:29 UTC
Permalink
Hi,

I have some questions about whats written in
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14
(Describing some memory pool)

#1 From what i understand this will also work for new x[] and delete
[]x, or did i misunderstand something ?

and,

#2 At the time of destruction i do know from which pool my object came,
and thus i'd like to avoid using a global delete operator.

The example says that I could simply call the destructor and then my
pool's dealloc method.
But, what do I have to do if I do not have one single object, but an
array of objects ?
Call each objects destructor and then a dealloc for the whole array ?
Isn't there a way to simply call some delete[] (mypool) my_array ?

with kind regards philip
Philip Lawatsch
2003-07-08 17:15:14 UTC
Permalink
Post by Philip Lawatsch
#2 At the time of destruction i do know from which pool my object came,
and thus i'd like to avoid using a global delete operator.
The example says that I could simply call the destructor and then my
pool's dealloc method.
But, what do I have to do if I do not have one single object, but an
array of objects ?
Call each objects destructor and then a dealloc for the whole array ?
That's right.
But this is a hassle for me, since I then have to rember the size of
each array (the number of elements in there) or otherwise i would not be
able to delete it correctly.

Looks like this will just increase my overhead and not give me any
significant speedups.

My problem is, i'm doing billions (!) of new and delete (and copy ctors)
on small int arrays, which results in quie slow code.
Post by Philip Lawatsch
Isn't there a way to simply call some delete[] (mypool) my_array ?
It might work, but rules of C++ say that if you use placement new you must
use explicit delete. So, best stick to the rules.
Well, not sure if you understood what i meant.
I'm looking for something like

int * foo = new (mypool) int[x];
delete[] (mypool) foo;

Something that will call the ctors and then call my pools delete, but
for arrays, and for my specific pool, just like the placement new does.

with kind regards philip
John Harrison
2003-07-08 18:47:23 UTC
Permalink
Post by Philip Lawatsch
Post by Philip Lawatsch
#2 At the time of destruction i do know from which pool my object came,
and thus i'd like to avoid using a global delete operator.
The example says that I could simply call the destructor and then my
pool's dealloc method.
But, what do I have to do if I do not have one single object, but an
array of objects ?
Call each objects destructor and then a dealloc for the whole array ?
That's right.
But this is a hassle for me, since I then have to rember the size of
each array (the number of elements in there) or otherwise i would not be
able to delete it correctly.
Looks like this will just increase my overhead and not give me any
significant speedups.
My problem is, i'm doing billions (!) of new and delete (and copy ctors)
on small int arrays, which results in quie slow code.
Perhaps you should have a look at the small object allocator that is part of
the Loki library. I did some tests on it myself and found a significant
speed up compared to the allocator that comes with my compiler.

http://sourceforge.net/projects/loki-lib/

Also described in the book 'Modern C++ Design' by Andrei Alexandrescu. Well
worth having.
Post by Philip Lawatsch
Post by Philip Lawatsch
Isn't there a way to simply call some delete[] (mypool) my_array ?
It might work, but rules of C++ say that if you use placement new you must
use explicit delete. So, best stick to the rules.
Well, not sure if you understood what i meant.
I'm looking for something like
int * foo = new (mypool) int[x];
delete[] (mypool) foo;
Well that's fine.
Post by Philip Lawatsch
Something that will call the ctors and then call my pools delete, but
for arrays, and for my specific pool, just like the placement new does.
with kind regards philip
john
Philip Lawatsch
2003-07-09 05:59:51 UTC
Permalink
Post by John Harrison
Post by Philip Lawatsch
Well, not sure if you understood what i meant.
I'm looking for something like
int * foo = new (mypool) int[x];
delete[] (mypool) foo;
Well that's fine.
Really ?
Neat, from what I understood this is not valid, I really gotta write
some small example and give it a try.
Perhaps the FAQ should be updated slightly to make that more clear

with kind regards Philip
John Harrison
2003-07-09 06:35:08 UTC
Permalink
Post by Philip Lawatsch
Post by John Harrison
Post by Philip Lawatsch
Well, not sure if you understood what i meant.
I'm looking for something like
int * foo = new (mypool) int[x];
delete[] (mypool) foo;
Well that's fine.
Really ?
Neat, from what I understood this is not valid, I really gotta write
some small example and give it a try.
Perhaps the FAQ should be updated slightly to make that more clear
with kind regards Philip
Actually its not, I don't know what I was thinking of. Sorry about that.

Placement delete does exist but it is only called during exception handling,
it can't be called explicitly. E.g.

#include <iostream>
using namespace std;

class Pool
{
};

class X
{
public:
X() { /*throw "error";*/ }
void* operator new[](size_t bytes, Pool& p)
{
cout << "placement new\n";
return malloc(bytes);
}
void operator delete[](void* ptr, Pool& p)
{
cout << "placement delete\n";
free(ptr);
}
void operator delete[](void* ptr)
{
cout << "ordinary delete\n";
free(ptr);
}
};

int main()
{
Pool pool;
try
{
X* x = new (pool) X[10];
delete[] x;
}
catch (...)
{
}
}

This program prints

placement new
ordinary delete

but uncommect the throw statement from the X constructor and it prints

placement new
placement delete

See http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/1995/N0642.pdf for
instance.

john
John Harrison
2003-07-09 06:39:07 UTC
Permalink
Post by John Harrison
Placement delete does exist but it is only called during exception handling,
it can't be called explicitly. E.g.
#include <iostream>
using namespace std;
class Pool
{
};
class X
{
X() { /*throw "error";*/ }
void* operator new[](size_t bytes, Pool& p)
{
cout << "placement new\n";
return malloc(bytes);
}
void operator delete[](void* ptr, Pool& p)
{
cout << "placement delete\n";
free(ptr);
}
void operator delete[](void* ptr)
{
cout << "ordinary delete\n";
free(ptr);
}
};
int main()
{
Pool pool;
try
{
X* x = new (pool) X[10];
delete[] x;
}
catch (...)
{
}
}
This program prints
placement new
ordinary delete
but uncommect the throw statement from the X constructor and it prints
placement new
placement delete
See http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/1995/N0642.pdf for
instance.
john
However AFAIK you can call placement delete explicitly, e.g. in terms of the
code above

X::operator delete[](x, pool);

of course you have to call destructors explicitly as well.

I think you know as much about this topic as I do (if not more).

john
Philip Lawatsch
2003-07-09 15:17:06 UTC
Permalink
Post by John Harrison
However AFAIK you can call placement delete explicitly, e.g. in terms of the
code above
X::operator delete[](x, pool);
of course you have to call destructors explicitly as well.
Hmmmm ...

Just a thought, my pools delete ops will only get called in case of an
exception by new, isn't it ?

Wouldnt it be possible for me to write a delete operator that takes a
ptr to my Base class and call the destructors in there ?

pseudo code:

class memory_pool
{

void operator delete (void * ptr, Pool & pool) // used in case of
exception at new

void operator delete (void * ptr) // used for atomic types
void operator delete (Base * ptr) // used for everything derived from Base
}

and have a template class

template <class A>
{
void free()
{
some_pool::operator delete (data);
}

A * data

}

In this case the free method of the template would always choose the
correct delete itself, isn't it ?
Its just really bad if you try to delete something that needs a dtor but
is NOT derived from Base ...

with kind regards philip
Michiel Salters
2003-07-09 12:30:09 UTC
Permalink
Post by Philip Lawatsch
Post by Philip Lawatsch
#2 At the time of destruction i do know from which pool my object came,
and thus i'd like to avoid using a global delete operator.
The example says that I could simply call the destructor and then my
pool's dealloc method. But, what do I have to do if I do not have
one single object, but an array of objects ?
Call each objects destructor and then a dealloc for the whole array ?
That's right.
But this is a hassle for me, since I then have to rember the size of
each array (the number of elements in there) or otherwise i would not be
able to delete it correctly.
My problem is, i'm doing billions (!) of new and delete (and copy ctors)
on small int arrays, which results in quie slow code.
No, it won't be slow - at least not for the reasons mentioned -
because deleting an int is a no-op.

You don't even have to write the explicit dtor call, though.
int, like all C types is called a 'POD' in C++. That means Plain Old
Data. For C compatibility, you can still treat those types like in C.

Regards
--
Michiel Salters
Philip Lawatsch
2003-07-09 15:10:28 UTC
Permalink
Post by Michiel Salters
No, it won't be slow - at least not for the reasons mentioned -
because deleting an int is a no-op.
You don't even have to write the explicit dtor call, though.
int, like all C types is called a 'POD' in C++. That means Plain Old
Data. For C compatibility, you can still treat those types like in C.
Well, for the sake of code beautifullness, i'd like to let the compiler
handle all of these.

This stuff would go right into an array template class, and thus i'd
have to distinguish between atomic types and objects, which is something
i'd rather avoid. (I do not have rtti support in my programme for
instance, and have no intentions to add it)

But, from all the answers i've got it seems that everything boils down
to exaclty this.

Sad though, since i thought that there was a better solution to this


Btw, is there a nice way to differ between atomic (PODs) and other types
at compile time ? (for templates)

Like

template <class A>
class foo
{
void something()
{
if (A kindof POD)
somecode
else
othercode
}
};
But at compile time, NOT runtime ?!


with kind regarsd philip
tom_usenet
2003-07-09 16:44:44 UTC
Permalink
Post by Philip Lawatsch
Btw, is there a nice way to differ between atomic (PODs) and other types
at compile time ? (for templates)
Yes, type traits, although compiler support is required to determine
that some types are PODS. A type traits implementation without
compiler support can manage to tell that these are PODs:

int
double
etc.
int*
T*
POD[]
etc.

but can't for UDT's like this:

struct POD
{
int x;
int y;
};

Some compilers do provide support with intrinsic type traits (SGI's
and perhaps Metroworks?)
Post by Philip Lawatsch
Like
template <class A>
class foo
{
void something()
{
if (A kindof POD)
somecode
else
othercode
}
};
But at compile time, NOT runtime ?!
Here's one way:

template<class A, bool impl = is_pod<A>::value>
class foo
{
//pod implementation
};

template <class A>
class foo<A, false>
{
//non pod implenentation
};

Obviously you can select at a finer grain if you prefer, using
forwarding to overloaded "something_impl" functions taking a true_type
and false_type.

You can get type_traits from www.boost.org, or you could implement
them yourself if you really wanted.

Tom

Loading...