Garbage Container in C++

Started by
29 comments, last by stefu 22 years ago
What's best way to do garbage container in c++. No smaprtpointers. Just keep track of referencecount.
      
list<Object *> alive;
list<Object *> dead;

class Object 
{
private:
    int ref_c;

public:
    Object() : ref_c(1) { alive.push_back(this); }
    virtual ~Object() {}

    void delRef() { 
        ref_c--;
        if (!ref_c) {
            alive.remove(this);
            dead.push_back(this);
        }
    void addRef() { ref_c++; }
}
    
This should keep track of objects that are alive and that should be deleted. Then frequently I need to delete all object in dead-list and empty it.
  
void emptyCarbage()
{
    list<Component*>::iterator it = dead.begin();
    list<Component*>::iterator last = dead.end();
    while (it != last) {
        delete (*it++);
    };
    dead.empty();
}
      
What do you think about this? Is it possible/smart to create separate thread for emptying dead objects periodically? I haven't yet implemented this because I have quite a big system I'd like to have clean and safe carbage collection. So I don't want to do this before I know it works ok. Thanks for any ideas Edited by - stefu on March 19, 2002 7:55:35 AM
Advertisement
Personally, I think this is a somewhat misguided attempt to instil GC into C++. GC is a hugely complex undertaking, and you are simplifying it to the extreme. My first piece of advice would simply be don''t do it! If you feel you must do this, then Google for existing GC systems.

The technique you are using makes it very easy to bypass the GC system, as it requires everything to inherit from Object (one of my pet hates in C++). You''re requiring C++ programmers using your framework to adhere to a rigorous and unnatural discipline just to make your GC work.

Also, what happens in the following sort of scenario:

std::vector *p_v = new std::vector; 


?
I think you are overshooting what I meant.
It''s not meant to be for all objects, like it''s in Java.

Just for example for GUI compoenents to be able to have multiple references, keep track of reference count and delete components when they''r not required anymore.
Have you looked at the reference counting pointer that is implemented in the the tutorial here on gamedev.net? I made my own implementation based on that tutorial(ie copy paste, change a few names and im gonna use it for the exact same thing you are, handling when to delete GUI components(and other components that are thrown around between modules).
The reference counting pointer they implement actually handles all reference counting, so you dont have to depend on yourself or other programmers to remember calling removeRef.
The only thing it cant handle is circular references, ie if Object1 holds a ref to Object2 and object2 has one to Object1 they will never get deleted, but that shouldnt be an issue with GUI components(at least now the way mine are implemented).

The URL is http://www.gamedev.net/reference/articles/article1060.asp
have a look at it.

[edited by - ziphnor on March 19, 2002 9:16:41 AM]
Quick look at it and it looks pretty good.
It''s using templates, I have to take a deeper look at it.

Thanks.
Ive played a little around with it, and now im trying to find ways to "break" it, ie obtaining the pointer from the ref.counting pointer and copying it without the ref being counted.

So far it surprised me that i could pass a managed pointer like this to a method that took a normal pointer.
I think it may have have defined a conversion from managed pointer to normal pointer. But what is to stop the method called from doing bad things(like copying the real pointer) now that it has the pointer?

EDIT: He defines the following conversions:

    /** Conversion operators */     operator T*       () const { return m_ptr; }     operator const T* () const { return m_ptr; }  

They seem a bit unsafe to me, sure it allows me to pass a managed pointer instead of a normal one, but then the pointer is lose, and just as unsafe as before, isnt it?

EDIT END <-

I was expecting to change methods like paint(GraphicsManager* gm) to paint(ManagedPointer gm).(i would probably make a typedef)

Well, ill give you a chance to have a better look at it, so we can find out exactly how useful it is.

Personally i understand templates and operator overloading well enough, but operator overloading confuses me a litle with regards to return values.

[edited by - ziphnor on March 19, 2002 10:08:36 AM]
This is actually smart pointer. While ago I looked at one implementation of smartpointers and it was so messy I ignored them as not being usable. This seems quite a clean.

quote:Original post by Ziphnor
I was expecting to change methods like paint(GraphicsManager* gm) to paint(ManagedPointer gm).(i would probably make a typedef)

That''s what I was too thinking, to use typedefs


  class Test : public RefCntObject{};typedef RefCntPointer<Test> sTest;// usagesTest p;  


What would be good naming conventions. post-''s'' for ''smart'' to know it''s smartpointer?
/** Conversion operators */
operator T* () const { return m_ptr; }
operator const T* () const { return m_ptr; }

Where do you actually need these?
Just had a look in the book "C++ for real programmers" by Jeff Alger which provides a similar implementation, but he never defines such conversion operators.

I guess they are provided for the managed pointer to be directly compatible with code that wants a normal pointer, but doing so kind of makes the whole exercise futile....

Anyway, Jeff Alger has one more trick, he makes the constructor private and instead provides a make() method that returns a managed pointer, so there is now way at all to retrieve a pointer to the managed object(perhaps apart from dereferencing it and then using & to obtain it), but that can be avoided by not supporting the dereference operator *).

As for your typedef im doing something similar, just using mp(ManagedPointer) as prefix.

    I actually developed problem with it.// Before I had thisclass Component{  // add any kind of component  void add(Component *c);}class Panel: public Component{};class Button : public Component{};I could add buttonsPanel *p = new Panel;Button *b = new Button;p->add(b);But this doesn't work with smartpointer :(class Component{  // add any kind of component  void add(sComponent c);  void add(sButton c); // Do need separate function for each component???   }typedef RefCntPointer<Component> sComponent;class Panel: public Component{};typedef RefCntPointer<Button> sButton;class Button : public Component{};typedef RefCntPointer<Button> sButton;sPanel p = new Panel;sButton b = new Button;p->add(b); // need add-procedure for each kind of component???     






[edited by - stefu on March 19, 2002 10:50:51 AM]

This topic is closed to new replies.

Advertisement