|
Boost Users : |
From: Stephan Born (yg-boost-users_at_[hidden])
Date: 2002-10-08 11:14:20
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<Singleton,SingletonDeleter> instance() {
> if ( inst == 0 )
> inst = shared_ptr<Singleton,SingletonDeleter> (
> new Singleton,SingletonDeleter());
> return inst;
> }
> };
>
> typedef shared_ptr<Singleton,SingletonDeleter> 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 <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/utility.hpp>
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_at_[hidden] | Germany --------------------------------------------------------------- PGP-Key verfügbar | PGP-Key available ---------------------------------------------------------------
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net