Boost logo

Boost Users :

Subject: [Boost-users] shared_ptr singleton
From: Alessandro Re (akirosspower_at_[hidden])
Date: 2008-10-16 15:08:01

I'm getting some troubles with shared_ptr when trying to implement a
singleton pattern.
Actually, it's not the singleton itself (which seems to work, in a
separate program), but in the context I need it, doesn't work.

I tried to figure out why (and actually I found an alternative
implementation which works), but still I'm trying to understand what
goes wrong.

I'm trying to do this:
having a hierarchy of classes where there is one Base class and a
number of derived ones, each class is in a different cpp file.
All these classes must be registered in a Register class, which is
itself derived from Object.
Register is the singleton, implemented like this:

class Register;
typedef shared_ptr<Register> RegisterP;
class Register: public Object {
        void add(string name) {
                // Stuff with name
        static RegisterP global() {
                if (!_global) _global = RegisterP(new Register); // *
                return _global;
        static RegisterP _global;

To register the various classes, does exist a special class, not in
hierarchy, like this:

class ClassRegisterer {
        ClassRegisterer::ClassRegisterer(string name) {
                // **

#define REGISTER(C) ClassRegisterer _registerClass_ ## C ( #C)

In each file of the of the project, this macro is used when a class is created:

class Foo: public Object {...};

class Bar: public Object {...};

This is also used for the Register class itself:

class Register: public Object {...};

The problem is that global() is called N times, but the new Register
(*) is executed twice, instead of once.
Investigating with some couts, I found out that - dunno why - the
pointer _global is set to 0 after the first execution,
in fact at the time of second execution it's created another object,
which isn't deleted and is kept.

Trying quickly with a debugger, it seems that at (**) a destructor for
shared_ptr is called,
and I think that it may be the cause of the issue, but I'm having an
hard time figuring this out and *why* a destructor is called (maybe
it's just for a temporary object).

Looking at boost docs, i found out this:
so I tried to use that null deleter, like this:

struct nullDeleter {
        void operator()(void const *p) const {
                cout << "Trying to delete " << p << endl;

and used like:
                if (!_global) _global = RegisterP(new Register, nullDeleter());

The problem is that this is never called! The object is never
destroyed by this, but somehow the static _global is set to 0 (only
once), and thus allocated twice.

I temporary solved this using a static raw pointer, which is allocated
once and a shared_ptr is built with it:

class Register {
        static RegisterP global() {
                if (!_global) _global = new Register;
                return RegisterP(_global, nullDeleter());
        static Register *_global;

Which works.

Any suggestion is welcome :)



Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at