Archived

This topic is now archived and is closed to further replies.

Template Delete

This topic is 5450 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hello! I have some plans for a engine. After reading through superpig''s great articles I figured that I''d need some kind of MemoryManagemanet. I didn''t want every object to have a common baseclass, rather that any created class without modification would be useable. I thought refcounting would be easiest to implement. After trial and error, I came up with this.
template<typename T>
struct Node
{
T data;
Node<T> * next;
};

inline void * operator new(size_t size)
{
if(!size)size++;
Node<unsigned int> * node = (Node<unsigned int> *)malloc(size + sizeof(Node<unsigned int>));
node->data = 0; // References

return (void*)((int)node + sizeof(Node<unsigned int>));
}

template<typename T>
void Delete(T * data)
{
Node<unsigned int> * ptr = (Node<unsigned int> *)((int)data - sizeof(Node<unsigned int>));
data->~T();
free(ptr);
//free(data) screws the memory up

}

{
Node<unsigned int> * node = (Node<unsigned int> *)((int)ptr - sizeof(Node<unsigned int>));
node->data++;
}

void Release(void * ptr)
{
Node<unsigned int> * node = (Node<unsigned int> *)((int)ptr - sizeof(Node<unsigned int>));
node->data--;
}

The objects would all be freed from some Registry class, no delete calls would be allowed. Now my questions are: (1)Are objects really freed when using free() on the ptr pointer? I know that the destructor is called, but is the whole memory block made free? (2)Is 2 byte too expensive for every object? There are some trouble when pointing to a arrayed object, but still... Sorry for a confusing post

Share on other sites
A pointer is 4 bytes, not 2

Share on other sites
Oh yea, I meant 8 byte, pointer + unsigned int

Share on other sites
You can overload the delete operator too, and make it dec the reference count until it reaches zero (then really delete the object).

Share on other sites
Oh yes, but I made it this way, since I need to get the size of the deleted object(planning on implementing a mem pool too), cause one can't get the size from delete(void * ptr). Anyway, the delete syntax wouldn't matter, I was going to let the GC do that job.

But is this a good aproach?

EDIT: Ahh, I'm on a LAN right now, so my mind is quite messy...

[edited by - SajberToffe on October 22, 2003 10:58:48 PM]

Share on other sites
What are these objects that you are reference counting? Typically, it only make sense to reference count "heavy" concrete objects, or specific references exposed by interfaces on a concrete object. Thus, you''d reference count the IPropertyCollection of some IEntity, but you wouldn''t reference count each CIntegerValue you get out from that collection, instead declaring the the CIntegerValue is live as long as the owning collection is live, using using copy semantics (likely for the integer property case).

Once you decide that you only reference count interfaces, having all interfaces derive (virtually?) from a single base interface, a la IUnknown in COM, makes reference counting mostly trivially implementable in that base class.

I also don''t like it the way you chain all your objects in a big linked list -- how would you delete an object from the list in an efficient manner? In your current version, the first object that you delte makes following the list be a crashing proposition. You need a doubly linked list (2 pointers, plus ref count) to accomplish that, and the value is dubious. Much better to hook in on the lower level and override operator new to allocate out of your own arena where you can dump allocated blocks. Then you can also easily do pooled allocations (allocate clumps of N objects at a time and dole them out 1 by 1).

Share on other sites

I guess you''re right... The objects that are reference counted are every object that''s on the heap, stacked variables won''t cause any memory leak. Yet, to assign 8 or 12(if I changed to a doubly-linked list) bytes for every object might be unnessasary. Perhaps I''ll find a better way of doning it.

Share on other sites
quote:
A pointer is 4 bytes, not 2

No, a pointer is sizeof(void*) bytes.

Share on other sites
Having a hard time with your code.

How does this

Like-wise
node->data--; remove one?

Please tell me your not expecting the type T to overide ++,-- to do the reference couting for itself.
Horrid design.

If you want it to be a generic memmory manager make it generic by not enforcing anything.

I think most (if not all, but not sure) standard containers dont even force the type to be default constructible.

Personally, i would just use std::list of some smart ptr to T.

Maybe theres a way to make a custom allocator that uses boost :: pool for said list. But i never used pool so it might be more trouble than its worth

Just my 2c
Amnesty

[edited by - Amnesty on October 23, 2003 3:55:13 AM]

Share on other sites
The size of the allocation is the size of the object + the size of a node. The Node is placed just before the object. The Node is just containing the references, that''s the data member(data = unsigned short), and that is increased, nothing in the class. The Node contain Pointers to other allocated objects, that are linked so GC can check references.
No pointer to the object it''s refering to is required, since it''s address is just after the node.

About STL, your right... It''s just a bad habbit, but I had some trouble learning the concept of linked list when I started. I made a couple of linked lists and that has just stuck so now my own imlpementations are easy and clear to me... maby a bit faster too

1. 1
2. 2
3. 3
Rutin
18
4. 4
JoeJ
14
5. 5

• 14
• 10
• 23
• 9
• 32
• Forum Statistics

• Total Topics
632630
• Total Posts
3007521
• Who's Online (See full list)

There are no registered users currently online

×