diff options
author | Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl> | 2016-05-17 11:22:17 +0200 |
---|---|---|
committer | Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl> | 2016-05-17 11:45:28 +0200 |
commit | 73ad6a97531b6bc1d311eceb6ba2770fdf407b81 (patch) | |
tree | 94430d9945144b97e61e47d6f5424c2e777f556a /include | |
parent | d60df8bbd0e17016036c279720d6e3464a4d295c (diff) | |
download | astra-73ad6a97531b6bc1d311eceb6ba2770fdf407b81.tar.gz astra-73ad6a97531b6bc1d311eceb6ba2770fdf407b81.tar.bz2 astra-73ad6a97531b6bc1d311eceb6ba2770fdf407b81.tar.xz astra-73ad6a97531b6bc1d311eceb6ba2770fdf407b81.zip |
Avoid defining singleton construction in header file
That way, the call to new is always executed by code inside libastra.
This avoids the situation where a singleton gets created by a copy
of the constructor linked into an object file outside of libastra, such
as a .mex file, which would then also cause the vtable to be outside of
libastra. This situation would cause issues when .mex files are unloaded.
Diffstat (limited to 'include')
-rw-r--r-- | include/astra/Singleton.h | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/include/astra/Singleton.h b/include/astra/Singleton.h index a256187..1ef4bba 100644 --- a/include/astra/Singleton.h +++ b/include/astra/Singleton.h @@ -57,15 +57,17 @@ class Singleton { m_singleton = 0; } + static void construct(); + // get singleton static T& getSingleton() { if (!m_singleton) - m_singleton = new T(); + construct(); return *m_singleton; } static T* getSingletonPtr() { if (!m_singleton) - m_singleton = new T(); + construct(); return m_singleton; } @@ -76,11 +78,23 @@ class Singleton { }; -#define DEFINE_SINGLETON(T) template<> T* Singleton<T >::m_singleton = 0 +// We specifically avoid defining construct() in the header. +// That way, the call to new is always executed by code inside libastra. +// This avoids the situation where a singleton gets created by a copy +// of the constructor linked into an object file outside of libastra, such +// as a .mex file, which would then also cause the vtable to be outside of +// libastra. This situation would cause issues when .mex files are unloaded. + +#define DEFINE_SINGLETON(T) \ +template<> void Singleton<T >::construct() { m_singleton = new T(); } \ +template<> T* Singleton<T >::m_singleton = 0 + // This is a hack to support statements like // DEFINE_SINGLETON2(CTemplatedClass<C1, C2>); -#define DEFINE_SINGLETON2(A,B) template<> A,B* Singleton<A,B >::m_singleton = 0 +#define DEFINE_SINGLETON2(A,B) \ +template<> void Singleton<A,B >::construct() { m_singleton = new A,B(); } \ +template<> A,B* Singleton<A,B >::m_singleton = 0 } // end namespace |