Hello stack overflowers, I have a desing that uses the flyweight pattern to share bitmaps that are shared between bitmap objects which manage drawing ops, etc. and integrate in the gui library. This is an embedded device so memory is at a premium. Currently I have done a working implementation with a std::vector of auto_ptr of a light class that counts usage. I know this is a bad idea and may leak, so I'm rewriting this part. I'm considering using boost::shared_ptr. The key of my question is that I'd like the bitmaps to be released if there are not being used. If I have a pool of shared_ptr I end up with the used bitmaps loaded once. I'm considering using shared_ptr::use_count() to delete the bitmap if use_count() == 1. But the docs warn against production code of use_count(). Basically the question is flyweight pattern with releasing of individual heavy objects. Do you think there's a better way to do this?
The idea of shared_ptr is that it manages the object lifetime for you. You shouldn't have to check the use count. Have one shared_ptr per user, remove the shared_ptrs when you remove users, and when there are no more users left, it will delete the bitmap for you. If you have a special routine that you need to call to delete the bitmap and can't just do that in the destructor, you can pass a special deleter function to the shared_ptr on creation.
You could use a pool of boost weak pointers so that the pool does not count in the ownership.
Only the bitmap objects have boost shared pointers, this way they decide when to release the bitmaps.
The pool of weak pointers allows us to retrieve the already constructed bitmaps :
When you create a bitmap object you either :
get a shared pointer from the weak pointer if it is not empty,
or otherwise load the new bitmap, make a new shared pointer from it and insert/replace the weak pointer in the pool.
Here is some sample code using a map for the pool :
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <map>
#include <string>
#include <iostream>
// represents the bitmap data
class Bitmap
{
public :
Bitmap( std::string const& name ) : name( name )
{
std::cout << "Bitmap " << name << std::endl ;
}
~Bitmap()
{
std::cout << "~Bitmap " << name << std::endl ;
}
std::string name ;
};
// the flyweight pool
class Factory
{
public :
typedef std::map< std::string , boost::weak_ptr< Bitmap > > Map ;
boost::shared_ptr< Bitmap > get( std::string const& what )
{
Map::iterator x = map.find( what );
// retrieve existing object from map's weak pointers
if( x != map.end() )
{
if( boost::shared_ptr< Bitmap > shared = x->second.lock() )
{
return shared ;
}
}
// populate or update the map
boost::shared_ptr< Bitmap > shared( new Bitmap( what ) );
boost::weak_ptr< Bitmap > weak( shared );
map.insert( std::make_pair( what , weak ) );
return shared ;
}
private :
Map map ;
};
int main(int argc, char** argv)
{
Factory f ;
// we try our flyweight bitmap factory ...
boost::shared_ptr< Bitmap > a = f.get( "a" );
boost::shared_ptr< Bitmap > b = f.get( "b" );
// a is not made again
boost::shared_ptr< Bitmap > a2 = f.get( "a" );
a.reset();
a2.reset();
// a is destroyed before ------
std::cout << "------" << std::endl ;
}