summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWillem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>2016-05-17 11:22:17 +0200
committerWillem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>2016-05-17 11:45:28 +0200
commit73ad6a97531b6bc1d311eceb6ba2770fdf407b81 (patch)
tree94430d9945144b97e61e47d6f5424c2e777f556a
parentd60df8bbd0e17016036c279720d6e3464a4d295c (diff)
downloadastra-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.
-rw-r--r--include/astra/Singleton.h22
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