|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r79558 - in branches/release/boost/interprocess: . detail sync/windows
From: igaztanaga_at_[hidden]
Date: 2012-07-16 04:55:10
Author: igaztanaga
Date: 2012-07-16 04:55:08 EDT (Mon, 16 Jul 2012)
New Revision: 79558
URL: http://svn.boost.org/trac/boost/changeset/79558
Log:
Merged revision(s) 79392-79557 from trunk/boost/interprocess
Properties modified:
branches/release/boost/interprocess/ (props changed)
Text files modified:
branches/release/boost/interprocess/anonymous_shared_memory.hpp | 6
branches/release/boost/interprocess/detail/intermodule_singleton_common.hpp | 262 ++++++++++++----------
branches/release/boost/interprocess/detail/managed_open_or_create_impl.hpp | 3
branches/release/boost/interprocess/detail/portable_intermodule_singleton.hpp | 60 ++++-
branches/release/boost/interprocess/detail/win32_api.hpp | 91 +++++++
branches/release/boost/interprocess/detail/windows_intermodule_singleton.hpp | 248 ++++++++++++++++++++-
branches/release/boost/interprocess/managed_shared_memory.hpp | 6
branches/release/boost/interprocess/mapped_region.hpp | 452 ++++++++++++++++++++++-----------------
branches/release/boost/interprocess/sync/windows/mutex.hpp | 4
branches/release/boost/interprocess/sync/windows/named_condition.hpp | 7
branches/release/boost/interprocess/sync/windows/named_semaphore.hpp | 5
branches/release/boost/interprocess/sync/windows/named_sync.hpp | 10
branches/release/boost/interprocess/sync/windows/semaphore.hpp | 2
branches/release/boost/interprocess/sync/windows/sync_utils.hpp | 90 ++++++-
branches/release/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp | 46 +++-
branches/release/boost/interprocess/windows_shared_memory.hpp | 25 +-
16 files changed, 896 insertions(+), 421 deletions(-)
Modified: branches/release/boost/interprocess/anonymous_shared_memory.hpp
==============================================================================
--- branches/release/boost/interprocess/anonymous_shared_memory.hpp (original)
+++ branches/release/boost/interprocess/anonymous_shared_memory.hpp 2012-07-16 04:55:08 EDT (Mon, 16 Jul 2012)
@@ -43,12 +43,10 @@
{
public:
static mapped_region
- create_posix_mapped_region(void *address, offset_t offset, std::size_t size)
+ create_posix_mapped_region(void *address, std::size_t size)
{
mapped_region region;
region.m_base = address;
- region.m_offset = offset;
- region.m_extra_offset = 0;
region.m_size = size;
return region;
}
@@ -101,7 +99,7 @@
if(fd != -1)
close(fd);
- return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, 0, size);
+ return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size);
}
#else
{
Modified: branches/release/boost/interprocess/detail/intermodule_singleton_common.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/intermodule_singleton_common.hpp (original)
+++ branches/release/boost/interprocess/detail/intermodule_singleton_common.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/detail/managed_open_or_create_impl.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/managed_open_or_create_impl.hpp (original)
+++ branches/release/boost/interprocess/detail/managed_open_or_create_impl.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/detail/portable_intermodule_singleton.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/portable_intermodule_singleton.hpp (original)
+++ branches/release/boost/interprocess/detail/portable_intermodule_singleton.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/detail/win32_api.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/win32_api.hpp (original)
+++ branches/release/boost/interprocess/detail/win32_api.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/detail/windows_intermodule_singleton.hpp
==============================================================================
--- branches/release/boost/interprocess/detail/windows_intermodule_singleton.hpp (original)
+++ branches/release/boost/interprocess/detail/windows_intermodule_singleton.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/managed_shared_memory.hpp
==============================================================================
--- branches/release/boost/interprocess/managed_shared_memory.hpp (original)
+++ branches/release/boost/interprocess/managed_shared_memory.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/mapped_region.hpp
==============================================================================
--- branches/release/boost/interprocess/mapped_region.hpp (original)
+++ branches/release/boost/interprocess/mapped_region.hpp 2012-07-16 04:55:08 EDT (Mon, 16 Jul 2012)
@@ -20,10 +20,11 @@
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <string>
-#include <limits>
+#include <boost/cstdint.hpp>
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
+# include <boost/interprocess/sync/windows/sync_utils.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
# include <fcntl.h>
@@ -55,6 +56,10 @@
//!The mapped_region class represents a portion or region created from a
//!memory_mappable object.
+//!
+//!The OS can map a region bigger than the requested one, as region must
+//!be multiple of the page size, but mapped_region will always refer to
+//!the region specified by the user.
class mapped_region
{
/// @cond
@@ -66,8 +71,14 @@
//!Creates a mapping region of the mapped memory "mapping", starting in
//!offset "offset", and the mapping's size will be "size". The mapping
- //!can be opened for read-only "read_only" or read-write
- //!"read_write.
+ //!can be opened for read only, read-write or copy-on-write.
+ //!
+ //!If an address is specified, both the offset and the address must be
+ //!multiples of the page size.
+ //!
+ //!The OS could allocate more pages than size/page_size(), but get_address()
+ //!will always return the address passed in this function (if not null) and
+ //!get_size() will return the specified size.
template<class MemoryMappable>
mapped_region(const MemoryMappable& mapping
,mode_t mode
@@ -75,8 +86,8 @@
,std::size_t size = 0
,const void *address = 0);
- //!Default constructor. Default constructor. Address will be 0 (nullptr).
- //!Size and offset will be 0.
+ //!Default constructor. Address will be 0 (nullptr).
+ //!Size will be 0.
//!Does not throw
mapped_region();
@@ -84,12 +95,12 @@
//!region and "other" will be left in default constructor state.
mapped_region(BOOST_RV_REF(mapped_region) other)
#if defined (BOOST_INTERPROCESS_WINDOWS)
- : m_base(0), m_size(0), m_offset(0)
- , m_extra_offset(0)
+ : m_base(0), m_size(0)
+ , m_page_offset(0)
, m_mode(read_only)
- , m_file_mapping_hnd(ipcdetail::invalid_file())
+ , m_file_or_mapping_hnd(ipcdetail::invalid_file())
#else
- : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only), m_is_xsi(false)
+ : m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
#endif
{ this->swap(other); }
@@ -106,33 +117,31 @@
return *this;
}
- //!Returns the size of the mapping. Note for windows users: If
- //!windows_shared_memory is mapped using 0 as the size, it returns 0
- //!because the size is unknown. Never throws.
+ //!Returns the size of the mapping. Never throws.
std::size_t get_size() const;
//!Returns the base address of the mapping.
//!Never throws.
void* get_address() const;
- //!Returns the offset of the mapping from the beginning of the
- //!mapped memory. Never throws.
- offset_t get_offset() const;
-
- //!Returns the mode of the mapping used to construct the mapped file.
+ //!Returns the mode of the mapping used to construct the mapped region.
//!Never throws.
mode_t get_mode() const;
//!Flushes to the disk a byte range within the mapped memory.
- //!Never throws
- bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0);
+ //!If 'async' is true, the function will return before flushing operation is completed
+ //!If 'async' is false, function will return once data has been written into the underlying
+ //!device (i.e., in mapped files OS cached information is written to disk).
+ //!Never throws. Returns false if operation could not be performed.
+ bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0, bool async = true);
//!Swaps the mapped_region with another
//!mapped region
void swap(mapped_region &other);
//!Returns the size of the page. This size is the minimum memory that
- //!will be used by the system when mapping a memory mappable source.
+ //!will be used by the system when mapping a memory mappable source and
+ //!will restrict the address and the offset to map.
static std::size_t get_page_size();
/// @cond
@@ -140,6 +149,13 @@
//!Closes a previously opened memory mapping. Never throws
void priv_close();
+ void* priv_map_address() const;
+ std::size_t priv_map_size() const;
+ bool priv_flush_param_check(std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const;
+ static void priv_size_from_mapping_size
+ (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size);
+ static offset_t priv_page_offset_addr_fixup(offset_t page_offset, const void *&addr);
+
template<int dummy>
struct page_size_holder
{
@@ -149,11 +165,10 @@
void* m_base;
std::size_t m_size;
- offset_t m_offset;
- offset_t m_extra_offset;
+ std::size_t m_page_offset;
mode_t m_mode;
- #if (defined BOOST_INTERPROCESS_WINDOWS)
- file_handle_t m_file_mapping_hnd;
+ #if defined(BOOST_INTERPROCESS_WINDOWS)
+ file_handle_t m_file_or_mapping_hnd;
#else
bool m_is_xsi;
#endif
@@ -161,6 +176,10 @@
friend class ipcdetail::interprocess_tester;
friend class ipcdetail::raw_mapped_region_creator;
void dont_close_on_destruction();
+ #if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+ template<int Dummy>
+ static void destroy_syncs_in_range(const void *addr, std::size_t size);
+ #endif
/// @endcond
};
@@ -175,20 +194,74 @@
inline std::size_t mapped_region::get_size() const
{ return m_size; }
-inline offset_t mapped_region::get_offset() const
-{ return m_offset; }
-
inline mode_t mapped_region::get_mode() const
{ return m_mode; }
inline void* mapped_region::get_address() const
{ return m_base; }
+inline void* mapped_region::priv_map_address() const
+{ return static_cast<char*>(m_base) - m_page_offset; }
+
+inline std::size_t mapped_region::priv_map_size() const
+{ return m_size + m_page_offset; }
+
+inline bool mapped_region::priv_flush_param_check
+ (std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const
+{
+ //Check some errors
+ if(m_base == 0)
+ return false;
+
+ if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){
+ return false;
+ }
+
+ //Update flush size if the user does not provide it
+ if(numbytes == 0){
+ numbytes = m_size - mapping_offset;
+ }
+ addr = (char*)this->priv_map_address() + mapping_offset;
+ numbytes += m_page_offset;
+ return true;
+}
+
+inline void mapped_region::priv_size_from_mapping_size
+ (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size)
+{
+ //Check if mapping size fits in the user address space
+ //as offset_t is the maximum file size and its signed.
+ if(mapping_size < offset ||
+ boost::uintmax_t(mapping_size - (offset - page_offset)) >
+ boost::uintmax_t(std::size_t(-1))){
+ error_info err(size_error);
+ throw interprocess_exception(err);
+ }
+ size = static_cast<std::size_t>(mapping_size - (offset - page_offset));
+}
+
+inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, const void *&address)
+{
+ //We can't map any offset so we have to obtain system's
+ //memory granularity
+ const std::size_t page_size = mapped_region::get_page_size();
+
+ //We calculate the difference between demanded and valid offset
+ //(always less than a page in std::size_t, thus, representable by std::size_t)
+ const std::size_t page_offset =
+ static_cast<std::size_t>(offset - (offset / page_size) * page_size);
+ //Update the mapping address
+ if(address){
+ address = static_cast<const char*>(address) - page_offset;
+ }
+ return page_offset;
+}
+
#if defined (BOOST_INTERPROCESS_WINDOWS)
inline mapped_region::mapped_region()
- : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only)
- , m_file_mapping_hnd(ipcdetail::invalid_file())
+ : m_base(0), m_size(0), m_page_offset(0), m_mode(read_only)
+ , m_file_or_mapping_hnd(ipcdetail::invalid_file())
{}
template<int dummy>
@@ -206,169 +279,146 @@
,offset_t offset
,std::size_t size
,const void *address)
- : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode)
- , m_file_mapping_hnd(ipcdetail::invalid_file())
+ : m_base(0), m_size(0), m_page_offset(0), m_mode(mode)
+ , m_file_or_mapping_hnd(ipcdetail::invalid_file())
{
mapping_handle_t mhandle = mapping.get_mapping_handle();
- file_handle_t native_mapping_handle = 0;
-
- //Set accesses
- unsigned long file_map_access = 0;
- unsigned long map_access = 0;
-
- switch(mode)
{
- case read_only:
- case read_private:
- file_map_access |= winapi::page_readonly;
- map_access |= winapi::file_map_read;
- break;
- case read_write:
- file_map_access |= winapi::page_readwrite;
- map_access |= winapi::file_map_write;
- break;
- case copy_on_write:
- file_map_access |= winapi::page_writecopy;
- map_access |= winapi::file_map_copy;
- break;
- default:
- {
- error_info err(mode_error);
- throw interprocess_exception(err);
- }
- break;
- }
-
- if(!mhandle.is_shm){
- //Update mapping size if the user does not specify it
- if(size == 0){
- __int64 total_size;
- if(!winapi::get_file_size
- (ipcdetail::file_handle_from_mapping_handle
- (mapping.get_mapping_handle()), total_size)){
- error_info err(winapi::get_last_error());
- throw interprocess_exception(err);
- }
+ file_handle_t native_mapping_handle = 0;
- if(static_cast<unsigned __int64>(total_size) >
- (std::numeric_limits<std::size_t>::max)()){
- error_info err(size_error);
+ //Set accesses
+ //For "create_file_mapping"
+ unsigned long protection = 0;
+ //For "mapviewoffile"
+ unsigned long map_access = 0;
+
+ switch(mode)
+ {
+ case read_only:
+ case read_private:
+ protection |= winapi::page_readonly;
+ map_access |= winapi::file_map_read;
+ break;
+ case read_write:
+ protection |= winapi::page_readwrite;
+ map_access |= winapi::file_map_write;
+ break;
+ case copy_on_write:
+ protection |= winapi::page_writecopy;
+ map_access |= winapi::file_map_copy;
+ break;
+ default:
+ {
+ error_info err(mode_error);
+ throw interprocess_exception(err);
+ }
+ break;
+ }
+
+ //For file mapping (including emulated shared memory through temporary files),
+ //the device is a file handle so we need to obtain file's size and call create_file_mapping
+ //to obtain the mapping handle.
+ //For files we don't need the file mapping after mapping the memory, as the file is there
+ //so we'll program the handle close
+ void * handle_to_close = winapi::invalid_handle_value;
+ if(!mhandle.is_shm){
+ //Create mapping handle
+ native_mapping_handle = winapi::create_file_mapping
+ ( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle())
+ , protection, 0, 0, 0);
+
+ //Check if all is correct
+ if(!native_mapping_handle){
+ error_info err = winapi::get_last_error();
throw interprocess_exception(err);
}
- size = static_cast<std::size_t>(total_size - offset);
+ handle_to_close = native_mapping_handle;
}
-
- //Create file mapping
- native_mapping_handle =
- winapi::create_file_mapping
- (ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle()), file_map_access, 0, 0, 0, 0);
-
- //Check if all is correct
- if(!native_mapping_handle){
- error_info err = winapi::get_last_error();
- this->priv_close();
- throw interprocess_exception(err);
+ else{
+ //For windows_shared_memory the device handle is already a mapping handle
+ //and we need to maintain it
+ native_mapping_handle = mhandle.handle;
}
- }
-
- //We can't map any offset so we have to obtain system's
- //memory granularity
- unsigned long granularity = 0;
- unsigned long foffset_low;
- unsigned long foffset_high;
+ //RAII handle close on scope exit
+ const winapi::handle_closer close_handle(handle_to_close);
+ (void)close_handle;
- winapi::system_info info;
- get_system_info(&info);
- granularity = info.dwAllocationGranularity;
-
- //Now we calculate valid offsets
- foffset_low = (unsigned long)(offset / granularity) * granularity;
- foffset_high = (unsigned long)(((offset / granularity) * granularity) >> 32);
-
- //We calculate the difference between demanded and valid offset
- m_extra_offset = (offset - (offset / granularity) * granularity);
+ const offset_t page_offset = priv_page_offset_addr_fixup(offset, address);
- //Store user values in memory
- m_offset = offset;
- m_size = size;
+ //Obtain mapping size if user provides 0 size
+ if(size == 0){
+ offset_t mapping_size;
+ if(!winapi::get_file_mapping_size(native_mapping_handle, mapping_size)){
+ error_info err = winapi::get_last_error();
+ throw interprocess_exception(err);
+ }
+ //This can throw
+ priv_size_from_mapping_size(mapping_size, offset, page_offset, size);
+ }
- //Update the mapping address
- if(address){
- address = static_cast<const char*>(address) - m_extra_offset;
- }
- if(mhandle.is_shm){
- //Windows shared memory needs the duplication of the handle if we want to
- //make mapped_region independent from the mappable device
- if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_mapping_hnd)){
+ //Map with new offsets and size
+ void *base = winapi::map_view_of_file_ex
+ (native_mapping_handle,
+ map_access,
+ offset - page_offset,
+ static_cast<std::size_t>(page_offset + size),
+ const_cast<void*>(address));
+ //Check error
+ if(!base){
error_info err = winapi::get_last_error();
- this->priv_close();
throw interprocess_exception(err);
}
- native_mapping_handle = m_file_mapping_hnd;
- }
-
- //Map with new offsets and size
- m_base = winapi::map_view_of_file_ex
- (native_mapping_handle,
- map_access,
- foffset_high,
- foffset_low,
- m_size ? static_cast<std::size_t>(m_extra_offset + m_size) : 0,
- const_cast<void*>(address));
-
- if(!mhandle.is_shm){
- //For files we don't need the file mapping anymore
- winapi::close_handle(native_mapping_handle);
- }
- //Check error
- if(!m_base){
+ //Calculate new base for the user
+ m_base = static_cast<char*>(base) + page_offset;
+ m_page_offset = page_offset;
+ m_size = size;
+ }
+ //Windows shared memory needs the duplication of the handle if we want to
+ //make mapped_region independent from the mappable device
+ //
+ //For mapped files, we duplicate the file handle to be able to FlushFileBuffers
+ if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_or_mapping_hnd)){
error_info err = winapi::get_last_error();
this->priv_close();
throw interprocess_exception(err);
}
-
- //Calculate new base for the user
- m_base = static_cast<char*>(m_base) + m_extra_offset;
}
-inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes)
+inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async)
{
- //Check some errors
- if(m_base == 0)
- return false;
-
- if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){
+ void *addr;
+ if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){
return false;
}
-
- //Update flush size if the user does not provide it
- if(m_size == 0){
- numbytes = 0;
+ //Flush it all
+ if(!winapi::flush_view_of_file(addr, numbytes)){
+ return false;
}
- else if(numbytes == 0){
- numbytes = m_size - mapping_offset;
+ //m_file_or_mapping_hnd can be a file handle or a mapping handle.
+ //so flushing file buffers has only sense for files...
+ else if(async && m_file_or_mapping_hnd != winapi::invalid_handle_value &&
+ winapi::get_file_type(m_file_or_mapping_hnd) == winapi::file_type_disk){
+ return winapi::flush_file_buffers(m_file_or_mapping_hnd);
}
-
- //Flush it all
- return winapi::flush_view_of_file
- (static_cast<char*>(m_base)+mapping_offset,
- static_cast<std::size_t>(numbytes));
+ return true;
}
inline void mapped_region::priv_close()
{
if(m_base){
- winapi::unmap_view_of_file(static_cast<char*>(m_base) - m_extra_offset);
+ void *addr = this->priv_map_address();
+ #if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+ mapped_region::destroy_syncs_in_range<0>(addr, m_size);
+ #endif
+ winapi::unmap_view_of_file(addr);
m_base = 0;
}
- #if (defined BOOST_INTERPROCESS_WINDOWS)
- if(m_file_mapping_hnd != ipcdetail::invalid_file()){
- winapi::close_handle(m_file_mapping_hnd);
- m_file_mapping_hnd = ipcdetail::invalid_file();
- }
- #endif
+ if(m_file_or_mapping_hnd != ipcdetail::invalid_file()){
+ winapi::close_handle(m_file_or_mapping_hnd);
+ m_file_or_mapping_hnd = ipcdetail::invalid_file();
+ }
}
inline void mapped_region::dont_close_on_destruction()
@@ -377,7 +427,7 @@
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
inline mapped_region::mapped_region()
- : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only), m_is_xsi(false)
+ : m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
{}
template<int dummy>
@@ -391,7 +441,7 @@
, offset_t offset
, std::size_t size
, const void *address)
- : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode), m_is_xsi(false)
+ : m_base(0), m_size(0), m_page_offset(0), m_mode(mode), m_is_xsi(false)
{
mapping_handle_t map_hnd = mapping.get_mapping_handle();
@@ -430,28 +480,25 @@
}
//Update members
m_base = base;
- m_offset = offset;
m_size = size;
m_mode = mode;
- m_extra_offset = 0;
+ m_page_offset = 0;
m_is_xsi = true;
return;
}
#endif //ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+
+ //We calculate the difference between demanded and valid offset
+ const offset_t page_offset = priv_page_offset_addr_fixup(offset, address);
+
if(size == 0){
struct ::stat buf;
if(0 != fstat(map_hnd.handle, &buf)){
error_info err(system_error_code());
throw interprocess_exception(err);
}
- std::size_t filesize = (std::size_t)buf.st_size;
- if((std::size_t)offset >= filesize){
- error_info err(size_error);
- throw interprocess_exception(err);
- }
-
- filesize -= offset;
- size = filesize;
+ //This can throw
+ priv_size_from_mapping_size(buf.st_size, offset, page_offset, size);
}
//Create new mapping
@@ -488,35 +535,23 @@
break;
}
- //We calculate the difference between demanded and valid offset
- const std::size_t page_size = this->get_page_size();
- const offset_t extra_offset = offset - (offset / page_size) * page_size;
-
-
- //Update the mapping address
- if(address){
- address = static_cast<const char*>(address) - extra_offset;
- }
-
//Map it to the address space
void* base = mmap ( const_cast<void*>(address)
- , static_cast<std::size_t>(extra_offset + size)
+ , static_cast<std::size_t>(page_offset + size)
, prot
, flags
, mapping.get_mapping_handle().handle
- , offset - extra_offset);
+ , offset - page_offset);
//Check if mapping was successful
if(base == MAP_FAILED){
error_info err = system_error_code();
- this->priv_close();
throw interprocess_exception(err);
}
//Calculate new base for the user
- m_base = static_cast<char*>(base) + extra_offset;
- m_extra_offset = extra_offset;
- m_offset = offset;
+ m_base = static_cast<char*>(base) + page_offset;
+ m_page_offset = page_offset;
m_size = size;
//Check for fixed mapping error
@@ -527,17 +562,14 @@
}
}
-inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes)
+inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async)
{
- if(mapping_offset >= m_size || (mapping_offset+numbytes)> m_size){
+ void *addr;
+ if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){
return false;
}
-
- if(numbytes == 0){
- numbytes = m_size - mapping_offset;
- }
//Flush it all
- return msync(static_cast<char*>(m_base)+mapping_offset, numbytes, MS_ASYNC) == 0;
+ return msync( addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0;
}
inline void mapped_region::priv_close()
@@ -551,7 +583,7 @@
return;
}
#endif //#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
- munmap(static_cast<char*>(m_base) - m_extra_offset, m_size + m_extra_offset);
+ munmap(this->priv_map_address(), this->priv_map_size());
m_base = 0;
}
}
@@ -577,11 +609,10 @@
{
ipcdetail::do_swap(this->m_base, other.m_base);
ipcdetail::do_swap(this->m_size, other.m_size);
- ipcdetail::do_swap(this->m_offset, other.m_offset);
- ipcdetail::do_swap(this->m_extra_offset, other.m_extra_offset);
+ ipcdetail::do_swap(this->m_page_offset, other.m_page_offset);
ipcdetail::do_swap(this->m_mode, other.m_mode);
#if (defined BOOST_INTERPROCESS_WINDOWS)
- ipcdetail::do_swap(this->m_file_mapping_hnd, other.m_file_mapping_hnd);
+ ipcdetail::do_swap(this->m_file_or_mapping_hnd, other.m_file_or_mapping_hnd);
#else
ipcdetail::do_swap(this->m_is_xsi, other.m_is_xsi);
#endif
@@ -603,3 +634,28 @@
#endif //BOOST_INTERPROCESS_MAPPED_REGION_HPP
+#ifndef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
+#define BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
+
+#if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+# include <boost/interprocess/sync/windows/sync_utils.hpp>
+# include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
+
+namespace boost {
+namespace interprocess {
+
+template<int Dummy>
+inline void mapped_region::destroy_syncs_in_range(const void *addr, std::size_t size)
+{
+ ipcdetail::sync_handles &handles =
+ ipcdetail::windows_intermodule_singleton<ipcdetail::sync_handles>::get();
+ handles.destroy_syncs_in_range(addr, size);
+}
+
+} //namespace interprocess {
+} //namespace boost {
+
+#endif //defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+
+#endif //#ifdef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
+
Modified: branches/release/boost/interprocess/sync/windows/mutex.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/mutex.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/mutex.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/sync/windows/named_condition.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/named_condition.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/named_condition.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/sync/windows/named_semaphore.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/named_semaphore.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/named_semaphore.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/sync/windows/named_sync.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/named_sync.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/named_sync.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/sync/windows/semaphore.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/semaphore.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/semaphore.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/sync/windows/sync_utils.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/sync_utils.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/sync_utils.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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: branches/release/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
==============================================================================
--- branches/release/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp (original)
+++ branches/release/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp 2012-07-16 04:55:08 EDT (Mon, 16 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()
{
Modified: branches/release/boost/interprocess/windows_shared_memory.hpp
==============================================================================
--- branches/release/boost/interprocess/windows_shared_memory.hpp (original)
+++ branches/release/boost/interprocess/windows_shared_memory.hpp 2012-07-16 04:55:08 EDT (Mon, 16 Jul 2012)
@@ -157,22 +157,26 @@
{
m_name = filename ? filename : "";
- unsigned long file_map_access = 0;
+ unsigned long protection = 0;
unsigned long map_access = 0;
switch(mode)
{
+ //"protection" is for "create_file_mapping"
+ //"map_access" is for "open_file_mapping"
+ //Add section query (strange that read or access does not grant it...)
+ //to obtain the size of the mapping. copy_on_write is equal to section_query.
case read_only:
- file_map_access |= winapi::page_readonly;
- map_access |= winapi::file_map_read;
+ protection |= winapi::page_readonly;
+ map_access |= winapi::file_map_read | winapi::section_query;
break;
case read_write:
- file_map_access |= winapi::page_readwrite;
- map_access |= winapi::file_map_write;
+ protection |= winapi::page_readwrite;
+ map_access |= winapi::file_map_write | winapi::section_query;
break;
case copy_on_write:
- file_map_access |= winapi::page_writecopy;
- map_access |= winapi::file_map_copy;
+ protection |= winapi::page_writecopy;
+ map_access |= winapi::file_map_copy;
break;
default:
{
@@ -184,16 +188,13 @@
switch(type){
case ipcdetail::DoOpen:
- m_handle = winapi::open_file_mapping
- (map_access, filename);
+ m_handle = winapi::open_file_mapping(map_access, filename);
break;
case ipcdetail::DoCreate:
case ipcdetail::DoOpenOrCreate:
{
- __int64 s = size;
- unsigned long high_size(s >> 32), low_size((boost::uint32_t)s);
m_handle = winapi::create_file_mapping
- ( winapi::invalid_handle_value, file_map_access, high_size, low_size, filename
+ ( winapi::invalid_handle_value, protection, size, filename
, (winapi::interprocess_security_attributes*)perm.get_permissions());
}
break;
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