Robert Ramey wrote:
So trap on this line and verify that
singletondetail::ktmap::is_destroyed() is not true
then trap on the destructor of singletondetail::ktmap::is_destroyed() to
verify that
m_is_destroyed is in fact getting set when the table is destroyed.
The detail::ktmap is getting destroyed *before* the singleton
that holds it. So is_destroyed() returns false... but that's wrong.
Does the standard guarantee that the static T that is inside
singleton<T>::get_instance() will be destroyed *after* the singleton<T>
itself? It seems like the compiler could figure out that the singleton<T>
never actually talks to the static T inside get_instance(), ie. it looks
like it would be pretty easy to figure out that use() doesn't do anything
and get rid of it entirely.
I put together a fix which works... not sure what I think of it.
Singletons inherit from a singleton_instance class that notifies the singleton (!)
of its destruction. Looks like this:
in extended_type_info.cpp, detail::ktmap is no longer a typedef:
struct ktmap : std::multiset,
singleton_instance<ktmap>
{ };
and in singleton.hpp, you've got this:
template <class T>
class singleton_instance;
template <class T>
class singleton : public singleton_module
{
static bool m_is_destroyed;
BOOST_DLLEXPORT static T & instance;
// include this to provoke instantiation at pre-execution time
static void use(T const &) {}
BOOST_DLLEXPORT static T & get_instance() {
static T t;
// refer to instance, causing it to be instantiated (and
// initialized at startup on working compilers)
assert(! m_is_destroyed);
use(instance);
return t;
}
BOOST_DLLEXPORT static void destroy() { m_is_destroyed = true; }
public:
BOOST_DLLEXPORT static T & get_mutable_instance(){
assert(! is_locked());
return get_instance();
}
BOOST_DLLEXPORT static const T & get_const_instance(){
return get_instance();
}
BOOST_DLLEXPORT static bool is_destroyed(){
return m_is_destroyed;
}
~singleton(){
m_is_destroyed = true;
}
friend class singleton_instance<T>;
};
template<class T>
BOOST_DLLEXPORT T & singleton<T>::instance = singleton<T>::get_instance();
template<class T> bool singleton<T>::m_is_destroyed = false;
template <class T>
class singleton_instance
{
public:
~singleton_instance() { singleton<T>::destroy(); }
};
What do you make of all this?
-t