How can an object ask to be deleted?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • emibt08
    New Member
    • Oct 2008
    • 25

    How can an object ask to be deleted?

    I have a class, say Container which contains objects of another class, for example MyObject. MyObject does some processing, and in some future time it is no longer needed. Hence, it should somehow tell to the Container about it. I currently do something like this:

    Code:
    class MyObject
    {
    public:
    	typedef void(*PFN)(void*,MyObject*);
    	MyObject(void* param, PFN p) : m_param(param), m_pfn(p) {}
    	// some other functions
    	
    private:
    	void Done() { m_pfn(m_param, this); }
    	
    	void* m_param;
    	PFN	m_pfn;
    };
    
    class Container
    {
    public:
    	Container()
    	{
    		// ...
    		// just an example
    		for (int i = 0; i != 100; ++i)
    		{
    			MyObject* pobj = new MyObject(this, MyObjectCallback);
    			m_Vector.push_back(pobj);
    		}
    	}
    	
    	// other functions...
    	
    static DWORD WINAPI MyObjectCallback(void* p, MyObject* pobj)
    {
    	Container *pThis = (Container*)p;
    	
    	pThis->lockVector();
    	vector<MyObject*>::iterator it = pThis->m_Vector.begin();
    	while (it != pThis->m_Vector.end())
    	{
    		if (*it == pobj)
    		{
    			delete *it;
    			pThis->m_Vector.erase(it);
    			break;
    		}
    		else
    			++it;
    	}
    	pThis->unlockVector();	
    }	
    
    private:
    	vector<MyObject*> m_Vector;
    };

    I could create a thread in the Container class and poll the objects, which can provide something like: bool DoneProcessing( ) and then can be deleted, but i believe it may be a worse solution.
    So, I wonder if it's safe to do the things the way i do: deleting the object in the callback function that it called, or maybe there is a better solution that i haven't thought of...

    Thanks in advance
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Get a book on Design Patterns and look up the Observer pattern.

    The Observer pattern uses the "notify" concept for an object to notify any "observers" that it's contents have changed.

    This sounds like your situation.

    Comment

    • emibt08
      New Member
      • Oct 2008
      • 25

      #3
      Thanks for the reply... however, after checking the observer pattern a little better, I doubt it applies here. I could use it to notify the main thread that the object is finished with the processing, but with that pattern i may have more than 1 observer. In my case, I have only one, so it's not a problem, but if i had more and the 1st deleted the object, then i suppose the object can't notify the others (or i am not even sure what will happen).

      However, the problem is simply.. how can an object tell to another onject to delete it?
      Like, in my case MyObject calls the callback that was provided to it and calls it. But in that call the callee wants to delete the MyObject. I have tested this and succeeds, whether it is a coincidence or not.
      In my understanding, when a function is called it puts it's address on the call stack and everything, but isn't that address invalidated when i delete the object?

      It's like this:

      Code:
      Container *pCont = new Container();
      MyObject *pObj = new MyObject();
      pObj->setCallback(pCont->CallBack);
      pCont->add(pObj);
      // after some time, in some function of MyObject, pObj does:
      Code:
      {
          pFunc(this);
      
          // I suppose the control will never come to this point,
          // because of what happens in the callback....
          // however, in the debuger it does...
      }
      // which calls the callback:
      Code:
      Container::CallBack(MyObject *sender)
      {
          delete sender;
      }
      I suppose it's like calling "delete this" from some function in MyObject (which i don't know if it is completely valid to do, although i know i can do it and works)

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        An object can have multiple observers.

        Usually, the observers register themselves with a Mediator (another pattern) and the Mediator notifies all observers when the object call its Notify() method.

        All you have to do is pass a message in your Notify() requesting the desired action, like delete this object.

        Comment

        • jhumelsine
          New Member
          • May 2010
          • 9

          #5
          As simple as it sounds, I don’t think you can directly do what you want. For example, an object cannot commit suicide, i.e., it can’t delete itself. What would happen to the thread?

          For much the same reason, your component cannot ask its container to delete it. The thread would be going from the component to the container where the container would delete it and then back to … what?

          Asking another object to delete the caller is like kicking the ladder out from underneath the object being called to do the deleting.

          About the best you can do is mark the component for deletion and let another thread clean it up. That thread could be a “maintenan ce” thread in the container, which deletes marked objects. Or it could be a callback thread, which is kind of what you described. The callback works, because they are often separate threads. So while your component commences the callback through a notification, it’s probably not the thread that implements the callback. This allows the container to clean up the marked component without having the rug pulled out from under its feet.

          If this still doesn’t sound like a clean implementation, consider how garbage collection works. Objects are marked for clean up when they have no pointers to them, and then the garbage collector, on a separate thread, looks for them and releases their resources. This is basically what Java does: http://www.javaworld.com/javaworld/j.../jw-08-gc.html

          Comment

          Working...