Search code examples
c++c++11smart-pointersobject-persistence

How to delete instance of persistent object when last client has finished


I'm trying to implement an object persistence model in C++. The idea is that there is a Database object that acts as a factory for various PersistentObjects, each of which being associated with a row in a database table. The Database has a method like this:

PersistentObject *Database::GetObject(int ID);

This returns a pointer to an object with the ID number supplied (or a null pointer if the ID doesn't exist). In the Database class, there is also a map of all PersistentObjects that have been created:

std::map<int, PersistentObject*> _objectMap;

Internally, GetObject does one of two things:

  1. If this is the first time the PersistentObject with the ID has been requested then it queries the database, constructs a new instance of PersistentObject based on the result, inserts that object address into the map(with the ID as the key) and returns a pointer to the new object.

  2. If the PersistentObject has previously been loaded (i.e. the ID already exists as a key in the map), it just returns a pointer to that object.

The reason for keeping track of the PersistentObjects centrally is that I have another thread that continually polls the database for changes to loaded PersistentObjects and sends an event to any object that is out of date.

What I want to be able to do is garbage-collect the central object map in Database so that when there are no remaining references to a particular object in the client code, the object is removed from the map and deleted, and is no longer checked by the update monitoring thread.

I thought of doing this with shared_ptr, but the problem is if that I use a shared_ptr in the map, then the reference count never gets to zero even when the object is no longer in use. I can't keep a traditional pointer to the PersistentObject in the map and create multiple shared_ptrs from it.

Does anybody know of a way to do this? I almost need a shared_ptr that will call the deleter when the reference count gets to 1 rather than 0. Or is there a better way to achieve what I'm trying to do?


Solution

  • Best way should be to return a shared_ptr to the Client but to store a weak_ptr in your map. weak_ptr do not increment the reference count and can easily produce more shared_ptr using lock(). You will have to watch your objects for expiration though, except you implement a custom deleter that cleans up the "dead" reference.