|
Boost Users : |
Subject: [Boost-users] shared_ptr singleton
From: Alessandro Re (akirosspower_at_[hidden])
Date: 2008-10-16 15:08:01
Hello,
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 {
public:
Register();
void add(string name) {
// Stuff with name
}
static RegisterP global() {
if (!_global) _global = RegisterP(new Register); // *
return _global;
}
private:
static RegisterP _global;
};
To register the various classes, does exist a special class, not in
hierarchy, like this:
class ClassRegisterer {
public:
ClassRegisterer::ClassRegisterer(string name) {
Register::global()->register(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:
Foo.cpp
class Foo: public Object {...};
REGISTER(Foo);
Bar.cpp
class Bar: public Object {...};
REGISTER(Bar);
This is also used for the Register class itself:
Register.cpp
class Register: public Object {...};
REGISTER(Register);
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:
http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html#static
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 :)
Thanks
-- ~Ale
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