Enginuity, Part II

Started by
8 comments, last by Skute 18 years, 7 months ago
Hi, ive been reading the enginuity part II article (http://www.gamedev.net/reference/articles/article1954.asp) and im wondering about the smart pointer section. Surely the point of a smart pointer is that when the reference count gets to zero, it automatically calls delete on itself? The way the enginuity guide suggests is having to call CollectGarbage() every time you want to free up some dangling memory. Wouldnt it be better to change the following:

// Enginuity
   ~CMMPointer()
   {
      if(obj)obj->Release();
   }

... to ...

// Change to...
   ~CMMPointer()
   {
      if(obj)obj->Release();

      if (obj->GetRefCount() <= 0)
        delete obj;
   }

Thanks,
Mark Ingramhttp://www.mark-ingram.com
Advertisement
It's been a while since I looked at Enginuity, but I'm fairly sure that the object itself deletes, or does whatever it does inside the Release function.

void IMMObject::Release(){   --refCount;   if(refCount<=0)   {      liveObjects.remove(this);      deadObjects.push_back(this);   }}


This is the code from the article, and as you see, the object itself decides whether its refCount is 0, and adds itself to the deadList.

Its one of the points of OO. If you need to manipulate the data of an object, the object should have a function that does it.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Yeah, the MMObject isnt responsible for deleting itself though, because its just a memory managed object, its not a smart pointer. but adding itself to the list of dead objects doesnt actually delete itself, it just adds it to a list of memory which hasnt been cleaned.

So i was thinking rather than having a list of dead objects, then having to call CollectGarbage, it would be better to just delete the pointer when the reference count gets to zero?
Mark Ingramhttp://www.mark-ingram.com
Is the outcome defined if you do "delete this"?
edit: misread your post and bad memory
I would guess that the coder/designer thought that doing release on a object should eventually kill it and not count it's reference down.

Perhaps another way of doing it would be that the IMMObject destructor removes itself from the dead object list. Might be a bit harder to do(iterating and removing from the same list) but it would (as I see it) satisfy both sollutions...
I think the point of the deadlist is that the deletion of 'dead' objects can be controlled by the user. For example, a managed particle class would mean lots of objects are deleted when they're released, potentially causing a framerate hit as all the deletions are processed. The 'CollectGarbage' method allows users to call 'delete' whenever they want, perhaps when there's not much happening in the game. However, the current system DOES suffer issues with this; entering a loop and deleting hundreds of objects per frame is costly, especially with the aforementioned particle system example. The system could be enhanced to take a 'WorkUnits' parameter, allowing the user to control how many objects are deleted in a single sweep (allowing small collections often without freezing the app). I'd also implement a freelist/block allocation scheme, so a list of each type of object is maintained and data isn't actually deleted, more like pushed onto a 'removed' stack to be reused when 'new' is called, thus avoiding a memory allocation and deletion altogether.

If you want to quickly acheive your goals, you could use boost::shared_ptr instead, which will automatically delete objects when hte internal refcount is zero - plus it's non-intrusive, unlike the Enginuity version.
I always thought it was perfectly legal, its just a strange thing todo. Heres a quote from a quick result in google:

Quote:
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.15

As long as you're careful, it's OK for an object to commit suicide (delete this).

Here's how I define "careful":

You must be absolutely 100% positive sure that this object was allocated via new (not by new[], nor by placement new, nor a local object on the stack, nor a global, nor a member of another object; but by plain ordinary new).
You must be absolutely 100% positive sure that your member function will be the last member function invoked on this object.
You must be absolutely 100% positive sure that the rest of your member function (after the delete this line) doesn't touch any piece of this object (including calling any other member functions or touching any data members).
You must be absolutely 100% positive sure that no one even touches the this pointer itself after the delete this line. In other words, you must not examine it, compare it with another pointer, compare it with NULL, print it, cast it, do anything with it.
Naturally the usual caveats apply in cases where your this pointer is a pointer to a base class when you don't have a virtual destructor.

Mark Ingramhttp://www.mark-ingram.com
Quote:Original post by evolutional
plus it's non-intrusive, unlike the Enginuity version.


how do you mean?

I was thinking about building in an option for the MMObject class, so that it can either have a list of dead objects or it could automatically free them.
Mark Ingramhttp://www.mark-ingram.com
Quote:Original post by Skute
Quote:Original post by evolutional
plus it's non-intrusive, unlike the Enginuity version.


how do you mean?


With boost::shared_ptr, you do not need to base any of your classes on it to take advantage of smart pointers. With the enginuity version, all of your garbage collected classes need to be based on the IMMObject class.
I'm too slow, this time I'm writing in notepad and updating explorer :)

Particle systems (and other intesive (runtime) allocation/deallocation) should IMHO use a internal deadlist and not rely on a global one. Personaly I think it's bad design if the particle manager goes around in the garbage collector.

I see, it may be legal to commit suicide, but I don't like it :)
So do you all think it would be better to have 2 types of pointer:

a) A smart pointer that deletes itself when needed
and
b) A garbage collected pointer that can be deleted whenever is convenient

?
Mark Ingramhttp://www.mark-ingram.com

This topic is closed to new replies.

Advertisement