summaryrefslogtreecommitdiff
path: root/boost/interprocess/detail/intermodule_singleton_common.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/interprocess/detail/intermodule_singleton_common.hpp')
-rw-r--r--boost/interprocess/detail/intermodule_singleton_common.hpp61
1 files changed, 33 insertions, 28 deletions
diff --git a/boost/interprocess/detail/intermodule_singleton_common.hpp b/boost/interprocess/detail/intermodule_singleton_common.hpp
index 0710c0bbc1..10c9eceabb 100644
--- a/boost/interprocess/detail/intermodule_singleton_common.hpp
+++ b/boost/interprocess/detail/intermodule_singleton_common.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
-#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#if defined(_MSC_VER)
#pragma once
#endif
@@ -20,8 +20,10 @@
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/exceptions.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/sync/spin/wait.hpp>
#include <boost/assert.hpp>
#include <cstddef>
#include <cstdio>
@@ -121,7 +123,8 @@ class intermodule_singleton_common
//Now try to create the singleton in global map.
//This function solves concurrency issues
//between threads of several modules
- void *tmp = constructor(get_map());
+ ThreadSafeGlobalMap *const pmap = get_map_ptr();
+ void *tmp = constructor(*pmap);
//Increment the module reference count that reflects how many
//singletons this module holds, so that we can safely destroy
//module global map object when no singleton is left
@@ -144,6 +147,7 @@ class intermodule_singleton_common
//If previous state was initializing, this means that another winner thread is
//trying to initialize the singleton. Just wait until completes its work.
else if(previous_module_singleton_initialized == Initializing){
+ spin_wait swait;
while(1){
previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
if(previous_module_singleton_initialized >= Initialized){
@@ -151,7 +155,7 @@ class intermodule_singleton_common
break;
}
else if(previous_module_singleton_initialized == Initializing){
- thread_yield();
+ swait.yield();
}
else{
//This can't be happening!
@@ -178,7 +182,8 @@ class intermodule_singleton_common
//Note: this destructor might provoke a Phoenix singleton
//resurrection. This means that this_module_singleton_count
//might change after this call.
- destructor(ptr, get_map());
+ ThreadSafeGlobalMap * const pmap = get_map_ptr();
+ destructor(ptr, *pmap);
ptr = 0;
//Memory barrier to make sure pointer is nulled.
@@ -197,14 +202,15 @@ class intermodule_singleton_common
}
private:
- static ThreadSafeGlobalMap &get_map()
+ static ThreadSafeGlobalMap *get_map_ptr()
{
- return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem));
+ return static_cast<ThreadSafeGlobalMap *>(static_cast<void*>(mem_holder.map_mem));
}
static void initialize_global_map_handle()
{
//Obtain unique map name and size
+ spin_wait swait;
while(1){
//Try to pass map state to initializing
::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
@@ -217,7 +223,7 @@ class intermodule_singleton_common
}
//If some other thread is doing the work wait
else if(tmp == Initializing){
- thread_yield();
+ swait.yield();
}
else{ //(tmp == Uninitialized)
//If not initialized try it again?
@@ -225,16 +231,17 @@ class intermodule_singleton_common
//Remove old global map from the system
intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
//in-place construction of the global map class
+ ThreadSafeGlobalMap * const pmap = get_map_ptr();
intermodule_singleton_helpers::thread_safe_global_map_dependant
- <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map()));
+ <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(pmap));
//Use global map's internal lock to initialize the lock file
//that will mark this gmem as "in use".
typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
- lock_file_logic f(get_map());
+ lock_file_logic f(*pmap);
//If function failed (maybe a competing process has erased the shared
//memory between creation and file locking), retry with a new instance.
if(f.retry()){
- get_map().~ThreadSafeGlobalMap();
+ pmap->~ThreadSafeGlobalMap();
atomic_write32(&this_module_map_initialized, Destroyed);
}
else{
@@ -257,9 +264,10 @@ class intermodule_singleton_common
//This module is being unloaded, so destroy
//the global map object of this module
//and unlink the global map if it's the last
+ ThreadSafeGlobalMap * const pmap = get_map_ptr();
typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
- unlink_map_logic f(get_map());
- (get_map()).~ThreadSafeGlobalMap();
+ unlink_map_logic f(*pmap);
+ pmap->~ThreadSafeGlobalMap();
atomic_write32(&this_module_map_initialized, Destroyed);
//Do some cleanup for other processes old gmem instances
intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
@@ -274,11 +282,11 @@ class intermodule_singleton_common
//Values: Uninitialized, Initializing, Initialized, Broken
static volatile boost::uint32_t this_module_map_initialized;
- //Raw memory to construct the global map manager
- static struct mem_holder_t
+ //Raw memory to construct the global map manager
+ static union mem_holder_t
{
+ unsigned char map_mem [sizeof(ThreadSafeGlobalMap)];
::boost::detail::max_align aligner;
- char map_mem [sizeof(ThreadSafeGlobalMap)];
} mem_holder;
};
@@ -308,7 +316,7 @@ struct ref_count_ptr
//Now this class is a singleton, initializing the singleton in
-//the first get() function call if LazyInit is false. If true
+//the first get() function call if LazyInit is true. If false
//then the singleton will be initialized when loading the module.
template<typename C, bool LazyInit, bool Phoenix, class ThreadSafeGlobalMap>
class intermodule_singleton_impl
@@ -356,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
@@ -384,7 +392,7 @@ class intermodule_singleton_impl
struct init_atomic_func
{
init_atomic_func(ThreadSafeGlobalMap &m)
- : m_map(m)
+ : m_map(m), ret_ptr()
{}
void operator()()
@@ -405,13 +413,13 @@ class intermodule_singleton_impl
throw;
}
}
- if(Phoenix){
+ //if(Phoenix){
std::atexit(&atexit_work);
- }
+ //}
atomic_inc32(&rcount->singleton_ref_count);
ret_ptr = rcount->ptr;
}
- void *data() const
+ void *data() const
{ return ret_ptr; }
private:
@@ -446,12 +454,9 @@ class intermodule_singleton_impl
delete pc;
}
}
- void *data() const
- { return ret_ptr; }
-
+
private:
ThreadSafeGlobalMap &m_map;
- void *ret_ptr;
};
//A wrapper to execute init_atomic_func