how to use a pool

A

abir

I am interested to allocate and deallocate lots of objects of same
type (and of course size). As the deallocation will take place in
random order and also the maximum number of objects at any time is not
known (though i have a hint), i can't use a vector for this purpose.

Thus i developed a memory pool for fixed objects(an allocator).
i can make the pool as a template of object type or object size.
at present what i am doing is,
1)
template<size_t sz>struct mypool;
struct myobj;
mypool<sizeof(myobj)> pool(1024);///1024 -> typical pool size
void* ptr = pool.allocate();
myobj* obj = new(ptr)(x,y,z);////where x,y,z are myobj constructor
params.

similarly te destruction is done as,
obj->~myobj();
pool.deallocate(obj);

if i want to have a single step solution for them like
2)
template<typename T> struct mypool;
myobj* ptr = pool.create(x,y,z);
pool.drop(ptr);
Here he first step (ie create ) i can't write as i can't forward the
x,y,z to the class constructor.
I have to use a copy constructor like,
myobj* ptr = pool.create(myobj(x,y,z));
any myobj doesn't have one!.

The most simplistic i wanted to write is of course overloading new &
delete for myobj like
3)
sruct myobj{
public:
static void* new(size_t sz,mypool<sizeof(myobj)>& p){
return p.allocate();
}
static void delete(void* ptr,mypool<sizeof(myobj)>& p){
p.deallocate(ptr);
}
};
and using it as,
mypool<sizeof(myobj)> pool(1024);
myobj* obj = new (pool)(x,y,z);
delete (pool) obj;

However this fancy syntax is not supported by C++ .
(Note: i can't make mypool<sizeof(myobj)> a static member of myobj.
They are to be allocated
from different thread with each one has its own private pool.)

So my choice is option 2, but any way can i make that forwarding take
place without copy constructor ? something like boost inplace factory?
Or can i have any more elegant method to solve this ?

A side question,
I was using boost lambda & function combination something as
function<bool(int)> f = _1 < 5;
or function<void(myobj)> print = std::cout<<_1;
recently wen i was testing it with gcc c++0x mode (also MSVC TR1)
all complains lambda is not overloaded with those operators.Was those
fancy things are BLL specific and not present in std?

Thanks in advance
abir
 
S

Salt_Peter

I am interested to allocate and deallocate lots of objects of same
type (and of course size). As the deallocation will take place in
random order and also the maximum number of objects at any time is not
known (though i have a hint), i can't use a vector for this purpose.

Why can't you use a vector with a reserve()?
Thus i developed a memory pool for fixed objects(an allocator).
i can make the pool as a template of object type or object size.
at present what i am doing is,
1)
template<size_t sz>struct mypool;
struct myobj;
mypool<sizeof(myobj)> pool(1024);///1024 -> typical pool size
void* ptr = pool.allocate();
myobj* obj = new(ptr)(x,y,z);////where x,y,z are myobj constructor
params.

similarly te destruction is done as,
obj->~myobj();
pool.deallocate(obj);

if i want to have a single step solution for them like
2)
template<typename T> struct mypool;
myobj* ptr = pool.create(x,y,z);
pool.drop(ptr);
Here he first step (ie create ) i can't write as i can't forward the
x,y,z to the class constructor.
I have to use a copy constructor like,
myobj* ptr = pool.create(myobj(x,y,z));
any myobj doesn't have one!.

The most simplistic i wanted to write is of course overloading new &
delete for myobj like
3)
sruct myobj{
public:
static void* new(size_t sz,mypool<sizeof(myobj)>& p){
return p.allocate();
}
static void delete(void* ptr,mypool<sizeof(myobj)>& p){
p.deallocate(ptr);
}};

and using it as,
mypool<sizeof(myobj)> pool(1024);
myobj* obj = new (pool)(x,y,z);
delete (pool) obj;

However this fancy syntax is not supported by C++ .

Old time Casting is dangerous at best, you don't know whether a
static_cast, a dynamic cast or a reinterpret cast was carried out.
Thats bad news in C++, lie to the compiler at your own peril.

C++ supports better syntax than the above, difference is allocation
and deallocation is automatic should you choose to do it that way
(less bugs, easier to maintain, a breeze to expand, debugging is much
easier).

#include <deque>

template< typename T >
class Container
{
std::deque< T > dt;
public:
Container( const std::size_t Size,
const T& t = T() ) : dt(Size, t) { }
typedef typename std::deque< T >::iterator iterator;
};

int main()
{
// don't blink
Container< double > container(10, 1.1);
Container< std::string > strings(100, "default");
Container< char > bytes(1000, 'a');
}

T must be copyable and assignable, as usual.

Any code that says "store a bunch of blocks of memory each equivalent
to sizeof(myobj) and then ignore the type inserted in those blocks" is
a pure nightmare. If i say that the apple is an orange then its an
orange, i don't think so? Thats like buying insurance from an ice-
cream salesman.
 
A

abir

Why can't you use a vector with a reserve()?
I already gave the reasons for this.
1) i destroy objects in random order, vector doesn't supports it.
2) i don't know max number of objects i will use. Without that vector
will
invalidate all of the objects.
3) My objects doesn't have copy constructor.
Old time Casting is dangerous at best, you don't know whether a
static_cast, a dynamic cast or a reinterpret cast was carried out.
Thats bad news in C++, lie to the compiler at your own peril.
I am not casting anywhere. am i?
(if at all any casting has to be done it is static cast. But that is
ok for any low
level memory management scheme. And there may be a reinterpret_cast
if i store
the free list pointer in the vacant object place. mypool is
essentially loki small object allocator)
C++ supports better syntax than the above, difference is allocation
and deallocation is automatic should you choose to do it that way
(less bugs, easier to maintain, a breeze to expand, debugging is much
easier).

#include <deque>

template< typename T >
class Container
{
std::deque< T > dt;
public:
Container( const std::size_t Size,
const T& t = T() ) : dt(Size, t) { }
typedef typename std::deque< T >::iterator iterator;

};

int main()
{
// don't blink
Container< double > container(10, 1.1);
Container< std::string > strings(100, "default");
Container< char > bytes(1000, 'a');

}

T must be copyable and assignable, as usual.
I am not sure what you are trying to say.
What purpose will this container will serve for me?
Probably you have replied without going through my mail.
Any code that says "store a bunch of blocks of memory each equivalent
to sizeof(myobj) and then ignore the type inserted in those blocks" is
a pure nightmare. If i say that the apple is an orange then its an
orange, i don't think so? Thats like buying insurance from an ice-
cream salesman.
Again not sure if you had gone through my email at all. For a memory
manager/ pool
it is not necessary to know the type(Though std allocators know, but
many doesn't).
And even many of them doesn't have luxury to know(eq malloc or new or
any heterogeneous memory
allocator).
I am developing a memory manager (or memory pool) for a fixed size
object.
Where objects will be frequently allocated & deallocated in any order.
I don't need a container at all.

Thanks for answering
 
C

Chris M. Thomasson

abir said:
I am interested to allocate and deallocate lots of objects of same
type (and of course size). As the deallocation will take place in
random order and also the maximum number of objects at any time is not
known (though i have a hint), i can't use a vector for this purpose.

Thus i developed a memory pool for fixed objects(an allocator).
i can make the pool as a template of object type or object size.
at present what i am doing is,
1)
template<size_t sz>struct mypool;
struct myobj;
mypool<sizeof(myobj)> pool(1024);///1024 -> typical pool size
void* ptr = pool.allocate();
myobj* obj = new(ptr)(x,y,z);////where x,y,z are myobj constructor
params.

similarly te destruction is done as,
obj->~myobj();
pool.deallocate(obj);

if i want to have a single step solution for them like
2)
template<typename T> struct mypool;
myobj* ptr = pool.create(x,y,z);
pool.drop(ptr);
Here he first step (ie create ) i can't write as i can't forward the
x,y,z to the class constructor.
I have to use a copy constructor like,
myobj* ptr = pool.create(myobj(x,y,z));
any myobj doesn't have one!.
[...]

You can indeed forward multiple arguments to class ctor. Look here for more
info:

http://groups.google.com/group/comp.lang.c++/browse_frm/thread/419bf7caebf53ac

Caveat, you have a problem with passing references. Template arguments seem
to deduce down to copy semantics instead of passing by reference. This can
be solved with a macro:



<pseudo-code!!!!>


template<typename T>
class allocator {
// [impl detail];

public:
void* allocate() {
void* mem = // impl detail;
return mem;
}

void deallocate(T* mem) {
mem->~T();
// impl detail
}
};



#define YOUR_NEW(a) new ((a)->allocate())


struct foo {
int a;

foo(int a_) : a(a_) {}
};


void foobar() {
allocator<foo> foo_alloc;
foo* f1 = YOUR_NEW(&foo_alloc) foo(1);
foo* f2 = YOUR_NEW(&foo_alloc) foo(2);
foo* f3 = YOUR_NEW(&foo_alloc) foo(3);
foo_alloc.deallocate(f3);
foo_alloc.deallocate(f2);
foo_alloc.deallocate(f1);
}




Problem, exceptions in ctor... How would you solve?



;^D
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top