|
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