2

I simply want a class that does this:

class cleanup : boost::noncopyable
{
 public:
  typedef boost::function0<void> function;
  explicit cleanup( function f ) : func( f )
  {
  }

  ~cleanup()
  {
    func();
  }
  private:
    function func; 
};

The purpose being that I have this "cleanup" to invoke func when it is deleted. cleanup will be passed around as a shared_ptr.

I have considered also doing it using a custom deleter in boost::shared_ptr. Perhaps I could use boost::shared_ptr and just create with NULL and get func() to take a parameter that it ignores.

The purpose of this all is to abstract out a step I want the class's destructor to perform when the last reference goes out of scope (actually remove itself from the container that holds it without the class having to know about its container).

If I do it with shared_ptr I would possibly pass around one of these:

boost::shared_ptr<void> cleanupObj( NULL, func );

Here the func must take a parameter. I am not 100% sure even that the deleter will always get called if the pointer is NULL so perhaps I need to use a different pointer which makes it start getting "messy" looking.

Is there a standard way to handle this and if not what is the best way?

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • 1
    What exactly do you need this for? Please give an example of what `func()` might do that you can't just do by using the destructors of existing objects. – Karl Knechtel Dec 06 '10 at 12:17
  • I was going to originally just create the class to do what I wanted and extract it, then realised wrapping in a boost::function at the time I create it will enable me to keep private things private, then thought just exactly how generic it all is. The item that holds the func() is an item in a container that should not have a dependency on the container it is in. When the item is no longer needed it will get removed from the table. The table itself stores a weak_ptr as its reference. – CashCow Dec 06 '10 at 12:27
  • From your description it sounds like you are trying to do something which might not be such a good idea. Maybe if you share your problem you will get better answers, and a better way to solve it. – Daniel Lidström Dec 06 '10 at 12:35
  • @Daniel Lidstrom. The only thing I need to ensure I manage is all the race conditions but I want an item to be removed from a collection when there is nothing accessing it. I am thinking now actually that for race conditions using the destructor is not a good idea as you cannot "back out" of a destructor after double-checking. I need something that has the logic: if (refcount==0) lock; if (refcount still == 0 ); remove_item; unlock; Of course this could happen in each users individual destructor but not in the shared one because sometimes it won't get deleted after all. – CashCow Dec 06 '10 at 12:49
  • 1
    It sounds like you are trying to implement some kind of cache. Am I correct? If so, then perhaps you can prune the cache when you retrieve items from it. If performance is critical then you can prune every X retrieval. – Daniel Lidström Dec 06 '10 at 13:09
  • I am implementing a kind of cache. The removal I am referring to is an "object in use" logic. I now actually think the "thread-safe" approach to the above is 2 nested objects of the above type. The inner "func" just does the removal. The outer "func" locks, reduces the reference count of the shared_ptr of the inner object which invokes the func when it goes out of scope, then unlocks. – CashCow Dec 06 '10 at 13:24

1 Answers1

2

I believe that there is a Scope Exit library within Boost. However, why not just use the code you wrote in the OP? And, typically, if you have a class within a container, make the container's owner dish out the references and handle what happens when there are none left.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • That is exactly what func() is there to do: the container's owner creates that to "handle what happens when there are none left". i.e. remove the item from the container. – CashCow Dec 06 '10 at 12:35
  • I looked at Scope Exit and it is not really what I am looking for as I am looking into something happening at class scope, not function / block scope. Scope Exit is there to automatically produce RAII objects for you within the scope of a function. – CashCow Dec 06 '10 at 13:05
  • The part "just use the code I wrote in the OP" seems the best idea. Given that none of the experts have jumped in and said the standard boost way to do it, I presume there isn't one. I am therefore accepting this answer. – CashCow Dec 06 '10 at 14:32
  • Actually I found that in our code base another developer had had the same idea, also looked in boost, found nothing and written one too. Our code has been "merged" into one solution. boost sort-of provides this with deleters in shared_ptr and unique_ptr – CashCow Feb 15 '11 at 11:56