intermodule_singleton fixes for many platforms:

- Use Boost.Container to allow debug-release mixed code (in some platforms, std:: containers' ABI changes from Debug to Release)

- By default non-Phoenix and Lazy singletons.

- Use atexit instead of the global object destructor to obtain LIFO semantics.

- Avoid testing Phoenix singletons, as in many plataforms calling atexit from atexit is not supported.
This commit is contained in:
Ion Gaztañaga
2014-07-14 23:34:17 +02:00
parent a3e766e635
commit 06eef6f4e8
5 changed files with 27 additions and 24 deletions

View File

@@ -31,7 +31,7 @@ namespace ipcdetail{
//Now this class is a singleton, initializing the singleton in
//the first get() function call if LazyInit is false. If true
//then the singleton will be initialized when loading the module.
template<typename C, bool LazyInit = true, bool Phoenix = true>
template<typename C, bool LazyInit = true, bool Phoenix = false>
class intermodule_singleton
#ifdef BOOST_INTERPROCESS_WINDOWS
: public windows_intermodule_singleton<C, LazyInit, Phoenix>

View File

@@ -364,9 +364,9 @@ class intermodule_singleton_impl
~lifetime_type_lazy()
{
if(!Phoenix){
atexit_work();
}
//if(!Phoenix){
//atexit_work();
//}
}
//Dummy volatile so that the compiler can't resolve its value at compile-time
@@ -413,9 +413,9 @@ class intermodule_singleton_impl
throw;
}
}
if(Phoenix){
//if(Phoenix){
std::atexit(&atexit_work);
}
//}
atomic_inc32(&rcount->singleton_ref_count);
ret_ptr = rcount->ptr;
}

View File

@@ -343,7 +343,7 @@ struct thread_safe_global_map_dependant<managed_global_memory>
} //namespace intermodule_singleton_helpers {
template<typename C, bool LazyInit = true, bool Phoenix = true>
template<typename C, bool LazyInit = true, bool Phoenix = false>
class portable_intermodule_singleton
: public intermodule_singleton_impl<C, LazyInit, Phoenix, managed_global_memory>
{};

View File

@@ -17,6 +17,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/container/string.hpp>
#if !defined(BOOST_INTERPROCESS_WINDOWS)
#error "This header can't be included from non-windows operating systems"
@@ -49,7 +50,7 @@ namespace intermodule_singleton_helpers {
// max and current semaphore count.
class windows_semaphore_based_map
{
typedef boost::container::map<std::string, ref_count_ptr> map_type;
typedef boost::container::map<boost::container::string, ref_count_ptr> map_type;
public:
windows_semaphore_based_map()
@@ -182,7 +183,7 @@ class windows_semaphore_based_map
{
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
map_type &map = this->get_map_unlocked();
map_type::iterator it = map.find(std::string(name));
map_type::iterator it = map.find(boost::container::string(name));
if(it != map.end()){
return &it->second;
}
@@ -195,7 +196,7 @@ class windows_semaphore_based_map
{
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
map_type &map = this->get_map_unlocked();
map_type::iterator it = map.insert(map_type::value_type(std::string(name), ref)).first;
map_type::iterator it = map.insert(map_type::value_type(boost::container::string(name), ref)).first;
return &it->second;
}
@@ -203,7 +204,7 @@ class windows_semaphore_based_map
{
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
map_type &map = this->get_map_unlocked();
return map.erase(std::string(name)) != 0;
return map.erase(boost::container::string(name)) != 0;
}
template<class F>
@@ -290,7 +291,7 @@ struct thread_safe_global_map_dependant<windows_semaphore_based_map>
} //namespace intermodule_singleton_helpers {
template<typename C, bool LazyInit = true, bool Phoenix = true>
template<typename C, bool LazyInit = true, bool Phoenix = false>
class windows_intermodule_singleton
: public intermodule_singleton_impl
< C

View File

@@ -47,20 +47,20 @@ class MyThrowingClass
};
template < template<class T, bool LazyInit = false, bool Phoenix = true> class IntermoduleType >
template < template<class T, bool LazyInit, bool Phoenix> class IntermoduleType >
int intermodule_singleton_test()
{
bool exception_thrown = false;
bool exception_2_thrown = false;
try{
IntermoduleType<MyThrowingClass, true>::get();
IntermoduleType<MyThrowingClass, true, false>::get();
}
catch(int &){
exception_thrown = true;
//Second try
try{
IntermoduleType<MyThrowingClass, true>::get();
IntermoduleType<MyThrowingClass, true, false>::get();
}
catch(interprocess_exception &){
exception_2_thrown = true;
@@ -71,15 +71,15 @@ int intermodule_singleton_test()
return 1;
}
MyClass & mc = IntermoduleType<MyClass>::get();
MyClass & mc = IntermoduleType<MyClass, true, false>::get();
mc.shout();
IntermoduleType<MyClass>::get().shout();
IntermoduleType<MyDerivedClass>::get().shout();
IntermoduleType<MyClass, true, false>::get().shout();
IntermoduleType<MyDerivedClass, true, false>::get().shout();
//Second try
exception_2_thrown = false;
try{
IntermoduleType<MyThrowingClass, true>::get();
IntermoduleType<MyThrowingClass, true, false>::get();
}
catch(interprocess_exception &){
exception_2_thrown = true;
@@ -222,7 +222,7 @@ class LogDeadReferenceUser
}
};
template < template<class T, bool LazyInit = false, bool Phoenix = true> class IntermoduleType >
template < template<class T, bool LazyInit, bool Phoenix> class IntermoduleType >
int phoenix_singleton_test()
{
typedef int DummyType;
@@ -254,7 +254,7 @@ int phoenix_singleton_test()
return 0;
}
template < template<class T, bool LazyInit = false, bool Phoenix = true> class IntermoduleType >
template < template<class T, bool LazyInit, bool Phoenix> class IntermoduleType >
int dead_reference_singleton_test()
{
typedef int DummyType;
@@ -280,13 +280,13 @@ int dead_reference_singleton_test()
}
//reduce name length
template<typename C, bool LazyInit = true, bool Phoenix = true>
template<typename C, bool LazyInit, bool Phoenix>
class port_singleton
: public ipcdetail::portable_intermodule_singleton<C, LazyInit, Phoenix>
{};
#ifdef BOOST_INTERPROCESS_WINDOWS
template<typename C, bool LazyInit = true, bool Phoenix = true>
template<typename C, bool LazyInit, bool Phoenix>
class win_singleton
: public ipcdetail::windows_intermodule_singleton< C, LazyInit, Phoenix>
{};
@@ -304,12 +304,15 @@ int main ()
}
#endif
//Only few platforms support this
#ifdef BOOST_INTERPROCESS_ATEXIT_CALLABLE_FROM_ATEXIT
//Phoenix singletons are tested after main ends,
//LogPhoenixTester does the work
phoenix_singleton_test<port_singleton>();
#ifdef BOOST_INTERPROCESS_WINDOWS
phoenix_singleton_test<win_singleton>();
#endif
#endif
//Dead reference singletons are tested after main ends,
//LogDeadReferenceUser does the work
@@ -322,4 +325,3 @@ int main ()
}
#include <boost/interprocess/detail/config_end.hpp>