Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r79514 - in trunk/boost/interprocess: . detail sync/windows
From: igaztanaga_at_[hidden]
Date: 2012-07-14 17:51:20


Author: igaztanaga
Date: 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
New Revision: 79514
URL: http://svn.boost.org/trac/boost/changeset/79514

Log:
Intermodule singleton optimization for windows
Text files modified:
   trunk/boost/interprocess/detail/intermodule_singleton_common.hpp | 262 +++++++++++++++++++++------------------
   trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp | 3
   trunk/boost/interprocess/detail/portable_intermodule_singleton.hpp | 60 +++++++-
   trunk/boost/interprocess/detail/win32_api.hpp | 91 ++++++++++++-
   trunk/boost/interprocess/detail/windows_intermodule_singleton.hpp | 248 ++++++++++++++++++++++++++++++++++++-
   trunk/boost/interprocess/managed_shared_memory.hpp | 6
   trunk/boost/interprocess/sync/windows/mutex.hpp | 4
   trunk/boost/interprocess/sync/windows/named_condition.hpp | 7
   trunk/boost/interprocess/sync/windows/named_semaphore.hpp | 5
   trunk/boost/interprocess/sync/windows/named_sync.hpp | 10
   trunk/boost/interprocess/sync/windows/semaphore.hpp | 2
   trunk/boost/interprocess/sync/windows/sync_utils.hpp | 90 ++++++++++---
   trunk/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp | 46 +++++-
   13 files changed, 627 insertions(+), 207 deletions(-)

Modified: trunk/boost/interprocess/detail/intermodule_singleton_common.hpp
==============================================================================
--- trunk/boost/interprocess/detail/intermodule_singleton_common.hpp (original)
+++ trunk/boost/interprocess/detail/intermodule_singleton_common.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -21,6 +21,7 @@
 #include <boost/interprocess/detail/atomic.hpp>
 #include <boost/interprocess/detail/os_thread_functions.hpp>
 #include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
 #include <boost/assert.hpp>
 #include <cstddef>
 #include <cstdio>
@@ -44,32 +45,32 @@
    s = stream.str();
 }
 
-inline const char *get_shm_base_name()
-{ return "bip.gmem.shm."; }
+inline const char *get_map_base_name()
+{ return "bip.gmem.map."; }
 
-inline void get_shm_name(std::string &shm_name)
+inline void get_map_name(std::string &map_name)
 {
- get_pid_creation_time_str(shm_name);
- shm_name.insert(0, get_shm_base_name());
+ get_pid_creation_time_str(map_name);
+ map_name.insert(0, get_map_base_name());
 }
 
-inline std::size_t get_shm_size()
+inline std::size_t get_map_size()
 { return 65536; }
 
-template<class ManagedGlobalMemory>
-struct managed_sh_dependant;
+template<class ThreadSafeGlobalMap>
+struct thread_safe_global_map_dependant;
 
 } //namespace intermodule_singleton_helpers {
 
 //This class contains common code for all singleton types, so that we instantiate this
-//code just once per module. This class also holds a shared memory manager
+//code just once per module. This class also holds a thread soafe global map
 //to be used by all instances protected with a reference count
-template<class ManagedGlobalMemory>
+template<class ThreadSafeGlobalMap>
 class intermodule_singleton_common
 {
    public:
- typedef void*(singleton_constructor_t)(ManagedGlobalMemory &);
- typedef void (singleton_destructor_t)(void *, ManagedGlobalMemory &);
+ typedef void*(singleton_constructor_t)(ThreadSafeGlobalMap &);
+ typedef void (singleton_destructor_t)(void *, ThreadSafeGlobalMap &);
 
    static const ::boost::uint32_t Uninitialized = 0u;
    static const ::boost::uint32_t Initializing = 1u;
@@ -77,11 +78,11 @@
    static const ::boost::uint32_t Broken = 3u;
    static const ::boost::uint32_t Destroyed = 4u;
 
- //Initialize this_module_singleton_ptr, creates the shared memory if needed and also creates an unique
- //opaque type in shared memory through a singleton_constructor_t function call,
+ //Initialize this_module_singleton_ptr, creates the global map if needed and also creates an unique
+ //opaque type in global map through a singleton_constructor_t function call,
    //initializing the passed pointer to that unique instance.
    //
- //We have two concurrency types here. a)the shared memory/singleton creation must
+ //We have two concurrency types here. a)the global map/singleton creation must
    //be safe between threads of this process but in different modules/dlls. b)
    //the pointer to the singleton is per-module, so we have to protect this
    //initization between threads of the same module.
@@ -98,7 +99,7 @@
          ::boost::uint32_t previous_module_singleton_initialized = atomic_cas32
             (&this_module_singleton_initialized, Initializing, Uninitialized);
          //If the thread succeeded the CAS (winner) it will compete with other
- //winner threads from other modules to create the shared memory
+ //winner threads from other modules to create the global map
          if(previous_module_singleton_initialized == Destroyed){
             //Trying to resurrect a dead Phoenix singleton. Just try to
             //mark it as uninitialized and start again
@@ -114,17 +115,17 @@
          }
          if(previous_module_singleton_initialized == Uninitialized){
             try{
- //Now initialize shm, this function solves concurrency issues
+ //Now initialize the global map, this function must solve concurrency
+ //issues between threads of several modules
+ initialize_global_map_handle();
+ //Now try to create the singleton in global map.
+ //This function solves concurrency issues
                //between threads of several modules
- initialize_shm();
+ void *tmp = constructor(get_map());
                //Increment the module reference count that reflects how many
                //singletons this module holds, so that we can safely destroy
- //module shared memory object when no singleton is left
+ //module global map object when no singleton is left
                atomic_inc32(&this_module_singleton_count);
- //Now try to create the singleton in shared memory.
- //This function solves concurrency issues
- //between threads of several modules
- void *tmp = constructor(get_shm());
                //Insert a barrier before assigning the pointer to
                //make sure this assignment comes after the initialization
                atomic_write32(&this_module_singleton_initialized, Initializing);
@@ -177,7 +178,7 @@
          //Note: this destructor might provoke a Phoenix singleton
          //resurrection. This means that this_module_singleton_count
          //might change after this call.
- destructor(ptr, get_shm());
+ destructor(ptr, get_map());
          ptr = 0;
 
          //Memory barrier to make sure pointer is nulled.
@@ -185,32 +186,35 @@
          atomic_write32(&this_module_singleton_initialized, Destroyed);
 
          //If this is the last singleton of this module
- //apply shm destruction.
+ //apply map destruction.
          //Note: singletons are destroyed when the module is unloaded
          //so no threads should be executing or holding references
          //to this module
          if(1 == atomic_dec32(&this_module_singleton_count)){
- destroy_shm();
+ destroy_global_map_handle();
          }
       }
    }
 
    private:
- static ManagedGlobalMemory &get_shm()
+ static ThreadSafeGlobalMap &get_map()
    {
- return *static_cast<ManagedGlobalMemory *>(static_cast<void *>(&mem_holder.shm_mem));
+ return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem));
    }
 
- static void initialize_shm()
+ static void initialize_global_map_handle()
    {
- //Obtain unique shm name and size
- std::string s;
+ //Obtain unique map name and size
       while(1){
- //Try to pass shm state to initializing
- ::boost::uint32_t tmp = atomic_cas32(&this_module_shm_initialized, Initializing, Uninitialized);
- if(tmp >= Initialized){
+ //Try to pass map state to initializing
+ ::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
+ if(tmp == Initialized || tmp == Broken){
             break;
          }
+ else if(tmp == Destroyed){
+ tmp = atomic_cas32(&this_module_map_initialized, Uninitialized, Destroyed);
+ continue;
+ }
          //If some other thread is doing the work wait
          else if(tmp == Initializing){
             thread_yield();
@@ -218,30 +222,24 @@
          else{ //(tmp == Uninitialized)
             //If not initialized try it again?
             try{
- //Remove old shared memory from the system
- intermodule_singleton_helpers::managed_sh_dependant<ManagedGlobalMemory>::remove_old_gmem();
- //
- if(s.empty()){
- intermodule_singleton_helpers::get_shm_name(s);
- }
- const char *ShmName = s.c_str();
- const std::size_t ShmSize = intermodule_singleton_helpers::get_shm_size();;
-
- //in-place construction of the shared memory class
- ::new (&get_shm())ManagedGlobalMemory(open_or_create, ShmName, ShmSize);
- //Use shared memory internal lock to initialize the lock file
+ //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
+ intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map()));
+ //Use global map's internal lock to initialize the lock file
                //that will mark this gmem as "in use".
- typename intermodule_singleton_helpers::managed_sh_dependant<ManagedGlobalMemory>::
- lock_file_logic f(get_shm());
+ typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
+ lock_file_logic f(get_map());
                //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_with_new_shm){
- get_shm().~ManagedGlobalMemory();
- atomic_write32(&this_module_shm_initialized, Destroyed);
+ if(f.retry()){
+ get_map().~ThreadSafeGlobalMap();
+ atomic_write32(&this_module_map_initialized, Destroyed);
                }
                else{
- //Locking succeeded, so this shared memory module-instance is ready
- atomic_write32(&this_module_shm_initialized, Initialized);
+ //Locking succeeded, so this global map module-instance is ready
+ atomic_write32(&this_module_map_initialized, Initialized);
                   break;
                }
             }
@@ -253,18 +251,18 @@
       }
    }
 
- static void destroy_shm()
+ static void destroy_global_map_handle()
    {
       if(!atomic_read32(&this_module_singleton_count)){
          //This module is being unloaded, so destroy
- //the shared memory object of this module
- //and unlink the shared memory if it's the last
- typename intermodule_singleton_helpers::managed_sh_dependant<ManagedGlobalMemory>::
- unlink_shmlogic f(get_shm());
- (get_shm()).~ManagedGlobalMemory();
- atomic_write32(&this_module_shm_initialized, Destroyed);
+ //the global map object of this module
+ //and unlink the global map if it's the last
+ typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
+ unlink_map_logic f(get_map());
+ (get_map()).~ThreadSafeGlobalMap();
+ atomic_write32(&this_module_map_initialized, Destroyed);
          //Do some cleanup for other processes old gmem instances
- intermodule_singleton_helpers::managed_sh_dependant<ManagedGlobalMemory>::remove_old_gmem();
+ intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
       }
    }
 
@@ -272,32 +270,47 @@
    //this_module_singleton_count is the number of singletons used by this module
    static volatile boost::uint32_t this_module_singleton_count;
 
- //this_module_shm_initialized is the state of this module's shm class object.
+ //this_module_map_initialized is the state of this module's map class object.
    //Values: Uninitialized, Initializing, Initialized, Broken
- static volatile boost::uint32_t this_module_shm_initialized;
+ static volatile boost::uint32_t this_module_map_initialized;
 
- //Raw memory to construct the shared memory manager
+ //Raw memory to construct the global map manager
    static struct mem_holder_t
    {
       ::boost::detail::max_align aligner;
- char shm_mem [sizeof(ManagedGlobalMemory)];
+ char map_mem [sizeof(ThreadSafeGlobalMap)];
    } mem_holder;
 };
 
-template<class ManagedGlobalMemory>
-volatile boost::uint32_t intermodule_singleton_common<ManagedGlobalMemory>::this_module_singleton_count;
+template<class ThreadSafeGlobalMap>
+volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_singleton_count;
 
-template<class ManagedGlobalMemory>
-volatile boost::uint32_t intermodule_singleton_common<ManagedGlobalMemory>::this_module_shm_initialized;
+template<class ThreadSafeGlobalMap>
+volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_map_initialized;
+
+template<class ThreadSafeGlobalMap>
+typename intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder_t
+ intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder;
+
+//A reference count to be stored in global map holding the number
+//of singletons (one per module) attached to the instance pointed by
+//the internal ptr.
+struct ref_count_ptr
+{
+ ref_count_ptr(void *p, boost::uint32_t count)
+ : ptr(p), singleton_ref_count(count)
+ {}
+ void *ptr;
+ //This reference count serves to count the number of attached
+ //modules to this singleton
+ volatile boost::uint32_t singleton_ref_count;
+};
 
-template<class ManagedGlobalMemory>
-typename intermodule_singleton_common<ManagedGlobalMemory>::mem_holder_t
- intermodule_singleton_common<ManagedGlobalMemory>::mem_holder;
 
 //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, bool Phoenix, class ManagedGlobalMemory>
+template<typename C, bool LazyInit, bool Phoenix, class ThreadSafeGlobalMap>
 class intermodule_singleton_impl
 {
    public:
@@ -316,13 +329,13 @@
 
    static void atentry_work()
    {
- intermodule_singleton_common<ManagedGlobalMemory>::initialize_singleton_logic
+ intermodule_singleton_common<ThreadSafeGlobalMap>::initialize_singleton_logic
          (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor, Phoenix);
    }
 
    static void atexit_work()
    {
- intermodule_singleton_common<ManagedGlobalMemory>::finalize_singleton_logic
+ intermodule_singleton_common<ThreadSafeGlobalMap>::finalize_singleton_logic
          (this_module_singleton_ptr, this_module_singleton_initialized, singleton_destructor);
    }
 
@@ -365,38 +378,29 @@
 
    static lifetime_type lifetime;
 
- //A reference count to be stored in shared memory holding the number
- //of singletons (one per module) attached to the instance pointed by
- //the internal ptr.
- struct ref_count_ptr
- {
- ref_count_ptr(C *p, boost::uint32_t count)
- : ptr(p), singleton_ref_count(count)
- {}
- C *ptr;
- //This reference count serves to count the number of attached
- //modules to this singleton
- volatile boost::uint32_t singleton_ref_count;
- };
-
- //A functor to be executed inside shared memory lock that just
- //searches for the singleton in shm and if not present creates a new one.
+ //A functor to be executed inside global map lock that just
+ //searches for the singleton in map and if not present creates a new one.
    //If singleton constructor throws, the exception is propagated
    struct init_atomic_func
    {
- init_atomic_func(ManagedGlobalMemory &m)
- : mshm(m)
+ init_atomic_func(ThreadSafeGlobalMap &m)
+ : m_map(m)
       {}
 
       void operator()()
       {
- ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
+ ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
          if(!rcount){
- C *p = new C();
+ C *p = new C;
             try{
- rcount = mshm.template construct<ref_count_ptr>(unique_instance)(p, 0u);
+ ref_count_ptr val(p, 0u);
+ rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::insert(m_map, typeid(C).name(), val);
             }
             catch(...){
+ intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
                delete p;
                throw;
             }
@@ -407,66 +411,80 @@
          atomic_inc32(&rcount->singleton_ref_count);
          ret_ptr = rcount->ptr;
       }
- ManagedGlobalMemory &mshm;
+ void *data() const
+ { return ret_ptr; }
+
+ private:
+ ThreadSafeGlobalMap &m_map;
       void *ret_ptr;
    };
 
- //A functor to be executed inside shared memory lock that just
- //deletes the singleton in shm if the attached count reaches to zero
+ //A functor to be executed inside global map lock that just
+ //deletes the singleton in map if the attached count reaches to zero
    struct fini_atomic_func
    {
- fini_atomic_func(ManagedGlobalMemory &m)
- : mshm(m)
+ fini_atomic_func(ThreadSafeGlobalMap &m)
+ : m_map(m)
       {}
 
       void operator()()
       {
- ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
+ ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
             //The object must exist
          BOOST_ASSERT(rcount);
+ BOOST_ASSERT(rcount->singleton_ref_count > 0);
          //Check if last reference
          if(atomic_dec32(&rcount->singleton_ref_count) == 1){
             //If last, destroy the object
             BOOST_ASSERT(rcount->ptr != 0);
- delete rcount->ptr;
- //Now destroy shm entry
- bool destroyed = mshm.template destroy<ref_count_ptr>(unique_instance);
+ C *pc = static_cast<C*>(rcount->ptr);
+ //Now destroy map entry
+ bool destroyed = intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
             (void)destroyed; BOOST_ASSERT(destroyed == true);
+ delete pc;
          }
       }
- ManagedGlobalMemory &mshm;
+ void *data() const
+ { return ret_ptr; }
+
+ private:
+ ThreadSafeGlobalMap &m_map;
       void *ret_ptr;
    };
 
    //A wrapper to execute init_atomic_func
- static void *singleton_constructor(ManagedGlobalMemory &mshm)
+ static void *singleton_constructor(ThreadSafeGlobalMap &map)
    {
- init_atomic_func f(mshm);
- mshm.atomic_func(f);
- return f.ret_ptr;
+ init_atomic_func f(map);
+ intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::atomic_func(map, f);
+ return f.data();
    }
 
    //A wrapper to execute fini_atomic_func
- static void singleton_destructor(void *p, ManagedGlobalMemory &mshm)
+ static void singleton_destructor(void *p, ThreadSafeGlobalMap &map)
    { (void)p;
- fini_atomic_func f(mshm);
- mshm.atomic_func(f);
+ fini_atomic_func f(map);
+ intermodule_singleton_helpers::thread_safe_global_map_dependant
+ <ThreadSafeGlobalMap>::atomic_func(map, f);
    }
 };
 
-template <typename C, bool L, bool P, class ManagedGlobalMemory>
-volatile int intermodule_singleton_impl<C, L, P, ManagedGlobalMemory>::lifetime_type_lazy::m_dummy = 0;
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+volatile int intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type_lazy::m_dummy = 0;
 
 //These will be zero-initialized by the loader
-template <typename C, bool L, bool P, class ManagedGlobalMemory>
-void *intermodule_singleton_impl<C, L, P, ManagedGlobalMemory>::this_module_singleton_ptr = 0;
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+void *intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_ptr = 0;
 
-template <typename C, bool L, bool P, class ManagedGlobalMemory>
-volatile boost::uint32_t intermodule_singleton_impl<C, L, P, ManagedGlobalMemory>::this_module_singleton_initialized = 0;
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+volatile boost::uint32_t intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_initialized = 0;
 
-template <typename C, bool L, bool P, class ManagedGlobalMemory>
-typename intermodule_singleton_impl<C, L, P, ManagedGlobalMemory>::lifetime_type
- intermodule_singleton_impl<C, L, P, ManagedGlobalMemory>::lifetime;
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+typename intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type
+ intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime;
 
 } //namespace ipcdetail{
 } //namespace interprocess{

Modified: trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp
==============================================================================
--- trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp (original)
+++ trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -396,7 +396,8 @@
 
             if(previous == UninitializedSegment){
                try{
- construct_func(static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset, size - ManagedOpenOrCreateUserOffset, true);
+ construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
+ , size - ManagedOpenOrCreateUserOffset, true);
                   //All ok, just move resources to the external mapped region
                   m_mapped_region.swap(region);
                }

Modified: trunk/boost/interprocess/detail/portable_intermodule_singleton.hpp
==============================================================================
--- trunk/boost/interprocess/detail/portable_intermodule_singleton.hpp (original)
+++ trunk/boost/interprocess/detail/portable_intermodule_singleton.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -104,7 +104,7 @@
 }
 
 template<>
-struct managed_sh_dependant<managed_global_memory>
+struct thread_safe_global_map_dependant<managed_global_memory>
 {
    private:
    static const int GMemMarkToBeRemoved = -1;
@@ -161,7 +161,7 @@
          }
          //If done, then the process is dead so take global shared memory name
          //(the name is based on the lock file name) and try to apply erasure logic
- str.insert(0, get_shm_base_name());
+ str.insert(0, get_map_base_name());
          try{
             managed_global_memory shm(open_only, str.c_str());
             gmem_erase_func func(str.c_str(), filepath, shm);
@@ -201,7 +201,7 @@
 
       void operator()(void)
       {
- retry_with_new_shm = false;
+ retry_with_new_map = false;
 
          //First find the file locking descriptor id
          locking_file_serial_id *pserial_id =
@@ -229,9 +229,9 @@
             if(fd < 0){
                this->register_lock_file(GMemMarkToBeRemoved);
                std::string s;
- get_shm_name(s);
+ get_map_name(s);
                shared_memory_object::remove(s.c_str());
- retry_with_new_shm = true;
+ retry_with_new_map = true;
             }
             //If successful, register the file descriptor
             else{
@@ -242,7 +242,7 @@
          //should retry creation logic, since this shm might have been already
          //unlinked since the shm was removed
          else if (fd == GMemMarkToBeRemoved){
- retry_with_new_shm = true;
+ retry_with_new_map = true;
          }
          //If the stored fd is not valid (a open fd, a normal file with the
          //expected size, or does not have the same file id number,
@@ -254,9 +254,9 @@
                !compare_file_serial(fd, *pserial_id)){
             pserial_id->fd = GMemMarkToBeRemoved;
             std::string s;
- get_shm_name(s);
+ get_map_name(s);
             shared_memory_object::remove(s.c_str());
- retry_with_new_shm = true;
+ retry_with_new_map = true;
          }
          else{
             //If the lock file is ok, increment reference count of
@@ -265,6 +265,8 @@
          }
       }
 
+ bool retry() const { return retry_with_new_map; }
+
       private:
       locking_file_serial_id * register_lock_file(int fd)
       {
@@ -273,16 +275,25 @@
          return pinfo;
       }
 
- public:
       managed_global_memory &mshm;
- bool retry_with_new_shm;
+ bool retry_with_new_map;
    };
 
- struct unlink_shmlogic
+ static void construct_map(void *addr)
    {
- unlink_shmlogic(managed_global_memory &mshm)
+ std::string s;
+ intermodule_singleton_helpers::get_map_name(s);
+ const char *MapName = s.c_str();
+ const std::size_t MapSize = intermodule_singleton_helpers::get_map_size();;
+ ::new (addr)managed_global_memory(open_or_create, MapName, MapSize);
+ }
+
+ struct unlink_map_logic
+ {
+ unlink_map_logic(managed_global_memory &mshm)
          : mshm_(mshm)
       { mshm.atomic_func(*this); }
+
       void operator()()
       {
          locking_file_serial_id *pserial_id =
@@ -297,13 +308,36 @@
                create_and_get_singleton_lock_file_path(s);
                delete_file(s.c_str());
                close_lock_file(fd);
- intermodule_singleton_helpers::get_shm_name(s);
+ intermodule_singleton_helpers::get_map_name(s);
                shared_memory_object::remove(s.c_str());
             }
          }
       }
+
+ private:
       managed_global_memory &mshm_;
    };
+
+ static ref_count_ptr *find(managed_global_memory &map, const char *name)
+ {
+ return map.find<ref_count_ptr>(name).first;
+ }
+
+ static ref_count_ptr *insert(managed_global_memory &map, const char *name, const ref_count_ptr &ref)
+ {
+ return map.construct<ref_count_ptr>(name)(ref);
+ }
+
+ static bool erase(managed_global_memory &map, const char *name)
+ {
+ return map.destroy<ref_count_ptr>(name);
+ }
+
+ template<class F>
+ static void atomic_func(managed_global_memory &map, F &f)
+ {
+ map.atomic_func(f);
+ }
 };
 
 } //namespace intermodule_singleton_helpers {

Modified: trunk/boost/interprocess/detail/win32_api.hpp
==============================================================================
--- trunk/boost/interprocess/detail/win32_api.hpp (original)
+++ trunk/boost/interprocess/detail/win32_api.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -46,6 +46,7 @@
 //Some used constants
 static const unsigned long infinite_time = 0xFFFFFFFF;
 static const unsigned long error_already_exists = 183L;
+static const unsigned long error_invalid_handle = 6L;
 static const unsigned long error_sharing_violation = 32L;
 static const unsigned long error_file_not_found = 2u;
 static const unsigned long error_no_more_files = 18u;
@@ -137,7 +138,14 @@
 static const unsigned long sublang_default = (unsigned long)0x01;
 static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF;
 static const unsigned long invalid_file_attributes = ((unsigned long)-1);
-static void * const invalid_handle_value = (void*)(long)(-1);
+static void * const invalid_handle_value = ((void*)(long)(-1));
+
+static const unsigned long file_type_char = 0x0002L;
+static const unsigned long file_type_disk = 0x0001L;
+static const unsigned long file_type_pipe = 0x0003L;
+static const unsigned long file_type_remote = 0x8000L;
+static const unsigned long file_type_unknown = 0x0000L;
+
 static const unsigned long create_new = 1;
 static const unsigned long create_always = 2;
 static const unsigned long open_existing = 3;
@@ -580,6 +588,13 @@
         unsigned int limit; // max semaphore count
 };
 
+struct interprocess_section_basic_information
+{
+ void * base_address;
+ unsigned long section_attributes;
+ __int64 section_size;
+};
+
 struct interprocess_filetime
 {
    unsigned long dwLowDateTime;
@@ -789,6 +804,12 @@
    object_data_information
 };
 
+enum section_information_class
+{
+ section_basic_information,
+ section_image_information
+};
+
 struct object_name_information_t
 {
    unicode_string_t Name;
@@ -813,6 +834,7 @@
    , void *hTargetProcessHandle, void **lpTargetHandle
    , unsigned long dwDesiredAccess, int bInheritHandle
    , unsigned long dwOptions);
+extern "C" __declspec(dllimport) long __stdcall GetFileType(void *hFile);
 extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData);
 extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData);
 extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile);
@@ -905,6 +927,7 @@
 typedef long (__stdcall *NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *);
 typedef long (__stdcall *NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *);
 typedef long (__stdcall *NtQuerySemaphore_t)(void*, unsigned int info_class, interprocess_semaphore_basic_information *pinfo, unsigned int info_size, unsigned int *ret_len);
+typedef long (__stdcall *NtQuerySection_t)(void*, section_information_class, interprocess_section_basic_information *pinfo, unsigned long info_size, unsigned long *ret_len);
 typedef long (__stdcall *NtQueryInformationFile_t)(void *,io_status_block_t *,void *, long, int);
 typedef long (__stdcall *NtOpenFile_t)(void*,unsigned long ,object_attributes_t*,io_status_block_t*,unsigned long,unsigned long);
 typedef long (__stdcall *NtClose_t) (void*);
@@ -989,6 +1012,12 @@
       , lpTargetHandle, 0, 0
       , duplicate_same_access);
 }
+
+inline long get_file_type(void *hFile)
+{
+ return GetFileType(hFile);
+}
+
 /*
 inline void get_system_time_as_file_time(interprocess_filetime *filetime)
 { GetSystemTimeAsFileTime(filetime); }
@@ -1012,6 +1041,9 @@
 inline void *open_or_create_semaphore(const char *name, long initial_count, long maximum_count, interprocess_security_attributes *attr)
 { return CreateSemaphoreA(attr, initial_count, maximum_count, name); }
 
+inline void *open_semaphore(const char *name)
+{ return OpenSemaphoreA(semaphore_all_access, 0, name); }
+
 inline int release_semaphore(void *handle, long release_count, long *prev_count)
 { return ReleaseSemaphore(handle, release_count, prev_count); }
 
@@ -1039,16 +1071,21 @@
    { return &sa; }
 };
 
-inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name, interprocess_security_attributes *psec)
+inline void * create_file_mapping (void * handle, unsigned long access, unsigned __int64 file_offset, const char * name, interprocess_security_attributes *psec)
 {
+ const unsigned long high_size(file_offset >> 32), low_size((boost::uint32_t)file_offset);
    return CreateFileMappingA (handle, psec, access, high_size, low_size, name);
 }
 
 inline void * open_file_mapping (unsigned long access, const char *name)
 { return OpenFileMappingA (access, 0, name); }
 
-inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned long highoffset, unsigned long lowoffset, std::size_t numbytes, void *base_addr)
-{ return MapViewOfFileEx(handle, file_access, highoffset, lowoffset, numbytes, base_addr); }
+inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned __int64 offset, std::size_t numbytes, void *base_addr)
+{
+ const unsigned long offset_low = (unsigned long)(offset & ((unsigned __int64)0xFFFFFFFF));
+ const unsigned long offset_high = offset >> 32;
+ return MapViewOfFileEx(handle, file_access, offset_high, offset_low, numbytes, base_addr);
+}
 
 inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes, interprocess_security_attributes *psec)
 {
@@ -1191,7 +1228,7 @@
 template<int Dummy>
 struct function_address_holder
 {
- enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NumFunction };
+ enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NumFunction };
    enum { NtDll_dll, NumModule };
 
    private:
@@ -1228,7 +1265,7 @@
    static void *get_address_from_dll(const unsigned int id)
    {
       assert(id < (unsigned int)NumFunction);
- const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject", "NtQuerySemaphore" };
+ const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject", "NtQuerySemaphore", "NtQuerySection" };
       bool compile_check[sizeof(function)/sizeof(function[0]) == NumFunction];
       (void)compile_check;
       return get_proc_address(get_module(NtDll_dll), function[id]);
@@ -1300,10 +1337,10 @@
    bool bSuccess = false;
 
    // Create a file mapping object.
- void * hFileMap = create_file_mapping(hFile, page_readonly, 0, 1, 0, 0);
+ void * hFileMap = create_file_mapping(hFile, page_readonly, 1, 0, 0);
    if(hFileMap){
       // Create a file mapping to get the file name.
- void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 0, 1, 0);
+ void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 1, 0);
 
       if (pMem){
          //out_length = pfGMFN(get_current_process(), pMem, pszFilename, MaxPath);
@@ -1398,9 +1435,12 @@
 class handle_closer
 {
    void *handle_;
+ handle_closer(const handle_closer &);
+ handle_closer& operator=(const handle_closer &);
    public:
- handle_closer(void *handle) : handle_(handle){}
- ~handle_closer(){ close_handle(handle_); }
+ explicit handle_closer(void *handle) : handle_(handle){}
+ ~handle_closer()
+ { close_handle(handle_); }
 };
 
 union ntquery_mem_t
@@ -1729,6 +1769,37 @@
                 (attrib & file_attribute_directory));
 }
 
+inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size)
+{
+ NtQuerySection_t pNtQuerySection =
+ (NtQuerySection_t)dll_func::get(dll_func::NtQuerySection);
+ //Obtain file name
+ interprocess_section_basic_information info;
+ unsigned long ntstatus =
+ pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0);
+ if(ntstatus){
+ return false;
+ }
+ size = info.section_size;
+ return true;
+}
+
+inline bool get_semaphore_info(void *handle, long &count, long &limit)
+{
+ winapi::interprocess_semaphore_basic_information info;
+ winapi::NtQuerySemaphore_t pNtQuerySemaphore =
+ (winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore);
+ unsigned int ret_len;
+ long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len);
+ if(status){
+ return false;
+ }
+ count = info.count;
+ limit = info.limit;
+ return true;
+}
+
+
 } //namespace winapi
 } //namespace interprocess
 } //namespace boost

Modified: trunk/boost/interprocess/detail/windows_intermodule_singleton.hpp
==============================================================================
--- trunk/boost/interprocess/detail/windows_intermodule_singleton.hpp (original)
+++ trunk/boost/interprocess/detail/windows_intermodule_singleton.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -22,21 +22,217 @@
    #error "This header can't be included from non-windows operating systems"
 #endif
 
-#include <boost/interprocess/detail/managed_global_memory.hpp>
-#include <boost/interprocess/detail/intermodule_singleton_common.hpp>
-#include <boost/interprocess/windows_shared_memory.hpp>
 #include <boost/assert.hpp>
+#include <boost/interprocess/detail/intermodule_singleton_common.hpp>
+#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
+#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/cstdint.hpp>
+#include <string>
+#include <map>
 
 namespace boost{
 namespace interprocess{
 namespace ipcdetail{
 
-typedef basic_managed_global_memory<windows_shared_memory, false> windows_managed_global_memory;
-
 namespace intermodule_singleton_helpers {
 
+//This global map will be implemented using 3 sync primitives:
+//
+//1) A named mutex that will implement global mutual exclusion between
+// threads from different modules/dlls
+//
+//2) A semaphore that will act as a global counter for modules attached to the global map
+// so that the global map can be destroyed when the last module is detached.
+//
+//3) A semaphore that will be hacked to hold the address of a heap-allocated map in the
+// max and current semaphore count.
+class windows_semaphore_based_map
+{
+ typedef std::map<std::string, ref_count_ptr> map_type;
+
+ public:
+ windows_semaphore_based_map()
+ {
+ map_type *m = new map_type;
+ boost::uint32_t initial_count = 0;
+ boost::uint32_t max_count = 0;
+
+ //Windows user address space sizes:
+ //32 bit windows: [32 bit processes] 2GB or 3GB (31/32 bits)
+ //64 bit windows: [32 bit processes] 2GB or 4GB (31/32 bits)
+ // [64 bit processes] 2GB or 8TB (31/43 bits)
+ //
+ //Windows semaphores use 'long' parameters (32 bits in LLP64 data model) and
+ //those values can't be negative, so we have 31 bits to store something
+ //in max_count and initial count parameters.
+ //Also, max count must be bigger than 0 and bigger or equal than initial count.
+ if(sizeof(void*) == sizeof(boost::uint32_t)){
+ //This means that for 32 bit processes, a semaphore count (31 usable bits) is
+ //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits).
+ //The max count will hold the pointer value and current semaphore count
+ //will be zero.
+ //
+ //Relying in UB with a cast through union, but all known windows compilers
+ //accept this (C11 also accepts this).
+ union caster_union
+ {
+ void *addr;
+ boost::uint32_t addr_uint32;
+ } caster;
+ caster.addr = m;
+ //memory is at least 4 byte aligned in windows
+ BOOST_ASSERT((caster.addr_uint32 & boost::uint32_t(3)) == 0);
+ max_count = caster.addr_uint32 >> 2;
+ }
+ else if(sizeof(void*) == sizeof(boost::uint64_t)){
+ //Relying in UB with a cast through union, but all known windows compilers
+ //accept this (C11 accepts this).
+ union caster_union
+ {
+ void *addr;
+ boost::uint64_t addr_uint64;
+ } caster;
+ caster.addr = m;
+ //We'll encode the address using 30 bits in each 32 bit high and low parts.
+ //High part will be the sem max count, low part will be the sem initial count.
+ //(restrictions: max count > 0, initial count >= 0 and max count >= initial count):
+ //
+ // - Low part will be shifted two times (4 byte alignment) so that top
+ // two bits are cleared (the top one for sign, the next one to
+ // assure low part value is always less than the high part value.
+ // - The top bit of the high part will be cleared and the next bit will be 1
+ // (so high part is always bigger than low part due to the quasi-top bit).
+ //
+ // This means that the addresses we can store must be 4 byte aligned
+ // and less than 1 ExbiBytes ( 2^60 bytes, ~1 ExaByte). User-level address space in Windows 64
+ // is much less than this (8TB, 2^43 bytes): "1 EByte (or it was 640K?) ought to be enough for anybody" ;-).
+ caster.addr = m;
+ BOOST_ASSERT((caster.addr_uint64 & boost::uint64_t(3)) == 0);
+ max_count = boost::uint32_t(caster.addr_uint64 >> 32);
+ initial_count = boost::uint32_t(caster.addr_uint64);
+ initial_count = initial_count/4;
+ //Make sure top two bits are zero
+ BOOST_ASSERT((max_count & boost::uint32_t(0xC0000000)) == 0);
+ //Set quasi-top bit
+ max_count |= boost::uint32_t(0x40000000);
+ }
+ bool created = false;
+ const permissions & perm = permissions();
+ std::string pid_creation_time, name;
+ get_pid_creation_time_str(pid_creation_time);
+ name = "bipc_gmap_sem_lock_";
+ name += pid_creation_time;
+ bool success = m_mtx_lock.open_or_create(name.c_str(), perm);
+ name = "bipc_gmap_sem_count_";
+ name += pid_creation_time;
+ scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+ {
+ success = success && m_sem_count.open_or_create
+ ( name.c_str(), static_cast<long>(0), winapi_semaphore_wrapper::MaxCount, perm, created);
+ name = "bipc_gmap_sem_map_";
+ name += pid_creation_time;
+ success = success && m_sem_map.open_or_create
+ (name.c_str(), initial_count, max_count, perm, created);
+ if(!success){
+ //winapi_xxx wrappers do the cleanup...
+ throw int(0);
+ }
+ if(!created){
+ delete m;
+ }
+ else{
+ BOOST_ASSERT(&get_map_unlocked() == m);
+ }
+ m_sem_count.post();
+ }
+ }
+
+ map_type &get_map_unlocked()
+ {
+ if(sizeof(void*) == sizeof(boost::uint32_t)){
+ union caster_union
+ {
+ void *addr;
+ boost::uint32_t addr_uint32;
+ } caster;
+ caster.addr = 0;
+ caster.addr_uint32 = m_sem_map.limit();
+ caster.addr_uint32 = caster.addr_uint32 << 2;
+ return *static_cast<map_type*>(caster.addr);
+ }
+ else{
+ union caster_union
+ {
+ void *addr;
+ boost::uint64_t addr_uint64;
+ } caster;
+ boost::uint32_t max_count(m_sem_map.limit()), initial_count(m_sem_map.value());
+ //Clear quasi-top bit
+ max_count &= boost::uint32_t(0xBFFFFFFF);
+ caster.addr_uint64 = max_count;
+ caster.addr_uint64 = caster.addr_uint64 << 32;
+ caster.addr_uint64 |= boost::uint64_t(initial_count) << 2;
+ return *static_cast<map_type*>(caster.addr);
+ }
+ }
+
+ ref_count_ptr *find(const char *name)
+ {
+ 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));
+ if(it != map.end()){
+ return &it->second;
+ }
+ else{
+ return 0;
+ }
+ }
+
+ ref_count_ptr * insert(const char *name, const ref_count_ptr &ref)
+ {
+ 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;
+ return &it->second;
+ }
+
+ bool erase(const char *name)
+ {
+ scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+ map_type &map = this->get_map_unlocked();
+ return map.erase(std::string(name)) != 0;
+ }
+
+ template<class F>
+ void atomic_func(F &f)
+ {
+ scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+ f();
+ }
+
+ ~windows_semaphore_based_map()
+ {
+ scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+ m_sem_count.wait();
+ if(0 == m_sem_count.value()){
+ delete &this->get_map_unlocked();
+ }
+ //First close sems to protect this with the external mutex
+ m_sem_map.close();
+ m_sem_count.close();
+ //Once scoped_lock unlocks the mutex, the destructor will close the handle...
+ }
+
+ private:
+ winapi_mutex_wrapper m_mtx_lock;
+ winapi_semaphore_wrapper m_sem_map;
+ winapi_semaphore_wrapper m_sem_count;
+};
+
 template<>
-struct managed_sh_dependant<windows_managed_global_memory>
+struct thread_safe_global_map_dependant<windows_semaphore_based_map>
 {
    static void apply_gmem_erase_logic(const char *, const char *){}
 
@@ -45,20 +241,48 @@
 
    struct lock_file_logic
    {
- lock_file_logic(windows_managed_global_memory &)
- : retry_with_new_shm(false)
+ lock_file_logic(windows_semaphore_based_map &)
+ : retry_with_new_map(false)
       {}
 
       void operator()(void){}
- const bool retry_with_new_shm;
+ bool retry() const { return retry_with_new_map; }
+ private:
+ const bool retry_with_new_map;
    };
 
- struct unlink_shmlogic
+ static void construct_map(void *addr)
+ {
+ ::new (addr)windows_semaphore_based_map;
+ }
+
+ struct unlink_map_logic
    {
- unlink_shmlogic(windows_managed_global_memory &)
+ unlink_map_logic(windows_semaphore_based_map &)
       {}
       void operator()(){}
    };
+
+ static ref_count_ptr *find(windows_semaphore_based_map &map, const char *name)
+ {
+ return map.find(name);
+ }
+
+ static ref_count_ptr * insert(windows_semaphore_based_map &map, const char *name, const ref_count_ptr &ref)
+ {
+ return map.insert(name, ref);
+ }
+
+ static bool erase(windows_semaphore_based_map &map, const char *name)
+ {
+ return map.erase(name);
+ }
+
+ template<class F>
+ static void atomic_func(windows_semaphore_based_map &map, F &f)
+ {
+ map.atomic_func(f);
+ }
 };
 
 } //namespace intermodule_singleton_helpers {
@@ -69,7 +293,7 @@
       < C
       , LazyInit
       , Phoenix
- , windows_managed_global_memory
+ , intermodule_singleton_helpers::windows_semaphore_based_map
>
 {};
 

Modified: trunk/boost/interprocess/managed_shared_memory.hpp
==============================================================================
--- trunk/boost/interprocess/managed_shared_memory.hpp (original)
+++ trunk/boost/interprocess/managed_shared_memory.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -187,12 +187,6 @@
       return base_t::template shrink_to_fit
          <basic_managed_shared_memory>(shmname);
    }
-
- bool flush()
- {
- return this->base2_t::flush();
- }
-
    /// @cond
 
    //!Tries to find a previous named allocation address. Returns a memory

Modified: trunk/boost/interprocess/sync/windows/mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/mutex.hpp (original)
+++ trunk/boost/interprocess/sync/windows/mutex.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -49,13 +49,13 @@
 };
 
 inline windows_mutex::windows_mutex()
- : id_()
+ : id_(this)
 {
    sync_handles &handles =
       windows_intermodule_singleton<sync_handles>::get();
    //Create mutex with the initial count
    bool open_or_created;
- handles.obtain_mutex(this->id_, &open_or_created);
+ (void)handles.obtain_mutex(this->id_, &open_or_created);
    //The mutex must be created, never opened
    assert(open_or_created);
    assert(open_or_created && winapi::get_last_error() != winapi::error_already_exists);

Modified: trunk/boost/interprocess/sync/windows/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/windows/named_condition.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -176,14 +176,17 @@
          //sem_block_queue
          aux_str += "_bq";
          winapi_semaphore_wrapper sem_block_queue;
- if(!sem_block_queue.open_or_create(aux_str.c_str(), sem_counts[0], perm))
+ bool created;
+ if(!sem_block_queue.open_or_create
+ (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created))
             return false;
          aux_str.erase(pos);
 
          //sem_block_lock
          aux_str += "_bl";
          winapi_semaphore_wrapper sem_block_lock;
- if(!sem_block_lock.open_or_create(aux_str.c_str(), sem_counts[1], perm))
+ if(!sem_block_lock.open_or_create
+ (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created))
             return false;
          aux_str.erase(pos);
 

Modified: trunk/boost/interprocess/sync/windows/named_semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/named_semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/windows/named_semaphore.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -90,7 +90,10 @@
          //
          permissions sem_perm;
          sem_perm.set_unrestricted();
- return m_sem_wrapper.open_or_create(aux_str.c_str(), static_cast<long>(m_sem_count), sem_perm);
+ bool created;
+ return m_sem_wrapper.open_or_create
+ ( aux_str.c_str(), static_cast<long>(m_sem_count)
+ , winapi_semaphore_wrapper::MaxCount, sem_perm, created);
       }
 
       virtual void close()

Modified: trunk/boost/interprocess/sync/windows/named_sync.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/named_sync.hpp (original)
+++ trunk/boost/interprocess/sync/windows/named_sync.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -102,7 +102,6 @@
    , windows_named_sync_interface &sync_interface)
 {
    std::string aux_str(name);
- sync_id::internal_type unique_id_val;
    m_file_hnd = winapi::invalid_handle_value;
    //Use a file to emulate POSIX lifetime semantics. After this logic
    //we'll obtain the ID of the native handle to open in aux_str
@@ -123,7 +122,8 @@
       if(m_file_hnd != winapi::invalid_handle_value){
          //Now lock the file
          const std::size_t buflen = sync_interface.get_data_size();
- const std::size_t sizeof_file_info = sizeof(unique_id_val) + buflen;
+ typedef __int64 unique_id_type;
+ const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen;
          winapi::interprocess_overlapped overlapped;
          if(winapi::lock_file_ex
             (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){
@@ -132,10 +132,10 @@
             //If file size was created
             if(winapi::get_file_size(m_file_hnd, filesize)){
                unsigned long written_or_read = 0;
+ unique_id_type unique_id_val;
                if(static_cast<std::size_t>(filesize) != sizeof_file_info){
                   winapi::set_end_of_file(m_file_hnd);
- sync_id unique_id;
- unique_id_val = unique_id.rand;
+ winapi::query_performance_counter(&unique_id_val);
                   const void *buf = sync_interface.buffer_with_init_data_to_file();
                   //Write unique ID in file. This ID will be used to calculate the semaphore name
                   if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) &&
@@ -145,7 +145,7 @@
                      success = true;
                   }
                   winapi::get_file_size(m_file_hnd, filesize);
- assert(filesize == sizeof_file_info);
+ assert(std::size_t(filesize) == sizeof_file_info);
                }
                else{
                   void *buf = sync_interface.buffer_to_store_init_data_from_file();

Modified: trunk/boost/interprocess/sync/windows/semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/windows/semaphore.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -48,7 +48,7 @@
 };
 
 inline windows_semaphore::windows_semaphore(unsigned int initialCount)
- : id_()
+ : id_(this)
 {
    sync_handles &handles =
       windows_intermodule_singleton<sync_handles>::get();

Modified: trunk/boost/interprocess/sync/windows/sync_utils.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/sync_utils.hpp (original)
+++ trunk/boost/interprocess/sync/windows/sync_utils.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -24,6 +24,7 @@
 #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
 #include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
 #include <boost/unordered/unordered_map.hpp>
+#include <boost/container/map.hpp>
 #include <cstddef>
 
 namespace boost {
@@ -52,22 +53,36 @@
    return true;
 }
 
-struct sync_id
+class sync_id
 {
+ public:
    typedef __int64 internal_type;
- internal_type rand;
+ sync_id(const void *map_addr)
+ : map_addr_(map_addr)
+ { winapi::query_performance_counter(&rand_); }
+
+ explicit sync_id(internal_type val, const void *map_addr)
+ : map_addr_(map_addr)
+ { rand_ = val; }
+
+ const internal_type &internal_pod() const
+ { return rand_; }
 
- sync_id()
- { winapi::query_performance_counter(&rand); }
+ internal_type &internal_pod()
+ { return rand_; }
 
- explicit sync_id(internal_type val)
- { rand = val; }
+ const void *map_addr() const
+ { return map_addr_; }
 
    friend std::size_t hash_value(const sync_id &m)
- { return boost::hash_value(m.rand); }
+ { return boost::hash_value(m.rand_); }
 
    friend bool operator==(const sync_id &l, const sync_id &r)
- { return l.rand == r.rand; }
+ { return l.rand_ == r.rand_ && l.map_addr_ == r.map_addr_; }
+
+ private:
+ internal_type rand_;
+ const void * const map_addr_;
 };
 
 class sync_handles
@@ -76,11 +91,19 @@
    enum type { MUTEX, SEMAPHORE };
 
    private:
- typedef boost::unordered_map<sync_id, void*> map_type;
+ struct address_less
+ {
+ bool operator()(sync_id const * const l, sync_id const * const r) const
+ { return l->map_addr() < r->map_addr(); }
+ };
+
+ typedef boost::unordered_map<sync_id, void*> umap_type;
+ typedef boost::container::map<const sync_id*, umap_type::iterator, address_less> map_type;
    static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1;
    static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1);
    typedef char NameBuf[StrSize];
 
+
    void fill_name(NameBuf &name, const sync_id &id)
    {
       const char *n = "Global\\boost.ipc";
@@ -90,13 +113,12 @@
          ++i;
       } while(n[i]);
       std::size_t len = sizeof(NameBuf) - LengthOfGlobal;
- bytes_to_str(&id.rand, sizeof(id.rand), &name[LengthOfGlobal], len);
+ bytes_to_str(&id.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len);
    }
 
- void erase_and_throw_if_error(void *hnd_val, const sync_id &id)
+ void throw_if_error(void *hnd_val)
    {
       if(!hnd_val){
- map_.erase(id);
          error_info err(winapi::get_last_error());
          throw interprocess_exception(err);
       }
@@ -109,8 +131,10 @@
       permissions unrestricted_security;
       unrestricted_security.set_unrestricted();
       winapi_semaphore_wrapper sem_wrapper;
- sem_wrapper.open_or_create(name, (long)initial_count, unrestricted_security);
- erase_and_throw_if_error(sem_wrapper.handle(), id);
+ bool created;
+ sem_wrapper.open_or_create
+ (name, (long)initial_count, winapi_semaphore_wrapper::MaxCount, unrestricted_security, created);
+ throw_if_error(sem_wrapper.handle());
       return sem_wrapper.release();
    }
 
@@ -122,15 +146,18 @@
       unrestricted_security.set_unrestricted();
       winapi_mutex_wrapper mtx_wrapper;
       mtx_wrapper.open_or_create(name, unrestricted_security);
- erase_and_throw_if_error(mtx_wrapper.handle(), id);
+ throw_if_error(mtx_wrapper.handle());
       return mtx_wrapper.release();
    }
 
    public:
    void *obtain_mutex(const sync_id &id, bool *popen_created = 0)
    {
+ umap_type::value_type v(id, (void*)0);
       scoped_lock<spin_mutex> lock(mtx_);
- void *&hnd_val = map_[id];
+ umap_type::iterator it = umap_.insert(v).first;
+ map_[&it->first] = it;
+ void *&hnd_val = it->second;
       if(!hnd_val){
          hnd_val = open_or_create_mutex(id);
          if(popen_created) *popen_created = true;
@@ -140,8 +167,11 @@
 
    void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0)
    {
+ umap_type::value_type v(id, (void*)0);
       scoped_lock<spin_mutex> lock(mtx_);
- void *&hnd_val = map_[id];
+ umap_type::iterator it = umap_.insert(v).first;
+ map_[&it->first] = it;
+ void *&hnd_val = it->second;
       if(!hnd_val){
          hnd_val = open_or_create_semaphore(id, initial_count);
          if(popen_created) *popen_created = true;
@@ -152,15 +182,35 @@
    void destroy_handle(const sync_id &id)
    {
       scoped_lock<spin_mutex> lock(mtx_);
- map_type::iterator it = map_.find(id);
- if(it != map_.end()){
+ umap_type::iterator it = umap_.find(id);
+ umap_type::iterator itend = umap_.end();
+
+ if(it != itend){
          winapi::close_handle(it->second);
- map_.erase(it);
+ const map_type::key_type &k = &it->first;
+ map_.erase(k);
+ umap_.erase(it);
+ }
+ }
+
+ void destroy_syncs_in_range(const void *addr, std::size_t size)
+ {
+ sync_id low_id(addr);
+ sync_id hig_id(static_cast<const char*>(addr)+size);
+ scoped_lock<spin_mutex> lock(mtx_);
+ map_type::iterator itlow(map_.lower_bound(&low_id)),
+ ithig(map_.lower_bound(&hig_id));
+ while(itlow != ithig){
+ void *hnd = umap_[*itlow->first];
+ winapi::close_handle(hnd);
+ umap_.erase(*itlow->first);
+ itlow = map_.erase(itlow);
       }
    }
 
    private:
    spin_mutex mtx_;
+ umap_type umap_;
    map_type map_;
 };
 

Modified: trunk/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp (original)
+++ trunk/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp 2012-07-14 17:51:18 EDT (Sat, 14 Jul 2012)
@@ -93,17 +93,20 @@
       }
    }
 
- unsigned int value() const
+ long value() const
    {
- winapi::interprocess_semaphore_basic_information info;
- winapi::NtQuerySemaphore_t pNtQuerySemaphore =
- (winapi::NtQuerySemaphore_t)winapi::dll_func::get(winapi::dll_func::NtQuerySemaphore);
- unsigned int ret_len;
- long status = pNtQuerySemaphore(m_sem_hnd, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len);
- if(status){
+ long count, limit;
+ if(!winapi::get_semaphore_info(m_sem_hnd, count, limit))
          return 0;
- }
- return info.count;
+ return count;
+ }
+
+ long limit() const
+ {
+ long count, limit;
+ if(!winapi::get_semaphore_info(m_sem_hnd, count, limit))
+ return 0;
+ return limit;
    }
 
    /// @cond
@@ -122,6 +125,9 @@
 
    public:
 
+ //Long is 32 bits in windows
+ static const long MaxCount = long(0x7FFFFFFF);
+
    winapi_semaphore_wrapper(void *hnd = winapi::invalid_handle_value)
       : winapi_semaphore_functions(hnd)
    {}
@@ -139,21 +145,37 @@
    void *handle() const
    { return m_sem_hnd; }
 
- bool open_or_create(const char *name, long sem_count, const permissions &perm)
+ bool open_or_create( const char *name
+ , long sem_count
+ , long max_count
+ , const permissions &perm
+ , bool &created)
    {
       if(m_sem_hnd == winapi::invalid_handle_value){
          m_sem_hnd = winapi::open_or_create_semaphore
             ( name
             , sem_count
- , (std::numeric_limits<long>::max)()
+ , max_count
             , (winapi::interprocess_security_attributes*)perm.get_permissions()
             );
+ created = winapi::get_last_error() != winapi::error_already_exists;
+ return m_sem_hnd != winapi::invalid_handle_value;
+ }
+ else{
+ return false;
+ }
+ }
+
+ bool open_semaphore(const char *name)
+ {
+ if(m_sem_hnd == winapi::invalid_handle_value){
+ m_sem_hnd = winapi::open_semaphore(name);
          return m_sem_hnd != winapi::invalid_handle_value;
       }
       else{
          return false;
       }
- }
+ }
 
    void close()
    {


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk