Nicola Musatti wrote:
Within the singleton class I hold the instance with a shared_ptr. I
consider this the best option, as it guarantees the correct order of
destruction when a singleton depends on another one.
But I *want* it to be delete automagically...and I do not see the
danger: if there is a dependent second_singleton it would hold a
shared_ptr to my singleton, and singleton would not be destroyed before
second_singleton is destroyed by its own. Maybe it should be made an
option by using policies....but I really do not the danger.
You should rely on the constructor that takes an additional deleter
argument, something like (not compiled and almost certainly incomplete
and incorrect):
class SingletonDeleter {
friend class shared_ptr<Singleton>;
operator() (Singleton *p) { delete p; }
};
class Singleton {
friend class SingletonDeleter;
public:
shared_ptr instance() {
if ( inst == 0 )
inst = shared_ptr (
new Singleton,SingletonDeleter());
return inst;
}
};
typedef shared_ptr SingletonPtr;
Yes, I fear it *is* incorrect ;) look at the bottom of the posting for
my implelentation
Declaring the destructor as private is only possible when defining
boost::checked_delete as friend of the singleton-class.
[...]
But then it is still possible to write the following code
singleton::singleton_ptr first_ptr = singleton::instance();
boost:checked_delete( first_ptr.get() );
OK, it's very unlikely to do it by chance, but it is possible.
Moreover, you rely on what should be an implementation detail.
OK, I hope that this will be the correct way:
* I do not rely on implementation-detail ( make boost::checked_delete a
friend )
* I provide my own deleter-functor
<code>
#include
#include
#include
class singleton : boost::noncopyable
{
public:
typedef boost::shared_ptr< singleton > singleton_ptr;
static singleton_ptr instance()
{
singleton_ptr tmp;
if( s_instance.expired() )
{
tmp.reset( new singleton, checked_deleter() ); // <-- NEW!!!
s_instance = tmp;
}
else
{
tmp = boost::make_shared( s_instance );
}
return tmp;
}
void foo()
{
// do something
i++;
}
private:
// NEW !!!!
struct checked_deleter
{
operator() ( singleton * p_ )
{
// does the same as boost::checked_delete from BOOST 1.28.0
typedef char type_must_be_complete[ sizeof( p_ ) ];
delete p_;
}
};
friend struct checked_deleter;
typedef boost::weak_ptr< singleton > internal_singleton_ptr;
singleton(){};
~singleton(){}; // NOW IT'S PRIVATE !!!
int i;
static internal_singleton_ptr s_instance;
};
singleton::internal_singleton_ptr singleton::s_instance;
int main()
{
{
singleton::singleton_ptr first_ptr = singleton::instance();
{
singleton::singleton_ptr second_ptr = singleton::instance();
second_ptr->foo();
}
first_ptr->foo();
}
singleton::singleton_ptr another_ptr = singleton::instance();
// OK, these things do not work anymore.....
//delete( another_ptr.get() );
//boost::checked_delete( another_ptr.get() );
//singleton::singleton_deleter deleter();
//deleter( another_ptr.get() );
another_ptr->foo();
return 0;
}
</code>
--
---------------------------------------------------------------
Dipl.-Inf. (FH) Stephan Born | beusen Solutions GmbH
fon: +49 30 549932-0 | Landsberger Allee 366
fax: +49 30 549932-21 | 12681 Berlin
mailto:stephan.born@beusen.de | Germany
---------------------------------------------------------------
PGP-Key verfügbar | PGP-Key available
---------------------------------------------------------------