|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r77912 - in trunk/boost/interprocess: detail smart_ptr smart_ptr/detail sync sync/detail sync/shm sync/windows
From: igaztanaga_at_[hidden]
Date: 2012-04-11 02:27:53
Author: igaztanaga
Date: 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
New Revision: 77912
URL: http://svn.boost.org/trac/boost/changeset/77912
Log:
Reworked native windows process-shared synchronization utilities.
Added:
trunk/boost/interprocess/detail/file_locking_helpers.hpp (contents, props changed)
trunk/boost/interprocess/detail/intermodule_singleton_common.hpp (contents, props changed)
trunk/boost/interprocess/detail/managed_global_memory.hpp (contents, props changed)
trunk/boost/interprocess/detail/portable_intermodule_singleton.hpp (contents, props changed)
trunk/boost/interprocess/detail/windows_intermodule_singleton.hpp (contents, props changed)
trunk/boost/interprocess/sync/detail/
trunk/boost/interprocess/sync/detail/condition_algorithm_8a.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/named_condition.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/named_mutex.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/named_recursive_mutex.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/named_semaphore.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/named_sync.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp (contents, props changed)
trunk/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp (contents, props changed)
Text files modified:
trunk/boost/interprocess/detail/atomic.hpp | 169 ++---
trunk/boost/interprocess/detail/config_begin.hpp | 1
trunk/boost/interprocess/detail/intermodule_singleton.hpp | 1142 ---------------------------------------
trunk/boost/interprocess/detail/os_file_functions.hpp | 12
trunk/boost/interprocess/detail/pointer_type.hpp | 2
trunk/boost/interprocess/detail/preprocessor.hpp | 30
trunk/boost/interprocess/detail/robust_emulation.hpp | 4
trunk/boost/interprocess/detail/tmp_dir_helpers.hpp | 163 ++--
trunk/boost/interprocess/detail/win32_api.hpp | 29
trunk/boost/interprocess/detail/workaround.hpp | 125 +--
trunk/boost/interprocess/smart_ptr/detail/shared_count.hpp | 2
trunk/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp | 2
trunk/boost/interprocess/smart_ptr/shared_ptr.hpp | 7
trunk/boost/interprocess/sync/interprocess_condition.hpp | 6
trunk/boost/interprocess/sync/interprocess_mutex.hpp | 6
trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp | 6
trunk/boost/interprocess/sync/interprocess_semaphore.hpp | 6
trunk/boost/interprocess/sync/named_condition.hpp | 16
trunk/boost/interprocess/sync/named_mutex.hpp | 27
trunk/boost/interprocess/sync/named_recursive_mutex.hpp | 14
trunk/boost/interprocess/sync/named_semaphore.hpp | 11
trunk/boost/interprocess/sync/shm/named_condition.hpp | 11
trunk/boost/interprocess/sync/windows/condition.hpp | 311 +---------
trunk/boost/interprocess/sync/windows/mutex.hpp | 55 -
trunk/boost/interprocess/sync/windows/semaphore.hpp | 57 -
trunk/boost/interprocess/sync/windows/sync_utils.hpp | 39
26 files changed, 440 insertions(+), 1813 deletions(-)
Modified: trunk/boost/interprocess/detail/atomic.hpp
==============================================================================
--- trunk/boost/interprocess/detail/atomic.hpp (original)
+++ trunk/boost/interprocess/detail/atomic.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -117,23 +117,6 @@
: "cc");
return prev;
-/*
- asm volatile( "lock\n\t"
- "cmpxchg %3,%1"
- : "=a" (prev), "=m" (*(mem))
- : "0" (prev), "r" (with)
- : "memory", "cc");
-*/
-/*
- boost::uint32_t prev;
-
- asm volatile ("lock; cmpxchgl %1, %2"
- : "=a" (prev)
- : "r" (with), "m" (*(mem)), "0"(cmp));
- asm volatile("" : : : "memory");
-
- return prev;
-*/
}
//! Atomically add 'val' to an boost::uint32_t
@@ -158,14 +141,6 @@
);
return r;
-/*
- asm volatile( "lock\n\t; xaddl %0,%1"
- : "=r"(val), "=m"(*mem)
- : "0"(val), "m"(*mem));
- asm volatile("" : : : "memory");
-
- return val;
-*/
}
//! Atomically increment an apr_uint32_t by 1
@@ -208,17 +183,14 @@
{
boost::uint32_t prev, temp;
- asm volatile ("0:\n\t" // retry local label
- "lwarx %0,0,%2\n\t" // load prev and reserve
- "add %1,%0,%3\n\t" // temp = prev + val
- "stwcx. %1,0,%2\n\t" // conditionally store
- "bne- 0b" // start over if we lost
- // the reservation
- //XXX find a cleaner way to define the temp
- //it's not an output
- : "=&r" (prev), "=&r" (temp) // output, temp
- : "b" (mem), "r" (val) // inputs
- : "memory", "cc"); // clobbered
+ asm volatile ("1:\n\t"
+ "lwarx %0,0,%2\n\t"
+ "add %1,%0,%3\n\t"
+ "stwcx. %1,0,%2\n\t"
+ "bne- 1b"
+ : "=&r" (prev), "=&r" (temp)
+ : "b" (mem), "r" (val)
+ : "cc", "memory");
return prev;
}
@@ -233,19 +205,16 @@
{
boost::uint32_t prev;
- asm volatile ("0:\n\t" // retry local label
- "lwarx %0,0,%1\n\t" // load prev and reserve
- "cmpw %0,%3\n\t" // does it match cmp?
- "bne- 1f\n\t" // ...no, bail out
- "stwcx. %2,0,%1\n\t" // ...yes, conditionally
- // store with
- "bne- 0b\n\t" // start over if we lost
- // the reservation
- "1:" // exit local label
-
- : "=&r"(prev) // output
- : "b" (mem), "r" (with), "r"(cmp) // inputs
- : "memory", "cc"); // clobbered
+ asm volatile ("1:\n\t"
+ "lwarx %0,0,%1\n\t"
+ "cmpw %0,%3\n\t"
+ "bne- 2f\n\t"
+ "stwcx. %2,0,%1\n\t"
+ "bne- 1b\n\t"
+ "2:"
+ : "=&r"(prev)
+ : "b" (mem), "r"(cmp), "r" (with)
+ : "cc", "memory");
return prev;
}
@@ -275,56 +244,6 @@
} //namespace interprocess{
} //namespace boost{
-#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
-
-namespace boost {
-namespace interprocess {
-namespace ipcdetail{
-
-//! Atomically add 'val' to an boost::uint32_t
-//! "mem": pointer to the object
-//! "val": amount to add
-//! Returns the old value pointed to by mem
-inline boost::uint32_t atomic_add32
- (volatile boost::uint32_t *mem, boost::uint32_t val)
-{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); }
-
-//! Atomically increment an apr_uint32_t by 1
-//! "mem": pointer to the object
-//! Returns the old value pointed to by mem
-inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
-{ return atomic_add32(mem, 1); }
-
-//! Atomically decrement an boost::uint32_t by 1
-//! "mem": pointer to the atomic value
-//! Returns the old value pointed to by mem
-inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
-{ return atomic_add32(mem, (boost::uint32_t)-1); }
-
-//! Atomically read an boost::uint32_t from memory
-inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
-{ return *mem; }
-
-//! Compare an boost::uint32_t's value with "cmp".
-//! If they are the same swap the value with "with"
-//! "mem": pointer to the value
-//! "with" what to swap it with
-//! "cmp": the value to compare it to
-//! Returns the old value of *mem
-inline boost::uint32_t atomic_cas32
- (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
-{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); }
-
-//! Atomically set an boost::uint32_t in memory
-//! "mem": pointer to the object
-//! "param": val value that the object will assume
-inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
-{ *mem = val; }
-
-} //namespace ipcdetail{
-} //namespace interprocess{
-} //namespace boost{
-
#elif (defined(sun) || defined(__sun))
#include <atomic.h>
@@ -561,7 +480,57 @@
} //namespace ipcdetail
} //namespace interprocess
-} //namespace boost
+} //namespace boost
+
+#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32
+ (volatile boost::uint32_t *mem, boost::uint32_t val)
+{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); }
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, 1); }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{ return atomic_add32(mem, (boost::uint32_t)-1); }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{ return *mem; }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+ (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{ *mem = val; }
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
#else
Modified: trunk/boost/interprocess/detail/config_begin.hpp
==============================================================================
--- trunk/boost/interprocess/detail/config_begin.hpp (original)
+++ trunk/boost/interprocess/detail/config_begin.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -44,4 +44,5 @@
// with /GR-; unpredictable behavior may result
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
#pragma warning (disable : 4671) // the copy constructor is inaccessible
+ #pragma warning (disable : 4250) // inherits 'x' via dominance
#endif
Added: trunk/boost/interprocess/detail/file_locking_helpers.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/file_locking_helpers.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,298 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
+#define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <sstream>
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <cstddef>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+#include <fcntl.h>
+#include <io.h>
+#include <sys/locking.h>
+
+#else //defined(BOOST_INTERPROCESS_WINDOWS)
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#endif //defined(BOOST_INTERPROCESS_WINDOWS)
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+struct locking_file_serial_id
+{
+ int fd;
+ unsigned long dwVolumeSerialNumber;
+ unsigned long nFileIndexHigh;
+ unsigned long nFileIndexLow;
+ //This reference count counts the number of modules attached
+ //to the shared memory and lock file. This serves to unlink
+ //the locking file and shared memory when all modules are
+ //done with the global memory (shared memory)
+ volatile boost::uint32_t modules_attached_to_gmem_count;
+};
+
+inline bool lock_locking_file(int fd)
+{
+ int ret = 0;
+ while(ret != 0 && errno == EDEADLK){
+ ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/);
+ }
+ return 0 == ret;
+}
+
+inline bool try_lock_locking_file(int fd)
+{
+ return 0 == _locking(fd, _LK_NBLCK , 1);
+}
+
+inline int open_or_create_and_lock_file(const char *name)
+{
+ permissions p;
+ p.set_unrestricted();
+ while(1){
+ file_handle_t handle = create_or_open_file(name, read_write, p);
+ int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
+ if(fd < 0){
+ close_file(handle);
+ return fd;
+ }
+ if(!try_lock_locking_file(fd)){
+ _close(fd);
+ return -1;
+ }
+ struct _stat s;
+ if(0 == _stat(name, &s)){
+ return fd;
+ }
+ else{
+ _close(fd);
+ }
+ }
+}
+
+inline int try_open_and_lock_file(const char *name)
+{
+ file_handle_t handle = open_existing_file(name, read_write);
+ int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
+ if(fd < 0){
+ close_file(handle);
+ return fd;
+ }
+ if(!try_lock_locking_file(fd)){
+ _close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+inline void close_lock_file(int fd)
+{ _close(fd); }
+
+inline bool is_valid_fd(int fd)
+{
+ struct _stat s;
+ return EBADF != _fstat(fd, &s);
+}
+
+inline bool is_normal_file(int fd)
+{
+ if(_isatty(fd))
+ return false;
+ struct _stat s;
+ if(0 != _fstat(fd, &s))
+ return false;
+ return 0 != (s.st_mode & _S_IFREG);
+}
+
+inline std::size_t get_size(int fd)
+{
+ struct _stat s;
+ if(0 != _fstat(fd, &s))
+ return 0u;
+ return (std::size_t)s.st_size;
+}
+
+inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
+{
+ winapi::interprocess_by_handle_file_information info;
+ if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
+ return false;
+ id.fd = fd;
+ id.dwVolumeSerialNumber = info.dwVolumeSerialNumber;
+ id.nFileIndexHigh = info.nFileIndexHigh;
+ id.nFileIndexLow = info.nFileIndexLow;
+ id.modules_attached_to_gmem_count = 1; //Initialize attached count
+ return true;
+}
+
+inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
+{
+ winapi::interprocess_by_handle_file_information info;
+ if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
+ return false;
+
+ return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber &&
+ id.nFileIndexHigh == info.nFileIndexHigh &&
+ id.nFileIndexLow == info.nFileIndexLow;
+}
+
+#else //UNIX
+
+struct locking_file_serial_id
+{
+ int fd;
+ dev_t st_dev;
+ ino_t st_ino;
+ //This reference count counts the number of modules attached
+ //to the shared memory and lock file. This serves to unlink
+ //the locking file and shared memory when all modules are
+ //done with the global memory (shared memory)
+ volatile boost::uint32_t modules_attached_to_gmem_count;
+};
+
+inline bool lock_locking_file(int fd)
+{
+ int ret = 0;
+ while(ret != 0 && errno != EINTR){
+ struct flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ ret = fcntl (fd, F_SETLKW, &lock);
+ }
+ return 0 == ret;
+}
+
+inline bool try_lock_locking_file(int fd)
+{
+ struct flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ return 0 == fcntl (fd, F_SETLK, &lock);
+}
+
+inline int open_or_create_and_lock_file(const char *name)
+{
+ permissions p;
+ p.set_unrestricted();
+ while(1){
+ int fd = create_or_open_file(name, read_write, p);
+ if(fd < 0){
+ return fd;
+ }
+ if(!try_lock_locking_file(fd)){
+ close(fd);
+ return -1;
+ }
+ struct stat s;
+ if(0 == stat(name, &s)){
+ return fd;
+ }
+ else{
+ close(fd);
+ }
+ }
+}
+
+inline int try_open_and_lock_file(const char *name)
+{
+ int fd = open_existing_file(name, read_write);
+ if(fd < 0){
+ return fd;
+ }
+ if(!try_lock_locking_file(fd)){
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+inline void close_lock_file(int fd)
+{ close(fd); }
+
+inline bool is_valid_fd(int fd)
+{
+ struct stat s;
+ return EBADF != fstat(fd, &s);
+}
+
+inline bool is_normal_file(int fd)
+{
+ struct stat s;
+ if(0 != fstat(fd, &s))
+ return false;
+ return 0 != (s.st_mode & S_IFREG);
+}
+
+inline std::size_t get_size(int fd)
+{
+ struct stat s;
+ if(0 != fstat(fd, &s))
+ return 0u;
+ return (std::size_t)s.st_size;
+}
+
+inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
+{
+ struct stat s;
+ if(0 != fstat(fd, &s))
+ return false;
+ id.fd = fd;
+ id.st_dev = s.st_dev;
+ id.st_ino = s.st_ino;
+ id.modules_attached_to_gmem_count = 1; //Initialize attached count
+ return true;
+}
+
+inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
+{
+ struct stat info;
+ if(0 != fstat(fd, &info))
+ return false;
+
+ return id.st_dev == info.st_dev &&
+ id.st_ino == info.st_ino;
+}
+
+#endif
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
Modified: trunk/boost/interprocess/detail/intermodule_singleton.hpp
==============================================================================
--- trunk/boost/interprocess/detail/intermodule_singleton.hpp (original)
+++ trunk/boost/interprocess/detail/intermodule_singleton.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -18,1150 +18,15 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#if defined(BOOST_INTERPROCESS_WINDOWS)
-#include <boost/interprocess/windows_shared_memory.hpp>
-#endif
-
-#include <boost/interprocess/shared_memory_object.hpp>
-
-#include <boost/interprocess/offset_ptr.hpp>
-#include <boost/interprocess/sync/spin/mutex.hpp>
-#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
-#include <boost/interprocess/detail/managed_memory_impl.hpp>
-#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
-#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
-#include <boost/interprocess/indexes/iset_index.hpp>
-#include <boost/interprocess/creation_tags.hpp>
-#include <boost/interprocess/permissions.hpp>
-
-
-#include <boost/interprocess/detail/atomic.hpp>
-#include <boost/interprocess/detail/os_thread_functions.hpp>
-#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
-#include <boost/interprocess/detail/os_file_functions.hpp>
-#include <boost/interprocess/detail/mpl.hpp>
-#include <boost/type_traits/type_with_alignment.hpp>
-#include <boost/assert.hpp>
-#include <cstddef>
-#include <cstdio>
-#include <cstring>
-#include <string>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#if defined(BOOST_INTERPROCESS_WINDOWS)
-#include <fcntl.h>
-#include <io.h>
-
-#include <sys/locking.h>
-#else
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
+#ifdef BOOST_INTERPROCESS_WINDOWS
+ #include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
#endif
+#include <boost/interprocess/detail/portable_intermodule_singleton.hpp>
namespace boost{
namespace interprocess{
namespace ipcdetail{
-struct intermodule_singleton_mutex_family
-{
- typedef boost::interprocess::ipcdetail::spin_mutex mutex_type;
- typedef boost::interprocess::ipcdetail::spin_recursive_mutex recursive_mutex_type;
-};
-
-struct intermodule_types
-{
- //We must use offset_ptr since a loaded DLL can map the singleton holder shared memory
- //at a different address than other DLLs/main executables
- typedef rbtree_best_fit<intermodule_singleton_mutex_family, offset_ptr<void> > mem_algo;
- template<class Device, bool FileBased>
- struct open_or_create
- {
- typedef managed_open_or_create_impl
- <Device, mem_algo::Alignment, FileBased> type;
- };
-};
-
-template<class Device, bool FileBased>
-class basic_managed_global_memory
- : public basic_managed_memory_impl
- < char
- , intermodule_types::mem_algo
- , iset_index
- , intermodule_types::open_or_create<Device, FileBased>::type::ManagedOpenOrCreateUserOffset
- >
- , private intermodule_types::open_or_create<Device, FileBased>::type
-{
- /// @cond
- typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t;
-
- typedef basic_managed_memory_impl
- < char
- , intermodule_types::mem_algo
- , iset_index
- , base2_t::ManagedOpenOrCreateUserOffset
- > base_t;
-
- typedef create_open_func<base_t> create_open_func_t;
-
- basic_managed_global_memory *get_this_pointer()
- { return this; }
-
- public:
- typedef typename base_t::size_type size_type;
-
- private:
- typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
- BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory)
- /// @endcond
-
- public: //functions
-/*
- basic_managed_global_memory()
- {}
-
- basic_managed_global_memory(create_only_t create_only, const char *name,
- size_type size, const void *addr = 0, const permissions& perm = permissions())
- : base_t()
- , base2_t(create_only, name, size, read_write, addr,
- create_open_func_t(get_this_pointer(), DoCreate), perm)
- {}
-*/
- basic_managed_global_memory (open_or_create_t open_or_create,
- const char *name, size_type size,
- const void *addr = 0, const permissions& perm = permissions())
- : base_t()
- , base2_t(open_or_create, name, size, read_write, addr,
- create_open_func_t(get_this_pointer(),
- DoOpenOrCreate), perm)
- {}
-
- basic_managed_global_memory (open_only_t open_only, const char* name,
- const void *addr = 0)
- : base_t()
- , base2_t(open_only, name, read_write, addr,
- create_open_func_t(get_this_pointer(),
- DoOpen))
- {}
-
-/*
- basic_managed_global_memory (open_copy_on_write_t, const char* name,
- const void *addr = 0)
- : base_t()
- , base2_t(open_only, name, copy_on_write, addr,
- create_open_func_t(get_this_pointer(),
- DoOpen))
- {}
-
- //!Connects to a created shared memory and its segment manager.
- //!in read-only mode.
- //!This can throw.
- basic_managed_global_memory (open_read_only_t, const char* name,
- const void *addr = 0)
- : base_t()
- , base2_t(open_only, name, read_only, addr,
- create_open_func_t(get_this_pointer(),
- DoOpen))
- {}
-
- //!Moves the ownership of "moved"'s managed memory to *this.
- //!Does not throw
- basic_managed_global_memory(BOOST_RV_REF(basic_managed_global_memory) moved)
- {
- basic_managed_global_memory tmp;
- this->swap(moved);
- tmp.swap(moved);
- }
-
- //!Moves the ownership of "moved"'s managed memory to *this.
- //!Does not throw
- basic_managed_global_memory &operator=(BOOST_RV_REF(basic_managed_global_memory) moved)
- {
- basic_managed_global_memory tmp(boost::move(moved));
- this->swap(tmp);
- return *this;
- }*/
-};
-
-#if defined(BOOST_INTERPROCESS_WINDOWS)
-typedef basic_managed_global_memory<windows_shared_memory, false> windows_managed_global_memory;
-#endif
-
-typedef basic_managed_global_memory<shared_memory_object, true> managed_global_memory;
-
-namespace file_locking_helpers {
-
-inline void get_pid_creation_time_str(std::string &s)
-{
- std::stringstream stream;
- stream << get_current_process_id() << '_';
- stream.precision(6);
- stream << std::fixed << get_current_process_creation_time();
- s = stream.str();
-}
-
-inline void create_tmp_subdir_and_get_pid_based_filepath(const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false)
-{
- //Let's create a lock file for each process gmem that will mark if
- //the process is alive or not
- create_tmp_and_clean_old(s);
- s += "/";
- s += subdir_name;
- if(!open_or_create_directory(s.c_str())){
- throw interprocess_exception(error_info(system_error_code()));
- }
- s += "/";
- s += file_prefix;
- if(creation_time){
- std::string sstamp;
- get_pid_creation_time_str(sstamp);
- s += sstamp;
- }
- else{
- pid_str_t pid_str;
- get_pid_str(pid_str, pid);
- s += pid_str;
- }
-}
-
-inline bool check_if_filename_complies_with_pid
- (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false)
-{
- //Check if filename complies with lock file name pattern
- std::string fname(filename);
- std::string fprefix(prefix);
- if(fname.size() <= fprefix.size()){
- return false;
- }
- fname.resize(fprefix.size());
- if(fname != fprefix){
- return false;
- }
-
- //If not our lock file, delete it if we can lock it
- fname = filename;
- fname.erase(0, fprefix.size());
- pid_str_t pid_str;
- get_pid_str(pid_str, pid);
- file_suffix = pid_str;
- if(creation_time){
- std::size_t p = fname.find('_');
- if (p == std::string::npos){
- return false;
- }
- std::string save_suffix(fname);
- fname.erase(p);
- fname.swap(file_suffix);
- bool ret = (file_suffix == fname);
- file_suffix.swap(save_suffix);
- return ret;
- }
- else{
- fname.swap(file_suffix);
- return (file_suffix == fname);
- }
-}
-
-} //file_locking_helpers
-
-namespace intermodule_singleton_helpers {
-
-const int GMemMarkToBeRemoved = -1;
-const int GMemNotPresent = -2;
-
-inline const char *get_lock_file_subdir_name()
-{ return "gmem"; }
-
-inline const char *get_lock_file_base_name()
-{ return "lck"; }
-
-inline void create_and_get_singleton_lock_file_path(std::string &s)
-{
- file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath
- (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true);
-}
-
-inline const char *get_shm_base_name()
-{ return "bip.gmem.shm."; }
-
-inline void get_shm_name(std::string &shm_name)
-{
- file_locking_helpers::get_pid_creation_time_str(shm_name);
- shm_name.insert(0, get_shm_base_name());
-}
-
-inline std::size_t get_shm_size()
-{ return 65536; }
-
-template<class ManagedShMem>
-struct managed_sh_dependant
-{
- static void apply_gmem_erase_logic(const char *filepath, const char *filename);
-
- static bool remove_old_gmem()
- {
- std::string refcstrRootDirectory;
- tmp_folder(refcstrRootDirectory);
- refcstrRootDirectory += "/";
- refcstrRootDirectory += get_lock_file_subdir_name();
- return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic);
- }
-};
-
-#if defined(BOOST_INTERPROCESS_WINDOWS)
-
-template<>
-struct managed_sh_dependant<windows_managed_global_memory>
-{
- static void apply_gmem_erase_logic(const char *, const char *){}
-
- static bool remove_old_gmem()
- { return true; }
-};
-
-
-struct locking_file_serial_id
-{
- int fd;
- unsigned long dwVolumeSerialNumber;
- unsigned long nFileIndexHigh;
- unsigned long nFileIndexLow;
- //This reference count counts the number of modules attached
- //to the shared memory and lock file. This serves to unlink
- //the locking file and shared memory when all modules are
- //done with the global memory (shared memory)
- volatile boost::uint32_t modules_attached_to_gmem_count;
-};
-
-inline bool lock_locking_file(int fd)
-{
- int ret = 0;
- while(ret != 0 && errno == EDEADLK){
- ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/);
- }
- return 0 == ret;
-}
-
-inline bool try_lock_locking_file(int fd)
-{
- return 0 == _locking(fd, _LK_NBLCK , 1);
-}
-
-inline int open_or_create_and_lock_file(const char *name)
-{
- permissions p;
- p.set_unrestricted();
- while(1){
- file_handle_t handle = create_or_open_file(name, read_write, p);
- int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
- if(fd < 0){
- close_file(handle);
- return fd;
- }
- if(!try_lock_locking_file(fd)){
- _close(fd);
- return -1;
- }
- struct _stat s;
- if(0 == _stat(name, &s)){
- return fd;
- }
- else{
- _close(fd);
- }
- }
-}
-
-inline int try_open_and_lock_file(const char *name)
-{
- file_handle_t handle = open_existing_file(name, read_write);
- int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
- if(fd < 0){
- close_file(handle);
- return fd;
- }
- if(!try_lock_locking_file(fd)){
- _close(fd);
- return -1;
- }
- return fd;
-}
-
-inline void close_lock_file(int fd)
-{ _close(fd); }
-
-inline bool is_valid_fd(int fd)
-{
- struct _stat s;
- return EBADF != _fstat(fd, &s);
-}
-
-inline bool is_normal_file(int fd)
-{
- if(_isatty(fd))
- return false;
- struct _stat s;
- if(0 != _fstat(fd, &s))
- return false;
- return 0 != (s.st_mode & _S_IFREG);
-}
-
-inline std::size_t get_size(int fd)
-{
- struct _stat s;
- if(0 != _fstat(fd, &s))
- return 0u;
- return (std::size_t)s.st_size;
-}
-
-inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
-{
- winapi::interprocess_by_handle_file_information info;
- if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
- return false;
- id.fd = fd;
- id.dwVolumeSerialNumber = info.dwVolumeSerialNumber;
- id.nFileIndexHigh = info.nFileIndexHigh;
- id.nFileIndexLow = info.nFileIndexLow;
- id.modules_attached_to_gmem_count = 1; //Initialize attached count
- return true;
-}
-
-inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
-{
- winapi::interprocess_by_handle_file_information info;
- if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
- return false;
-
- return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber &&
- id.nFileIndexHigh == info.nFileIndexHigh &&
- id.nFileIndexLow == info.nFileIndexLow;
-}
-
-#else //UNIX
-
-struct locking_file_serial_id
-{
- int fd;
- dev_t st_dev;
- ino_t st_ino;
- //This reference count counts the number of modules attached
- //to the shared memory and lock file. This serves to unlink
- //the locking file and shared memory when all modules are
- //done with the global memory (shared memory)
- volatile boost::uint32_t modules_attached_to_gmem_count;
-};
-
-inline bool lock_locking_file(int fd)
-{
- int ret = 0;
- while(ret != 0 && errno != EINTR){
- struct flock lock;
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 1;
- ret = fcntl (fd, F_SETLKW, &lock);
- }
- return 0 == ret;
-}
-
-inline bool try_lock_locking_file(int fd)
-{
- struct flock lock;
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 1;
- return 0 == fcntl (fd, F_SETLK, &lock);
-}
-
-inline int open_or_create_and_lock_file(const char *name)
-{
- permissions p;
- p.set_unrestricted();
- while(1){
- int fd = create_or_open_file(name, read_write, p);
- if(fd < 0){
- return fd;
- }
- if(!try_lock_locking_file(fd)){
- close(fd);
- return -1;
- }
- struct stat s;
- if(0 == stat(name, &s)){
- return fd;
- }
- else{
- close(fd);
- }
- }
-}
-
-inline int try_open_and_lock_file(const char *name)
-{
- int fd = open_existing_file(name, read_write);
- if(fd < 0){
- return fd;
- }
- if(!try_lock_locking_file(fd)){
- close(fd);
- return -1;
- }
- return fd;
-}
-
-inline void close_lock_file(int fd)
-{ close(fd); }
-
-inline bool is_valid_fd(int fd)
-{
- struct stat s;
- return EBADF != fstat(fd, &s);
-}
-
-inline bool is_normal_file(int fd)
-{
- struct stat s;
- if(0 != fstat(fd, &s))
- return false;
- return 0 != (s.st_mode & S_IFREG);
-}
-
-inline std::size_t get_size(int fd)
-{
- struct stat s;
- if(0 != fstat(fd, &s))
- return 0u;
- return (std::size_t)s.st_size;
-}
-
-inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
-{
- struct stat s;
- if(0 != fstat(fd, &s))
- return false;
- id.fd = fd;
- id.st_dev = s.st_dev;
- id.st_ino = s.st_ino;
- id.modules_attached_to_gmem_count = 1; //Initialize attached count
- return true;
-}
-
-inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
-{
- struct stat info;
- if(0 != fstat(fd, &info))
- return false;
-
- return id.st_dev == info.st_dev &&
- id.st_ino == info.st_ino;
-}
-
-#endif
-
-template<class ManagedShMem>
-struct gmem_erase_func
-{
- gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, ManagedShMem & shm)
- :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm)
- {}
-
- void operator()()
- {
- locking_file_serial_id *pserial_id = shm_.template find<locking_file_serial_id>("lock_file_fd").first;
- if(pserial_id){
- pserial_id->fd = GMemMarkToBeRemoved;
- }
- delete_file(singleton_lock_file_path_);
- shared_memory_object::remove(shm_name_);
- }
-
- const char * const shm_name_;
- const char * const singleton_lock_file_path_;
- ManagedShMem & shm_;
-};
-
-//This function applies shared memory erasure logic based on the passed lock file.
-template<class ManagedShMem>
-void managed_sh_dependant<ManagedShMem>::
- apply_gmem_erase_logic(const char *filepath, const char *filename)
-{
- int fd = GMemMarkToBeRemoved;
- try{
- std::string str;
- //If the filename is current process lock file, then avoid it
- if(file_locking_helpers::check_if_filename_complies_with_pid
- (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){
- return;
- }
- //Open and lock the other process' lock file
- fd = try_open_and_lock_file(filepath);
- if(fd < 0){
- return;
- }
- //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());
- try{
- ManagedShMem shm(open_only, str.c_str());
- gmem_erase_func<ManagedShMem> func(str.c_str(), filepath, shm);
- shm.try_atomic_func(func);
- }
- catch(interprocess_exception &e){
- //If shared memory is not found erase the lock file
- if(e.get_error_code() == not_found_error){
- delete_file(filepath);
- }
- }
- }
- catch(...){
-
- }
- if(fd >= 0){
- close_lock_file(fd);
- }
-}
-
-} //namespace intermodule_singleton_helpers {
-
-
-
-namespace intermodule_singleton_helpers {
-
-//The lock file logic creates uses a unique instance to a file
-template <class ManagedShMem>
-struct lock_file_logic
-{
- lock_file_logic(ManagedShMem &shm)
- : mshm(shm)
- { shm.atomic_func(*this); }
-
- void operator()(void)
- {
- retry_with_new_shm = false;
-
- //First find the file locking descriptor id
- locking_file_serial_id *pserial_id =
- mshm.template find<locking_file_serial_id>("lock_file_fd").first;
-
- int fd;
- //If not found schedule a creation
- if(!pserial_id){
- fd = GMemNotPresent;
- }
- //Else get it
- else{
- fd = pserial_id->fd;
- }
- //If we need to create a new one, do it
- if(fd == GMemNotPresent){
- std::string lck_str;
- //Create a unique current pid based lock file path
- create_and_get_singleton_lock_file_path(lck_str);
- //Open or create and lock file
- int fd = intermodule_singleton_helpers::open_or_create_and_lock_file(lck_str.c_str());
- //If failed, write a bad file descriptor to notify other modules that
- //something was wrong and unlink shared memory. Mark the function object
- //to tell caller to retry with another shared memory
- if(fd < 0){
- this->register_lock_file(GMemMarkToBeRemoved);
- std::string s;
- get_shm_name(s);
- shared_memory_object::remove(s.c_str());
- retry_with_new_shm = true;
- }
- //If successful, register the file descriptor
- else{
- this->register_lock_file(fd);
- }
- }
- //If the fd was invalid (maybe a previous try failed) notify caller that
- //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;
- }
- //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,
- //then it's an old shm from an old process with the same pid.
- //If that's the case, mark it as invalid
- else if(!is_valid_fd(fd) ||
- !is_normal_file(fd) ||
- 0 != get_size(fd) ||
- !compare_file_serial(fd, *pserial_id)){
- pserial_id->fd = GMemMarkToBeRemoved;
- std::string s;
- get_shm_name(s);
- shared_memory_object::remove(s.c_str());
- retry_with_new_shm = true;
- }
- else{
- //If the lock file is ok, increment reference count of
- //attached modules to shared memory
- atomic_inc32(&pserial_id->modules_attached_to_gmem_count);
- }
- }
-
- private:
- locking_file_serial_id * register_lock_file(int fd)
- {
- locking_file_serial_id *pinfo = mshm.template construct<locking_file_serial_id>("lock_file_fd")();
- fill_file_serial_id(fd, *pinfo);
- return pinfo;
- }
-
- public:
- ManagedShMem &mshm;
- bool retry_with_new_shm;
-};
-
-#if defined(BOOST_INTERPROCESS_WINDOWS)
-
-template<>
-struct lock_file_logic<windows_managed_global_memory>
-{
- lock_file_logic(windows_managed_global_memory &)
- : retry_with_new_shm(false)
- {}
-
- void operator()(void){}
- const bool retry_with_new_shm;
-};
-
-#endif
-
-} //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 reference counted shared memory
-//to be used by all instances
-
-template<class ManagedShMem>
-class intermodule_singleton_common
-{
- public:
- typedef void*(singleton_constructor_t)(ManagedShMem &);
- typedef void (singleton_destructor_t)(void *, ManagedShMem &);
-
- static const ::boost::uint32_t Uninitialized = 0u;
- static const ::boost::uint32_t Initializing = 1u;
- static const ::boost::uint32_t Initialized = 2u;
- static const ::boost::uint32_t Broken = 3u;
-
- static void finalize_singleton_logic(void *ptr, singleton_destructor_t destructor)
- {
- if(ptr)
- destructor(ptr, get_shm());
- //If this is the last singleton of this module
- //apply shm 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();
- }
- }
-
- static void initialize_singleton_logic
- (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t ini_func);
-
- private:
- static ManagedShMem &get_shm()
- {
- return *static_cast<ManagedShMem *>(static_cast<void *>(&mem_holder.shm_mem));
- }
-
- static void initialize_shm();
- static void destroy_shm();
- //Static data, zero-initalized without any dependencies
- //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
- static volatile boost::uint32_t this_module_shm_initialized;
- static struct mem_holder_t
- {
- ::boost::detail::max_align aligner;
- char shm_mem [sizeof(ManagedShMem)];
- } mem_holder;
-};
-
-template<class ManagedShMem>
-volatile boost::uint32_t intermodule_singleton_common<ManagedShMem>::this_module_singleton_count;
-
-template<class ManagedShMem>
-volatile boost::uint32_t intermodule_singleton_common<ManagedShMem>::this_module_shm_initialized;
-
-template<class ManagedShMem>
-typename intermodule_singleton_common<ManagedShMem>::mem_holder_t
- intermodule_singleton_common<ManagedShMem>::mem_holder;
-
-template<class ManagedShMem>
-void intermodule_singleton_common<ManagedShMem>::initialize_shm()
-{
- //Obtain unique shm name and size
- std::string s;
- while(1){
- //Try to pass shm state to initializing
- ::boost::uint32_t tmp = atomic_cas32(&this_module_shm_initialized, Initializing, Uninitialized);
- if(tmp >= Initialized){
- break;
- }
- //If some other thread is doing the work wait
- else if(tmp == Initializing){
- thread_yield();
- }
- else{ //(tmp == Uninitialized)
- //If not initialized try it again?
- try{
- //Remove old shared memory from the system
- intermodule_singleton_helpers::managed_sh_dependant<ManagedShMem>::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())ManagedShMem(open_or_create, ShmName, ShmSize);
- //Use shared memory internal lock to initialize the lock file
- //that will mark this gmem as "in use".
- intermodule_singleton_helpers::lock_file_logic<ManagedShMem> f(get_shm());
- //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().~ManagedShMem();
- atomic_write32(&this_module_shm_initialized, Uninitialized);
- }
- else{
- //Locking succeeded, so this shared memory module-instance is ready
- atomic_write32(&this_module_shm_initialized, Initialized);
- break;
- }
- }
- catch(...){
- //
- throw;
- }
- }
- }
-}
-
-template<class ManagedShMem>
-struct unlink_shmlogic
-{
- unlink_shmlogic(ManagedShMem &mshm)
- : mshm_(mshm)
- { mshm.atomic_func(*this); }
- void operator()()
- {
- intermodule_singleton_helpers::locking_file_serial_id *pserial_id =
- mshm_.template find<intermodule_singleton_helpers::locking_file_serial_id>
- ("lock_file_fd").first;
- BOOST_ASSERT(0 != pserial_id);
- if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){
- int fd = pserial_id->fd;
- if(fd > 0){
- pserial_id->fd = intermodule_singleton_helpers::GMemMarkToBeRemoved;
- std::string s;
- intermodule_singleton_helpers::create_and_get_singleton_lock_file_path(s);
- delete_file(s.c_str());
- intermodule_singleton_helpers::close_lock_file(fd);
- intermodule_singleton_helpers::get_shm_name(s);
- shared_memory_object::remove(s.c_str());
- }
- }
- }
- ManagedShMem &mshm_;
-};
-
-#if defined(BOOST_INTERPROCESS_WINDOWS)
-
-template<>
-struct unlink_shmlogic<windows_managed_global_memory>
-{
- unlink_shmlogic(windows_managed_global_memory &)
- {}
- void operator()(){}
-};
-
-#endif
-
-
-template<class ManagedShMem>
-void intermodule_singleton_common<ManagedShMem>::destroy_shm()
-{
- 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
- unlink_shmlogic<ManagedShMem> f(get_shm());
- (get_shm()).~ManagedShMem();
- atomic_write32(&this_module_shm_initialized, Uninitialized);
- //Do some cleanup for other processes old gmem instances
- intermodule_singleton_helpers::managed_sh_dependant<ManagedShMem>::remove_old_gmem();
- }
-}
-
-//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,
-//initializing the passed pointer to that unique instance.
-//
-//We have two concurrency types here. a)the shared memory/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.
-//
-//All static variables declared here are shared between inside a module
-//so atomic operations will synchronize only threads of the same module.
-template<class ManagedShMem>
-void intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic
- (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor)
-{
- //If current module is not initialized enter to lock free logic
- if(atomic_read32(&this_module_singleton_initialized) != Initialized){
- //Now a single thread of the module will succeed in this CAS.
- //trying to pass from Uninitialized to Initializing
- ::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
- if(previous_module_singleton_initialized == Uninitialized){
- try{
- //Now initialize shm, this function solves concurrency issues
- //between threads of several modules
- initialize_shm();
- //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
- 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);
- //Assign the singleton address to the module-local pointer
- ptr = tmp;
- //Memory barrier inserted, all previous operations should complete
- //before this one. Now marked as initialized
- atomic_inc32(&this_module_singleton_initialized);
- }
- catch(...){
- //Mark singleton failed to initialize
- atomic_write32(&this_module_singleton_initialized, Broken);
- throw;
- }
- }
- //If previous state was initializing, this means that another winner thread is
- //trying to initialize the singleton. Just wait until completes its work.
- else if(previous_module_singleton_initialized == Initializing){
- while(1){
- previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
- if(previous_module_singleton_initialized >= Initialized){
- //Already initialized, or exception thrown by initializer thread
- break;
- }
- else if(previous_module_singleton_initialized == Initializing){
- thread_yield();
- }
- else{
- //This can't be happening!
- BOOST_ASSERT(0);
- }
- }
- }
- else if(previous_module_singleton_initialized == Initialized){
- //Nothing to do here, the singleton is ready
- }
- //If previous state was greater than initialized, then memory is broken
- //trying to initialize the singleton.
- else{//(previous_module_singleton_initialized > Initialized)
- throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed");
- }
- }
- BOOST_ASSERT(ptr != 0);
-}
-
-//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, class ManagedShMem>
-class intermodule_singleton_impl
-{
- public:
- static C& get() //Let's make inlining easy
- {
- if(!this_module_singleton_ptr){
- if(lifetime.dummy_function()) //This forces lifetime instantiation, for reference counted destruction
- intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic
- (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
- }
- return *static_cast<C*>(this_module_singleton_ptr);
- }
-
- private:
-
- 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;
- };
-
- //These statics will be zero-initialized without any constructor call dependency
- //this_module_singleton_ptr will be a module-local pointer to the singleton
- static void* this_module_singleton_ptr;
- //this_module_singleton_count will be used to synchronize threads of the same module
- //for access to a singleton instance, and to flag the state of the
- //singleton.
- static volatile boost::uint32_t this_module_singleton_initialized;
-
- //This class destructor will trigger singleton destruction
- struct lifetime_type_lazy
- {
- bool dummy_function()
- { return m_dummy == 0; }
-
- ~lifetime_type_lazy()
- {
- intermodule_singleton_common<ManagedShMem>::finalize_singleton_logic
- (this_module_singleton_ptr, singleton_destructor);
- }
- //Dummy volatile so that the compiler can't resolve its value at compile-time
- //and can't avoid lifetime_type instantiation if dummy_function() is called.
- static volatile int m_dummy;
- };
-
- struct lifetime_type_static
- : public lifetime_type_lazy
- {
- lifetime_type_static()
- {
- intermodule_singleton_common<ManagedShMem>::initialize_singleton_logic
- (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
- }
- };
-
- typedef typename if_c
- <LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type;
-
- static lifetime_type lifetime;
-
- //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.
- //If singleton constructor throws, the exception is propagated
- struct init_atomic_func
- {
- init_atomic_func(ManagedShMem &m)
- : mshm(m)
- {}
-
- void operator()()
- {
- ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
- if(!rcount){
- C *p = new C();
- try{
- rcount = mshm.template construct<ref_count_ptr>(unique_instance)(p, 0u);
- }
- catch(...){
- delete p;
- throw;
- }
- }
- atomic_inc32(&rcount->singleton_ref_count);
- ret_ptr = rcount->ptr;
- }
- ManagedShMem &mshm;
- 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
- struct fini_atomic_func
- {
- fini_atomic_func(ManagedShMem &m)
- : mshm(m)
- {}
-
- void operator()()
- {
- ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
- //The object must exist
- BOOST_ASSERT(rcount);
- //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);
- (void)destroyed; BOOST_ASSERT(destroyed == true);
- }
- }
- ManagedShMem &mshm;
- void *ret_ptr;
- };
-
- //A wrapper to execute init_atomic_func
- static void *singleton_constructor(ManagedShMem &mshm)
- {
- init_atomic_func f(mshm);
- mshm.atomic_func(f);
- return f.ret_ptr;
- }
-
- //A wrapper to execute fini_atomic_func
- static void singleton_destructor(void *p, ManagedShMem &mshm)
- { (void)p;
- fini_atomic_func f(mshm);
- mshm.atomic_func(f);
- }
-};
-
-template <typename C, bool L, class ManagedShMem>
-volatile int intermodule_singleton_impl<C, L, ManagedShMem>::lifetime_type_lazy::m_dummy = 0;
-
-//These will be zero-initialized by the loader
-template <typename C, bool L, class ManagedShMem>
-void *intermodule_singleton_impl<C, L, ManagedShMem>::this_module_singleton_ptr = 0;
-
-template <typename C, bool L, class ManagedShMem>
-volatile boost::uint32_t intermodule_singleton_impl<C, L, ManagedShMem>::this_module_singleton_initialized = 0;
-
-template <typename C, bool L, class ManagedShMem>
-typename intermodule_singleton_impl<C, L, ManagedShMem>::lifetime_type
- intermodule_singleton_impl<C, L, ManagedShMem>::lifetime;
-
-template<typename C, bool LazyInit = false>
-class portable_intermodule_singleton
- : public intermodule_singleton_impl<C, LazyInit, managed_global_memory>
-{};
-
-#if defined(BOOST_INTERPROCESS_WINDOWS)
-
-template<typename C, bool LazyInit = false>
-class windows_intermodule_singleton
- : public intermodule_singleton_impl
- < C
- , LazyInit
- , windows_managed_global_memory
- >
-{};
-
-#endif
-
//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.
@@ -1174,7 +39,6 @@
#endif
{};
-
} //namespace ipcdetail{
} //namespace interprocess{
} //namespace boost{
Added: trunk/boost/interprocess/detail/intermodule_singleton_common.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/intermodule_singleton_common.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,439 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
+#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/assert.hpp>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <sstream>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+namespace intermodule_singleton_helpers {
+
+inline void get_pid_creation_time_str(std::string &s)
+{
+ std::stringstream stream;
+ stream << get_current_process_id() << '_';
+ stream.precision(6);
+ stream << std::fixed << get_current_process_creation_time();
+ s = stream.str();
+}
+
+inline const char *get_shm_base_name()
+{ return "bip.gmem.shm."; }
+
+inline void get_shm_name(std::string &shm_name)
+{
+ get_pid_creation_time_str(shm_name);
+ shm_name.insert(0, get_shm_base_name());
+}
+
+inline std::size_t get_shm_size()
+{ return 65536; }
+
+template<class ManagedGlobalMemory>
+struct managed_sh_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 reference counted shared memory
+//to be used by all instances
+
+template<class ManagedGlobalMemory>
+class intermodule_singleton_common
+{
+ public:
+ typedef void*(singleton_constructor_t)(ManagedGlobalMemory &);
+ typedef void (singleton_destructor_t)(void *, ManagedGlobalMemory &);
+
+ static const ::boost::uint32_t Uninitialized = 0u;
+ static const ::boost::uint32_t Initializing = 1u;
+ static const ::boost::uint32_t Initialized = 2u;
+ static const ::boost::uint32_t Broken = 3u;
+
+ static void finalize_singleton_logic(void *ptr, singleton_destructor_t destructor)
+ {
+ //Protect destruction against lazy singletons not initialized in this execution
+ if(ptr){
+ destructor(ptr, get_shm());
+ //If this is the last singleton of this module
+ //apply shm 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();
+ }
+ }
+ }
+
+ static void initialize_singleton_logic
+ (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t ini_func);
+
+ private:
+ static ManagedGlobalMemory &get_shm()
+ {
+ return *static_cast<ManagedGlobalMemory *>(static_cast<void *>(&mem_holder.shm_mem));
+ }
+
+ static void initialize_shm();
+ static void destroy_shm();
+ //Static data, zero-initalized without any dependencies
+ //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
+ static volatile boost::uint32_t this_module_shm_initialized;
+ static struct mem_holder_t
+ {
+ ::boost::detail::max_align aligner;
+ char shm_mem [sizeof(ManagedGlobalMemory)];
+ } mem_holder;
+};
+
+template<class ManagedGlobalMemory>
+volatile boost::uint32_t intermodule_singleton_common<ManagedGlobalMemory>::this_module_singleton_count;
+
+template<class ManagedGlobalMemory>
+volatile boost::uint32_t intermodule_singleton_common<ManagedGlobalMemory>::this_module_shm_initialized;
+
+template<class ManagedGlobalMemory>
+typename intermodule_singleton_common<ManagedGlobalMemory>::mem_holder_t
+ intermodule_singleton_common<ManagedGlobalMemory>::mem_holder;
+
+template<class ManagedGlobalMemory>
+void intermodule_singleton_common<ManagedGlobalMemory>::initialize_shm()
+{
+ //Obtain unique shm name and size
+ std::string s;
+ while(1){
+ //Try to pass shm state to initializing
+ ::boost::uint32_t tmp = atomic_cas32(&this_module_shm_initialized, Initializing, Uninitialized);
+ if(tmp >= Initialized){
+ break;
+ }
+ //If some other thread is doing the work wait
+ else if(tmp == Initializing){
+ thread_yield();
+ }
+ 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
+ //that will mark this gmem as "in use".
+ typename intermodule_singleton_helpers::managed_sh_dependant<ManagedGlobalMemory>::
+ lock_file_logic f(get_shm());
+ //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, Uninitialized);
+ }
+ else{
+ //Locking succeeded, so this shared memory module-instance is ready
+ atomic_write32(&this_module_shm_initialized, Initialized);
+ break;
+ }
+ }
+ catch(...){
+ //
+ throw;
+ }
+ }
+ }
+}
+
+template<class ManagedGlobalMemory>
+void intermodule_singleton_common<ManagedGlobalMemory>::destroy_shm()
+{
+ 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, Uninitialized);
+ //Do some cleanup for other processes old gmem instances
+ intermodule_singleton_helpers::managed_sh_dependant<ManagedGlobalMemory>::remove_old_gmem();
+ }
+}
+
+//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,
+//initializing the passed pointer to that unique instance.
+//
+//We have two concurrency types here. a)the shared memory/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.
+//
+//All static variables declared here are shared between inside a module
+//so atomic operations will synchronize only threads of the same module.
+template<class ManagedGlobalMemory>
+void intermodule_singleton_common<ManagedGlobalMemory>::initialize_singleton_logic
+ (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor)
+{
+ //If current module is not initialized enter to lock free logic
+ if(atomic_read32(&this_module_singleton_initialized) != Initialized){
+ //Now a single thread of the module will succeed in this CAS.
+ //trying to pass from Uninitialized to Initializing
+ ::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
+ if(previous_module_singleton_initialized == Uninitialized){
+ try{
+ //Now initialize shm, this function solves concurrency issues
+ //between threads of several modules
+ initialize_shm();
+ //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
+ 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);
+ //Assign the singleton address to the module-local pointer
+ ptr = tmp;
+ //Memory barrier inserted, all previous operations should complete
+ //before this one. Now marked as initialized
+ atomic_inc32(&this_module_singleton_initialized);
+ }
+ catch(...){
+ //Mark singleton failed to initialize
+ atomic_write32(&this_module_singleton_initialized, Broken);
+ throw;
+ }
+ }
+ //If previous state was initializing, this means that another winner thread is
+ //trying to initialize the singleton. Just wait until completes its work.
+ else if(previous_module_singleton_initialized == Initializing){
+ while(1){
+ previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
+ if(previous_module_singleton_initialized >= Initialized){
+ //Already initialized, or exception thrown by initializer thread
+ break;
+ }
+ else if(previous_module_singleton_initialized == Initializing){
+ thread_yield();
+ }
+ else{
+ //This can't be happening!
+ BOOST_ASSERT(0);
+ }
+ }
+ }
+ else if(previous_module_singleton_initialized == Initialized){
+ //Nothing to do here, the singleton is ready
+ }
+ //If previous state was greater than initialized, then memory is broken
+ //trying to initialize the singleton.
+ else{//(previous_module_singleton_initialized > Initialized)
+ throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed");
+ }
+ }
+ BOOST_ASSERT(ptr != 0);
+}
+
+//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, class ManagedGlobalMemory>
+class intermodule_singleton_impl
+{
+ public:
+ static C& get() //Let's make inlining easy
+ {
+ if(!this_module_singleton_ptr){
+ if(lifetime.dummy_function()) //This forces lifetime instantiation, for reference counted destruction
+ intermodule_singleton_common<ManagedGlobalMemory>::initialize_singleton_logic
+ (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
+ }
+ return *static_cast<C*>(this_module_singleton_ptr);
+ }
+
+ private:
+
+ 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;
+ };
+
+ //These statics will be zero-initialized without any constructor call dependency
+ //this_module_singleton_ptr will be a module-local pointer to the singleton
+ static void* this_module_singleton_ptr;
+ //this_module_singleton_count will be used to synchronize threads of the same module
+ //for access to a singleton instance, and to flag the state of the
+ //singleton.
+ static volatile boost::uint32_t this_module_singleton_initialized;
+
+ //This class destructor will trigger singleton destruction
+ struct lifetime_type_lazy
+ {
+ bool dummy_function()
+ { return m_dummy == 0; }
+
+ ~lifetime_type_lazy()
+ {
+ intermodule_singleton_common<ManagedGlobalMemory>::finalize_singleton_logic
+ (this_module_singleton_ptr, singleton_destructor);
+ }
+ //Dummy volatile so that the compiler can't resolve its value at compile-time
+ //and can't avoid lifetime_type instantiation if dummy_function() is called.
+ static volatile int m_dummy;
+ };
+
+ struct lifetime_type_static
+ : public lifetime_type_lazy
+ {
+ lifetime_type_static()
+ {
+ intermodule_singleton_common<ManagedGlobalMemory>::initialize_singleton_logic
+ (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor);
+ }
+ };
+
+ typedef typename if_c
+ <LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type;
+
+ static lifetime_type lifetime;
+
+ //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.
+ //If singleton constructor throws, the exception is propagated
+ struct init_atomic_func
+ {
+ init_atomic_func(ManagedGlobalMemory &m)
+ : mshm(m)
+ {}
+
+ void operator()()
+ {
+ ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
+ if(!rcount){
+ C *p = new C();
+ try{
+ rcount = mshm.template construct<ref_count_ptr>(unique_instance)(p, 0u);
+ }
+ catch(...){
+ delete p;
+ throw;
+ }
+ }
+ atomic_inc32(&rcount->singleton_ref_count);
+ ret_ptr = rcount->ptr;
+ }
+ ManagedGlobalMemory &mshm;
+ 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
+ struct fini_atomic_func
+ {
+ fini_atomic_func(ManagedGlobalMemory &m)
+ : mshm(m)
+ {}
+
+ void operator()()
+ {
+ ref_count_ptr *rcount = mshm.template find<ref_count_ptr>(unique_instance).first;
+ //The object must exist
+ BOOST_ASSERT(rcount);
+ //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);
+ (void)destroyed; BOOST_ASSERT(destroyed == true);
+ }
+ }
+ ManagedGlobalMemory &mshm;
+ void *ret_ptr;
+ };
+
+ //A wrapper to execute init_atomic_func
+ static void *singleton_constructor(ManagedGlobalMemory &mshm)
+ {
+ init_atomic_func f(mshm);
+ mshm.atomic_func(f);
+ return f.ret_ptr;
+ }
+
+ //A wrapper to execute fini_atomic_func
+ static void singleton_destructor(void *p, ManagedGlobalMemory &mshm)
+ { (void)p;
+ fini_atomic_func f(mshm);
+ mshm.atomic_func(f);
+ }
+};
+
+template <typename C, bool L, class ManagedGlobalMemory>
+volatile int intermodule_singleton_impl<C, L, ManagedGlobalMemory>::lifetime_type_lazy::m_dummy = 0;
+
+//These will be zero-initialized by the loader
+template <typename C, bool L, class ManagedGlobalMemory>
+void *intermodule_singleton_impl<C, L, ManagedGlobalMemory>::this_module_singleton_ptr = 0;
+
+template <typename C, bool L, class ManagedGlobalMemory>
+volatile boost::uint32_t intermodule_singleton_impl<C, L, ManagedGlobalMemory>::this_module_singleton_initialized = 0;
+
+template <typename C, bool L, class ManagedGlobalMemory>
+typename intermodule_singleton_impl<C, L, ManagedGlobalMemory>::lifetime_type
+ intermodule_singleton_impl<C, L, ManagedGlobalMemory>::lifetime;
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
Added: trunk/boost/interprocess/detail/managed_global_memory.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/managed_global_memory.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,115 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP
+#define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/offset_ptr.hpp>
+#include <boost/interprocess/sync/spin/mutex.hpp>
+#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/indexes/iset_index.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+struct intermodule_singleton_mutex_family
+{
+ typedef boost::interprocess::ipcdetail::spin_mutex mutex_type;
+ typedef boost::interprocess::ipcdetail::spin_recursive_mutex recursive_mutex_type;
+};
+
+struct intermodule_types
+{
+ //We must use offset_ptr since a loaded DLL can map the singleton holder shared memory
+ //at a different address than other DLLs or the main executable
+ typedef rbtree_best_fit<intermodule_singleton_mutex_family, offset_ptr<void> > mem_algo;
+ template<class Device, bool FileBased>
+ struct open_or_create
+ {
+ typedef managed_open_or_create_impl
+ <Device, mem_algo::Alignment, FileBased> type;
+ };
+};
+
+//we must implement our own managed shared memory to avoid circular dependencies
+template<class Device, bool FileBased>
+class basic_managed_global_memory
+ : public basic_managed_memory_impl
+ < char
+ , intermodule_types::mem_algo
+ , iset_index
+ , intermodule_types::open_or_create<Device, FileBased>::type::ManagedOpenOrCreateUserOffset
+ >
+ , private intermodule_types::open_or_create<Device, FileBased>::type
+{
+ /// @cond
+ typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t;
+
+ typedef basic_managed_memory_impl
+ < char
+ , intermodule_types::mem_algo
+ , iset_index
+ , base2_t::ManagedOpenOrCreateUserOffset
+ > base_t;
+
+ typedef create_open_func<base_t> create_open_func_t;
+
+ basic_managed_global_memory *get_this_pointer()
+ { return this; }
+
+ public:
+ typedef typename base_t::size_type size_type;
+
+ private:
+ typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory)
+ /// @endcond
+
+ public: //functions
+
+ basic_managed_global_memory (open_or_create_t open_or_create,
+ const char *name, size_type size,
+ const void *addr = 0, const permissions& perm = permissions())
+ : base_t()
+ , base2_t(open_or_create, name, size, read_write, addr,
+ create_open_func_t(get_this_pointer(),
+ DoOpenOrCreate), perm)
+ {}
+
+ basic_managed_global_memory (open_only_t open_only, const char* name,
+ const void *addr = 0)
+ : base_t()
+ , base2_t(open_only, name, read_write, addr,
+ create_open_func_t(get_this_pointer(),
+ DoOpen))
+ {}
+};
+
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP
Modified: trunk/boost/interprocess/detail/os_file_functions.hpp
==============================================================================
--- trunk/boost/interprocess/detail/os_file_functions.hpp (original)
+++ trunk/boost/interprocess/detail/os_file_functions.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -140,7 +140,7 @@
if(offset_t(size) > filesize){
if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
return false;
- }
+ }
//We will write zeros in the end of the file
//since set_end_of_file does not guarantee this
for(std::size_t remaining = size - filesize, write_size = 0
@@ -191,7 +191,7 @@
inline bool acquire_file_lock(file_handle_t hnd)
{
static winapi::interprocess_overlapped overlapped;
- const unsigned long len = 0xffffffff;
+ const unsigned long len = ~((unsigned long)(0u));
// winapi::interprocess_overlapped overlapped;
// std::memset(&overlapped, 0, sizeof(overlapped));
return winapi::lock_file_ex
@@ -200,7 +200,7 @@
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
{
- const unsigned long len = 0xffffffff;
+ const unsigned long len = ~((unsigned long)(0u));
winapi::interprocess_overlapped overlapped;
std::memset(&overlapped, 0, sizeof(overlapped));
if(!winapi::lock_file_ex
@@ -215,7 +215,7 @@
inline bool release_file_lock(file_handle_t hnd)
{
- const unsigned long len = 0xffffffff;
+ const unsigned long len = ~((unsigned long)(0u));
winapi::interprocess_overlapped overlapped;
std::memset(&overlapped, 0, sizeof(overlapped));
return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped);
@@ -223,7 +223,7 @@
inline bool acquire_file_lock_sharable(file_handle_t hnd)
{
- const unsigned long len = 0xffffffff;
+ const unsigned long len = ~((unsigned long)(0u));
winapi::interprocess_overlapped overlapped;
std::memset(&overlapped, 0, sizeof(overlapped));
return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped);
@@ -231,7 +231,7 @@
inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
{
- const unsigned long len = 0xffffffff;
+ const unsigned long len = ~((unsigned long)(0u));
winapi::interprocess_overlapped overlapped;
std::memset(&overlapped, 0, sizeof(overlapped));
if(!winapi::lock_file_ex
Modified: trunk/boost/interprocess/detail/pointer_type.hpp
==============================================================================
--- trunk/boost/interprocess/detail/pointer_type.hpp (original)
+++ trunk/boost/interprocess/detail/pointer_type.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -61,7 +61,7 @@
struct pointer_type
{
typedef typename pointer_type_imp::pointer_type<T,
- typename ipcdetail::remove_reference<D>::type>::type type;
+ typename remove_reference<D>::type>::type type;
};
} //namespace ipcdetail {
Added: trunk/boost/interprocess/detail/portable_intermodule_singleton.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/portable_intermodule_singleton.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,321 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
+#define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/managed_global_memory.hpp>
+#include <boost/interprocess/detail/intermodule_singleton_common.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/file_locking_helpers.hpp>
+#include <boost/assert.hpp>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+typedef basic_managed_global_memory<shared_memory_object, true> managed_global_memory;
+
+namespace intermodule_singleton_helpers {
+
+static void create_tmp_subdir_and_get_pid_based_filepath
+ (const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false)
+{
+ //Let's create a lock file for each process gmem that will mark if
+ //the process is alive or not
+ create_tmp_and_clean_old(s);
+ s += "/";
+ s += subdir_name;
+ if(!open_or_create_directory(s.c_str())){
+ throw interprocess_exception(error_info(system_error_code()));
+ }
+ s += "/";
+ s += file_prefix;
+ if(creation_time){
+ std::string sstamp;
+ get_pid_creation_time_str(sstamp);
+ s += sstamp;
+ }
+ else{
+ pid_str_t pid_str;
+ get_pid_str(pid_str, pid);
+ s += pid_str;
+ }
+}
+
+static bool check_if_filename_complies_with_pid
+ (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false)
+{
+ //Check if filename complies with lock file name pattern
+ std::string fname(filename);
+ std::string fprefix(prefix);
+ if(fname.size() <= fprefix.size()){
+ return false;
+ }
+ fname.resize(fprefix.size());
+ if(fname != fprefix){
+ return false;
+ }
+
+ //If not our lock file, delete it if we can lock it
+ fname = filename;
+ fname.erase(0, fprefix.size());
+ pid_str_t pid_str;
+ get_pid_str(pid_str, pid);
+ file_suffix = pid_str;
+ if(creation_time){
+ std::size_t p = fname.find('_');
+ if (p == std::string::npos){
+ return false;
+ }
+ std::string save_suffix(fname);
+ fname.erase(p);
+ fname.swap(file_suffix);
+ bool ret = (file_suffix == fname);
+ file_suffix.swap(save_suffix);
+ return ret;
+ }
+ else{
+ fname.swap(file_suffix);
+ return (file_suffix == fname);
+ }
+}
+
+template<>
+struct managed_sh_dependant<managed_global_memory>
+{
+ private:
+ static const int GMemMarkToBeRemoved = -1;
+ static const int GMemNotPresent = -2;
+
+ static const char *get_lock_file_subdir_name()
+ { return "gmem"; }
+
+ static const char *get_lock_file_base_name()
+ { return "lck"; }
+
+ static void create_and_get_singleton_lock_file_path(std::string &s)
+ {
+ create_tmp_subdir_and_get_pid_based_filepath
+ (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true);
+ }
+
+ struct gmem_erase_func
+ {
+ gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, managed_global_memory & shm)
+ :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm)
+ {}
+
+ void operator()()
+ {
+ locking_file_serial_id *pserial_id = shm_.find<locking_file_serial_id>("lock_file_fd").first;
+ if(pserial_id){
+ pserial_id->fd = GMemMarkToBeRemoved;
+ }
+ delete_file(singleton_lock_file_path_);
+ shared_memory_object::remove(shm_name_);
+ }
+
+ const char * const shm_name_;
+ const char * const singleton_lock_file_path_;
+ managed_global_memory & shm_;
+ };
+
+ public:
+ //This function applies shared memory erasure logic based on the passed lock file.
+ static void apply_gmem_erase_logic(const char *filepath, const char *filename)
+ {
+ int fd = GMemMarkToBeRemoved;
+ try{
+ std::string str;
+ //If the filename is current process lock file, then avoid it
+ if(check_if_filename_complies_with_pid
+ (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){
+ return;
+ }
+ //Open and lock the other process' lock file
+ fd = try_open_and_lock_file(filepath);
+ if(fd < 0){
+ return;
+ }
+ //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());
+ try{
+ managed_global_memory shm(open_only, str.c_str());
+ gmem_erase_func func(str.c_str(), filepath, shm);
+ shm.try_atomic_func(func);
+ }
+ catch(interprocess_exception &e){
+ //If shared memory is not found erase the lock file
+ if(e.get_error_code() == not_found_error){
+ delete_file(filepath);
+ }
+ }
+ }
+ catch(...){
+
+ }
+ if(fd >= 0){
+ close_lock_file(fd);
+ }
+ }
+
+ static bool remove_old_gmem()
+ {
+ std::string refcstrRootDirectory;
+ tmp_folder(refcstrRootDirectory);
+ refcstrRootDirectory += "/";
+ refcstrRootDirectory += get_lock_file_subdir_name();
+ return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic);
+ }
+
+ struct lock_file_logic
+ {
+ lock_file_logic(managed_global_memory &shm)
+ : mshm(shm)
+ { shm.atomic_func(*this); }
+
+ void operator()(void)
+ {
+ retry_with_new_shm = false;
+
+ //First find the file locking descriptor id
+ locking_file_serial_id *pserial_id =
+ mshm.find<locking_file_serial_id>("lock_file_fd").first;
+
+ int fd;
+ //If not found schedule a creation
+ if(!pserial_id){
+ fd = GMemNotPresent;
+ }
+ //Else get it
+ else{
+ fd = pserial_id->fd;
+ }
+ //If we need to create a new one, do it
+ if(fd == GMemNotPresent){
+ std::string lck_str;
+ //Create a unique current pid based lock file path
+ create_and_get_singleton_lock_file_path(lck_str);
+ //Open or create and lock file
+ int fd = open_or_create_and_lock_file(lck_str.c_str());
+ //If failed, write a bad file descriptor to notify other modules that
+ //something was wrong and unlink shared memory. Mark the function object
+ //to tell caller to retry with another shared memory
+ if(fd < 0){
+ this->register_lock_file(GMemMarkToBeRemoved);
+ std::string s;
+ get_shm_name(s);
+ shared_memory_object::remove(s.c_str());
+ retry_with_new_shm = true;
+ }
+ //If successful, register the file descriptor
+ else{
+ this->register_lock_file(fd);
+ }
+ }
+ //If the fd was invalid (maybe a previous try failed) notify caller that
+ //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;
+ }
+ //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,
+ //then it's an old shm from an old process with the same pid.
+ //If that's the case, mark it as invalid
+ else if(!is_valid_fd(fd) ||
+ !is_normal_file(fd) ||
+ 0 != get_size(fd) ||
+ !compare_file_serial(fd, *pserial_id)){
+ pserial_id->fd = GMemMarkToBeRemoved;
+ std::string s;
+ get_shm_name(s);
+ shared_memory_object::remove(s.c_str());
+ retry_with_new_shm = true;
+ }
+ else{
+ //If the lock file is ok, increment reference count of
+ //attached modules to shared memory
+ atomic_inc32(&pserial_id->modules_attached_to_gmem_count);
+ }
+ }
+
+ private:
+ locking_file_serial_id * register_lock_file(int fd)
+ {
+ locking_file_serial_id *pinfo = mshm.construct<locking_file_serial_id>("lock_file_fd")();
+ fill_file_serial_id(fd, *pinfo);
+ return pinfo;
+ }
+
+ public:
+ managed_global_memory &mshm;
+ bool retry_with_new_shm;
+ };
+
+ struct unlink_shmlogic
+ {
+ unlink_shmlogic(managed_global_memory &mshm)
+ : mshm_(mshm)
+ { mshm.atomic_func(*this); }
+ void operator()()
+ {
+ locking_file_serial_id *pserial_id =
+ mshm_.find<locking_file_serial_id>
+ ("lock_file_fd").first;
+ BOOST_ASSERT(0 != pserial_id);
+ if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){
+ int fd = pserial_id->fd;
+ if(fd > 0){
+ pserial_id->fd = GMemMarkToBeRemoved;
+ std::string s;
+ create_and_get_singleton_lock_file_path(s);
+ delete_file(s.c_str());
+ close_lock_file(fd);
+ intermodule_singleton_helpers::get_shm_name(s);
+ shared_memory_object::remove(s.c_str());
+ }
+ }
+ }
+ managed_global_memory &mshm_;
+ };
+};
+
+} //namespace intermodule_singleton_helpers {
+
+template<typename C, bool LazyInit = false>
+class portable_intermodule_singleton
+ : public intermodule_singleton_impl<C, LazyInit, managed_global_memory>
+{};
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
Modified: trunk/boost/interprocess/detail/preprocessor.hpp
==============================================================================
--- trunk/boost/interprocess/detail/preprocessor.hpp (original)
+++ trunk/boost/interprocess/detail/preprocessor.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -57,28 +57,30 @@
#ifndef BOOST_NO_RVALUE_REFERENCES
-#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+ #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
-#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
- BOOST_PP_CAT(m_p, n) (BOOST_INTERPROCESS_MOVE_NAMESPACE::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
-//!
+ #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
+ //!
-#else
-#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
- BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
-//!
+ #else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
-#endif
+ #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
+ //!
-#else
-#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
- BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
-//!
+ #endif //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#else //#ifndef BOOST_NO_RVALUE_REFERENCES
+
+ #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
+ //!
#endif
#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
- BOOST_PP_CAT(++m_p, n) \
+ BOOST_PP_CAT(++m_p, n) \
//!
#ifndef BOOST_NO_RVALUE_REFERENCES
Modified: trunk/boost/interprocess/detail/robust_emulation.hpp
==============================================================================
--- trunk/boost/interprocess/detail/robust_emulation.hpp (original)
+++ trunk/boost/interprocess/detail/robust_emulation.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -68,7 +68,7 @@
inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid)
{
- file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath
+ intermodule_singleton_helpers::create_tmp_subdir_and_get_pid_based_filepath
(robust_lock_subdir_path(), robust_lock_prefix(), pid, s);
}
@@ -154,7 +154,7 @@
{
std::string pid_str;
//If the lock file is not our own lock file, then try to do the cleanup
- if(!file_locking_helpers::check_if_filename_complies_with_pid
+ if(!intermodule_singleton_helpers::check_if_filename_complies_with_pid
(filename, robust_lock_prefix(), get_current_process_id(), pid_str)){
remove_if_can_lock_file(filepath);
}
Modified: trunk/boost/interprocess/detail/tmp_dir_helpers.hpp
==============================================================================
--- trunk/boost/interprocess/detail/tmp_dir_helpers.hpp (original)
+++ trunk/boost/interprocess/detail/tmp_dir_helpers.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -18,80 +18,87 @@
#include <boost/interprocess/exceptions.hpp>
#include <string>
-#if defined(BOOST_INTERPROCESS_WINDOWS)
- //#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
- //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
- //#include <boost/interprocess/detail/win32_api.hpp>
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
- //#include <sys/sysctl.h>
- //#if defined(CTL_KERN) && defined (KERN_BOOTTIME)
- //#define BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME
- //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
- //#endif
+#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
#endif
namespace boost {
namespace interprocess {
namespace ipcdetail {
-#if defined (BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME)
-inline void get_bootstamp(std::string &s, bool add = false)
-{
- std::string bootstamp;
- winapi::get_last_bootup_time(bootstamp);
- if(add){
- s += bootstamp;
- }
- else{
- s.swap(bootstamp);
- }
-}
-#elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
-inline void get_bootstamp(std::string &s, bool add = false)
-{
- // FreeBSD specific: sysctl "kern.boottime"
- int request[2] = { CTL_KERN, KERN_BOOTTIME };
- struct ::timeval result;
- std::size_t result_len = sizeof result;
-
- if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
- return;
-
- char bootstamp_str[256];
-
- const char Characters [] =
- { '0', '1', '2', '3', '4', '5', '6', '7'
- , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
- std::size_t char_counter = 0;
- //32 bit values to allow 32 and 64 bit process IPC
- boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) };
- for(std::size_t field = 0; field != 2; ++field){
- for(std::size_t i = 0; i != sizeof(fields[0]); ++i){
- const char *ptr = (const char *)&fields[field];
- bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
- bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
+#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+ #if defined(BOOST_INTERPROCESS_WINDOWS)
+ //This type will initialize the stamp
+ struct windows_bootstamp
+ {
+ windows_bootstamp()
+ {
+ winapi::get_last_bootup_time(stamp);
+ }
+ //Use std::string. Even if this will be constructed in shared memory, all
+ //modules/dlls are from this process so internal raw pointers to heap are always valid
+ std::string stamp;
+ };
+
+ inline void get_bootstamp(std::string &s, bool add = false)
+ {
+ const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp, true>::get();
+ if(add){
+ s += bootstamp.stamp;
+ }
+ else{
+ s = bootstamp.stamp;
+ }
}
- }
- bootstamp_str[char_counter] = 0;
- if(add){
- s += bootstamp_str;
- }
- else{
- s = bootstamp_str;
- }
-}
-#endif
+ #elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
+ inline void get_bootstamp(std::string &s, bool add = false)
+ {
+ // FreeBSD specific: sysctl "kern.boottime"
+ int request[2] = { CTL_KERN, KERN_BOOTTIME };
+ struct ::timeval result;
+ std::size_t result_len = sizeof result;
+
+ if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
+ return;
+
+ char bootstamp_str[256];
+
+ const char Characters [] =
+ { '0', '1', '2', '3', '4', '5', '6', '7'
+ , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ std::size_t char_counter = 0;
+ //32 bit values to allow 32 and 64 bit process IPC
+ boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) };
+ for(std::size_t field = 0; field != 2; ++field){
+ for(std::size_t i = 0; i != sizeof(fields[0]); ++i){
+ const char *ptr = (const char *)&fields[field];
+ bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
+ bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
+ }
+ }
+ bootstamp_str[char_counter] = 0;
+ if(add){
+ s += bootstamp_str;
+ }
+ else{
+ s = bootstamp_str;
+ }
+ }
+ #else
+ #error "BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME defined with no known implementation"
+ #endif
+#endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
inline void get_tmp_base_dir(std::string &tmp_name)
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
- winapi::get_shared_documents_folder(tmp_name);
- if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){
- tmp_name = get_temporary_path();
- }
+ winapi::get_shared_documents_folder(tmp_name);
+ if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){
+ tmp_name = get_temporary_path();
+ }
#else
- tmp_name = get_temporary_path();
+ tmp_name = get_temporary_path();
#endif
if(tmp_name.empty()){
error_info err = system_error_code();
@@ -104,9 +111,9 @@
inline void tmp_folder(std::string &tmp_name)
{
get_tmp_base_dir(tmp_name);
- #ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
- tmp_name += "/";
- get_bootstamp(tmp_name, true);
+ #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+ tmp_name += "/";
+ get_bootstamp(tmp_name, true);
#endif
}
@@ -131,22 +138,22 @@
}
}
- #ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
- tmp_folder(tmp_name);
+ #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+ tmp_folder(tmp_name);
- //If fails, check that it's because already exists
- if(!create_directory(tmp_name.c_str())){
- error_info info(system_error_code());
- if(info.get_error_code() != already_exists_error){
- throw interprocess_exception(info);
+ //If fails, check that it's because already exists
+ if(!create_directory(tmp_name.c_str())){
+ error_info info(system_error_code());
+ if(info.get_error_code() != already_exists_error){
+ throw interprocess_exception(info);
+ }
}
- }
- //Now erase all old directories created in the previous boot sessions
- std::string subdir = tmp_name;
- subdir.erase(0, root_tmp_name.size()+1);
- delete_subdirectories(root_tmp_name, subdir.c_str());
+ //Now erase all old directories created in the previous boot sessions
+ std::string subdir = tmp_name;
+ subdir.erase(0, root_tmp_name.size()+1);
+ delete_subdirectories(root_tmp_name, subdir.c_str());
#else
- tmp_name = root_tmp_name;
+ tmp_name = root_tmp_name;
#endif
}
Modified: trunk/boost/interprocess/detail/win32_api.hpp
==============================================================================
--- trunk/boost/interprocess/detail/win32_api.hpp (original)
+++ trunk/boost/interprocess/detail/win32_api.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -574,6 +574,12 @@
void *h_event;
};
+struct interprocess_semaphore_basic_information
+{
+ unsigned int count; // current semaphore count
+ unsigned int limit; // max semaphore count
+};
+
struct interprocess_filetime
{
unsigned long dwLowDateTime;
@@ -620,7 +626,7 @@
unsigned short wProcessorRevision;
};
-struct interprocess_memory_basic_information
+typedef struct _interprocess_memory_basic_information
{
void * BaseAddress;
void * AllocationBase;
@@ -629,7 +635,7 @@
unsigned long State;
unsigned long Protect;
unsigned long Type;
-};
+} interprocess_memory_basic_information;
typedef struct _interprocess_acl
{
@@ -695,6 +701,10 @@
file_maximum_information
};
+enum semaphore_information_class {
+ semaphore_basic_information = 0
+};
+
struct file_name_information_t {
unsigned long FileNameLength;
wchar_t FileName[1];
@@ -844,6 +854,7 @@
extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped);
+extern "C" __declspec(dllimport) int __stdcall ReadFile(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped);
extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision);
extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted);
extern "C" __declspec(dllimport) void *__stdcall LoadLibraryA(const char *);
@@ -891,8 +902,9 @@
//Pointer to functions
typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes);
typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass );
-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 *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 *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*);
@@ -1051,7 +1063,7 @@
if (error_sharing_violation != get_last_error()){
return handle;
}
- Sleep(error_sharing_violation_sleep_ms);
+ sleep(error_sharing_violation_sleep_ms);
}
return invalid_handle_value;
}
@@ -1101,6 +1113,9 @@
inline bool write_file(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped)
{ return 0 != WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); }
+inline bool read_file(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped)
+{ return 0 != ReadFile(hnd, buffer, bytes_to_read, bytes_read, overlapped); }
+
inline bool get_file_information_by_handle(void *hnd, interprocess_by_handle_file_information *info)
{ return 0 != GetFileInformationByHandle(hnd, info); }
@@ -1176,7 +1191,7 @@
template<int Dummy>
struct function_address_holder
{
- enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NumFunction };
+ enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NumFunction };
enum { NtDll_dll, NumModule };
private:
@@ -1213,7 +1228,7 @@
static void *get_address_from_dll(const unsigned int id)
{
assert(id < (unsigned int)NumFunction);
- const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject" };
+ const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject", "NtQuerySemaphore" };
bool compile_check[sizeof(function)/sizeof(function[0]) == NumFunction];
(void)compile_check;
return get_proc_address(get_module(NtDll_dll), function[id]);
Added: trunk/boost/interprocess/detail/windows_intermodule_singleton.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/windows_intermodule_singleton.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,81 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
+#define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#if !defined(BOOST_INTERPROCESS_WINDOWS)
+ #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>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+typedef basic_managed_global_memory<windows_shared_memory, false> windows_managed_global_memory;
+
+namespace intermodule_singleton_helpers {
+
+template<>
+struct managed_sh_dependant<windows_managed_global_memory>
+{
+ static void apply_gmem_erase_logic(const char *, const char *){}
+
+ static bool remove_old_gmem()
+ { return true; }
+
+ struct lock_file_logic
+ {
+ lock_file_logic(windows_managed_global_memory &)
+ : retry_with_new_shm(false)
+ {}
+
+ void operator()(void){}
+ const bool retry_with_new_shm;
+ };
+
+ struct unlink_shmlogic
+ {
+ unlink_shmlogic(windows_managed_global_memory &)
+ {}
+ void operator()(){}
+ };
+};
+
+} //namespace intermodule_singleton_helpers {
+
+template<typename C, bool LazyInit = false>
+class windows_intermodule_singleton
+ : public intermodule_singleton_impl
+ < C
+ , LazyInit
+ , windows_managed_global_memory
+ >
+{};
+
+} //namespace ipcdetail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
Modified: trunk/boost/interprocess/detail/workaround.hpp
==============================================================================
--- trunk/boost/interprocess/detail/workaround.hpp (original)
+++ trunk/boost/interprocess/detail/workaround.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -13,42 +13,33 @@
#include <boost/interprocess/detail/config_begin.hpp>
-#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
-
-#define BOOST_INTERPROCESS_WINDOWS
-
-/*
-#if !defined(_MSC_EXTENSIONS)
-#error "Turn on Microsoft language extensions (_MSC_EXTENSIONS) to be able to call Windows API functions"
-#endif
-*/
-
-#endif
-
-#if !defined(BOOST_INTERPROCESS_WINDOWS)
-
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+ #define BOOST_INTERPROCESS_WINDOWS
+ //#define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
+ #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+#else
#include <unistd.h>
- #if ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
- //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
- //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work.
- # if !defined(__CYGWIN__) && !defined(__APPLE__)
- # define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
- # endif
+ #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
+ //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
+ //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work.
+ #if !defined(__CYGWIN__) && !defined(__APPLE__)
+ #define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
+ #endif
#endif
- #if ((_POSIX_BARRIERS - 0) > 0)
- # define BOOST_INTERPROCESS_POSIX_BARRIERS
- # endif
-
- #if ((_POSIX_SEMAPHORES - 0) > 0)
- # define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
- # if defined(__CYGWIN__)
- #define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
- # endif
+ #if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0)
+ #define BOOST_INTERPROCESS_POSIX_BARRIERS
+ #endif
+
+ #if defined(_POSIX_SEMAPHORES) && ((_POSIX_SEMAPHORES - 0) > 0)
+ #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+ #if defined(__CYGWIN__)
+ #define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
+ #endif
//Some platforms have a limited (name length) named semaphore support
#elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__)
- # define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+ #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
#endif
#if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\
@@ -60,87 +51,83 @@
((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\
((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))
#define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T
- #else
#endif
//Check for XSI shared memory objects. They are available in nearly all UNIX platforms
#if !defined(__QNXNTO__)
- # define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+ #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
#endif
- #if ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
- # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+ #if defined(_POSIX_SHARED_MEMORY_OBJECTS) && ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
+ #define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
#else
- //VMS and MACOS don't define it but the have shm_open/close interface
- # if defined(__vms)
- # if __CRTL_VER >= 70200000
- # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
- # endif
- //Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
- # elif defined (__APPLE__)
-// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
-// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW
- # endif
+ //VMS and MACOS don't define it but they have shm_open/close interface
+ #if defined(__vms)
+ #if __CRTL_VER >= 70200000
+ #define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+ #endif
+ //Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
+ #elif defined (__APPLE__)
+ //#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+ //#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW
+ #endif
#endif
//Now check if we have only XSI shared memory
#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) &&\
!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
- //# define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY
+ //#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY
#endif
- #if ((_POSIX_TIMEOUTS - 0) > 0)
- # define BOOST_INTERPROCESS_POSIX_TIMEOUTS
+ #if defined(_POSIX_TIMEOUTS) && ((_POSIX_TIMEOUTS - 0) > 0)
+ #define BOOST_INTERPROCESS_POSIX_TIMEOUTS
#endif
-
#ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
//Some systems have filesystem-based resources, so the
//portable "/shmname" format does not work due to permission issues
//For those systems we need to form a path to a temporary directory:
// hp-ux tru64 vms freebsd
#if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7))
- #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
+ #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
#elif defined(__FreeBSD__)
- #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
+ #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
#endif
#endif
#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
#if defined(__osf__) || defined(__vms)
- #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
+ #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
#endif
#endif
- #if ((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500)
- #define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
+ #if defined(_POSIX_VERSION) && defined(_XOPEN_VERSION) && \
+ (((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500))
+ #define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
#endif
-#endif
+ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+ #define BOOST_INTERPROCESS_BSD_DERIVATIVE
+ #include <sys/sysctl.h>
+ #if defined(CTL_KERN) && defined (KERN_BOOTTIME)
+ //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+ #endif
+ #endif
+#endif //!defined(BOOST_INTERPROCESS_WINDOWS)
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\
- && !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
-#define BOOST_INTERPROCESS_PERFECT_FORWARDING
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #define BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif
//Now declare some Boost.Interprocess features depending on the implementation
-
-#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
-
-#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
-
-#endif
-
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
-
-#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
-#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
-
+ #define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
+ #define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
#endif
// Timeout duration use if BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING is set
#ifndef BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS
-#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
+ #define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
#endif
#include <boost/interprocess/detail/config_end.hpp>
Modified: trunk/boost/interprocess/smart_ptr/detail/shared_count.hpp
==============================================================================
--- trunk/boost/interprocess/smart_ptr/detail/shared_count.hpp (original)
+++ trunk/boost/interprocess/smart_ptr/detail/shared_count.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -28,7 +28,7 @@
#include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
#include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
#include <boost/interprocess/detail/utilities.hpp>
-#include <boost/container/allocator/allocator_traits.hpp>
+#include <boost/container/allocator_traits.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <functional> // std::less
Modified: trunk/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp
==============================================================================
--- trunk/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp (original)
+++ trunk/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -26,7 +26,7 @@
#include <boost/interprocess/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
#include <boost/interprocess/detail/utilities.hpp>
-#include <boost/container/allocator/allocator_traits.hpp>
+#include <boost/container/allocator_traits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
namespace boost {
Modified: trunk/boost/interprocess/smart_ptr/shared_ptr.hpp
==============================================================================
--- trunk/boost/interprocess/smart_ptr/shared_ptr.hpp (original)
+++ trunk/boost/interprocess/smart_ptr/shared_ptr.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -137,8 +137,13 @@
ipcdetail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) );
}
+ //!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs
+ //!a shared_ptr that shares ownership with r. Never throws.
+ shared_ptr(const shared_ptr &r)
+ : m_pn(r.m_pn) // never throws
+ {}
- //!Constructs a shared_ptr that shares ownership with r and stores p.
+ //!Constructs a shared_ptr that shares ownership with other and stores p.
//!Postconditions: get() == p && use_count() == r.use_count().
//!Throws: nothing.
shared_ptr(const shared_ptr &other, const pointer &p)
Added: trunk/boost/interprocess/sync/detail/condition_algorithm_8a.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/detail/condition_algorithm_8a.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,316 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
+#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <limits>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+//
+// Condition variable algorithm taken from pthreads-win32 discussion.
+//
+// The algorithm was developed by Alexander Terekhov in colaboration with
+// Louis Thomas.
+//
+// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
+//
+// semBlockLock - bin.semaphore
+// semBlockQueue - semaphore
+// mtxExternal - mutex or CS
+// mtxUnblockLock - mutex or CS
+// nWaitersGone - int
+// nWaitersBlocked - int
+// nWaitersToUnblock - int
+//
+// wait( timeout ) {
+//
+// [auto: register int result ] // error checking omitted
+// [auto: register int nSignalsWasLeft ]
+// [auto: register int nWaitersWasGone ]
+//
+// sem_wait( semBlockLock );
+// nWaitersBlocked++;
+// sem_post( semBlockLock );
+//
+// unlock( mtxExternal );
+// bTimedOut = sem_wait( semBlockQueue,timeout );
+//
+// lock( mtxUnblockLock );
+// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
+// if ( bTimedOut ) { // timeout (or canceled)
+// if ( 0 != nWaitersBlocked ) {
+// nWaitersBlocked--;
+// }
+// else {
+// nWaitersGone++; // count spurious wakeups.
+// }
+// }
+// if ( 0 == --nWaitersToUnblock ) {
+// if ( 0 != nWaitersBlocked ) {
+// sem_post( semBlockLock ); // open the gate.
+// nSignalsWasLeft = 0; // do not open the gate
+// // below again.
+// }
+// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
+// nWaitersGone = 0;
+// }
+// }
+// }
+// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
+// // spurious semaphore :-)
+// sem_wait( semBlockLock );
+// nWaitersBlocked -= nWaitersGone; // something is going on here
+// // - test of timeouts? :-)
+// sem_post( semBlockLock );
+// nWaitersGone = 0;
+// }
+// unlock( mtxUnblockLock );
+//
+// if ( 1 == nSignalsWasLeft ) {
+// if ( 0 != nWaitersWasGone ) {
+// // sem_adjust( semBlockQueue,-nWaitersWasGone );
+// while ( nWaitersWasGone-- ) {
+// sem_wait( semBlockQueue ); // better now than spurious later
+// }
+// } sem_post( semBlockLock ); // open the gate
+// }
+//
+// lock( mtxExternal );
+//
+// return ( bTimedOut ) ? ETIMEOUT : 0;
+// }
+//
+// signal(bAll) {
+//
+// [auto: register int result ]
+// [auto: register int nSignalsToIssue]
+//
+// lock( mtxUnblockLock );
+//
+// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
+// if ( 0 == nWaitersBlocked ) { // NO-OP
+// return unlock( mtxUnblockLock );
+// }
+// if (bAll) {
+// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
+// nWaitersBlocked = 0;
+// }
+// else {
+// nSignalsToIssue = 1;
+// nWaitersToUnblock++;
+// nWaitersBlocked--;
+// }
+// }
+// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
+// sem_wait( semBlockLock ); // close the gate
+// if ( 0 != nWaitersGone ) {
+// nWaitersBlocked -= nWaitersGone;
+// nWaitersGone = 0;
+// }
+// if (bAll) {
+// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
+// nWaitersBlocked = 0;
+// }
+// else {
+// nSignalsToIssue = nWaitersToUnblock = 1;
+// nWaitersBlocked--;
+// }
+// }
+// else { // NO-OP
+// return unlock( mtxUnblockLock );
+// }
+//
+// unlock( mtxUnblockLock );
+// sem_post( semBlockQueue,nSignalsToIssue );
+// return result;
+// }
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+
+// Required interface for ConditionMembers
+// class ConditionMembers
+// {
+// typedef implementation_defined semaphore_type;
+// typedef implementation_defined mutex_type;
+// typedef implementation_defined integer_type;
+//
+// integer_type &get_nwaiters_blocked()
+// integer_type &get_nwaiters_gone()
+// integer_type &get_nwaiters_to_unblock()
+// semaphore_type &get_sem_block_queue()
+// semaphore_type &get_sem_block_lock()
+// mutex_type &get_mtx_unblock_lock()
+// };
+//
+template<class ConditionMembers>
+class condition_algorithm_8a
+{
+ private:
+ condition_algorithm_8a();
+ ~condition_algorithm_8a();
+ condition_algorithm_8a(const condition_algorithm_8a &);
+ condition_algorithm_8a &operator=(const condition_algorithm_8a &);
+
+ typedef typename ConditionMembers::semaphore_type semaphore_type;
+ typedef typename ConditionMembers::mutex_type mutex_type;
+ typedef typename ConditionMembers::integer_type integer_type;
+
+ // nwaiters_blocked == 0
+ // nwaiters_gone() == 0
+ // nwaiters_to_unblock == 0
+ // sem_block_queue() == initial count 0
+ // sem_block_lock() == initial count 1
+ // mtx_unblock_lock (unlocked)
+
+ public:
+ template<class InterprocessMutex>
+ static bool wait (ConditionMembers &data, bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
+ static void signal(ConditionMembers &data, bool broadcast);
+};
+
+template<class ConditionMembers>
+inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &data, bool broadcast)
+{
+ integer_type nsignals_to_issue;
+
+ {
+ scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
+
+ if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!!
+ if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ return;
+ }
+ if (broadcast) {
+ data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked();
+ data.get_nwaiters_blocked() = 0;
+ }
+ else {
+ nsignals_to_issue = 1;
+ data.get_nwaiters_to_unblock()++;
+ data.get_nwaiters_blocked()--;
+ }
+ }
+ else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION!
+ data.get_sem_block_lock().wait(); // close the gate
+ if ( 0 != data.get_nwaiters_gone() ) {
+ data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
+ data.get_nwaiters_gone() = 0;
+ }
+ if (broadcast) {
+ nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked();
+ data.get_nwaiters_blocked() = 0;
+ }
+ else {
+ nsignals_to_issue = data.get_nwaiters_to_unblock() = 1;
+ data.get_nwaiters_blocked()--;
+ }
+ }
+ else { // NO-OP
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ return;
+ }
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ }
+ data.get_sem_block_queue().post(nsignals_to_issue);
+}
+
+template<class ConditionMembers>
+template<class InterprocessMutex>
+inline bool condition_algorithm_8a<ConditionMembers>::wait
+ (ConditionMembers &data, bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal)
+{
+ //Initialize to avoid warnings
+ integer_type nsignals_was_left = 0;
+ integer_type nwaiters_was_gone = 0;
+
+ data.get_sem_block_lock().wait();
+ ++data.get_nwaiters_blocked();
+ data.get_sem_block_lock().post();
+
+ struct scoped_unlock
+ {
+ InterprocessMutex & mut;
+ scoped_unlock(InterprocessMutex & m)
+ : mut(m)
+ { m.unlock(); }
+
+ ~scoped_unlock()
+ { mut.lock(); }
+ } unlocker(mtxExternal);
+
+
+ bool bTimedOut = tout_enabled ? !data.get_sem_block_queue().timed_wait(abs_time) : (data.get_sem_block_queue().wait(), false);
+
+ {
+ scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
+ if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) {
+ if ( bTimedOut ) { // timeout (or canceled)
+ if ( 0 != data.get_nwaiters_blocked() ) {
+ data.get_nwaiters_blocked()--;
+ }
+ else {
+ data.get_nwaiters_gone()++; // count spurious wakeups.
+ }
+ }
+ if ( 0 == --data.get_nwaiters_to_unblock() ) {
+ if ( 0 != data.get_nwaiters_blocked() ) {
+ data.get_sem_block_lock().post(); // open the gate.
+ nsignals_was_left = 0; // do not open the gate below again.
+ }
+ else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) {
+ data.get_nwaiters_gone() = 0;
+ }
+ }
+ }
+ else if ( (std::numeric_limits<integer_type>::max)()/2
+ == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-)
+ data.get_sem_block_lock().wait();
+ data.get_nwaiters_blocked() -= data.get_nwaiters_gone(); // something is going on here - test of timeouts? :-)
+ data.get_sem_block_lock().post();
+ data.get_nwaiters_gone() = 0;
+ }
+ //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
+ }
+
+ if ( 1 == nsignals_was_left ) {
+ if ( 0 != nwaiters_was_gone ) {
+ // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone );
+ while ( nwaiters_was_gone-- ) {
+ data.get_sem_block_queue().wait(); // better now than spurious later
+ }
+ }
+ data.get_sem_block_lock().post(); // open the gate
+ }
+
+ //mtxExternal.lock(); called from unlocker
+
+ return ( bTimedOut ) ? false : true;
+}
+
+} //namespace ipcdetail
+} //namespace interprocess
+} //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
Modified: trunk/boost/interprocess/sync/interprocess_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_condition.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_condition.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -30,9 +30,9 @@
#include <boost/interprocess/sync/posix/condition.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
-//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
-// #include <boost/interprocess/sync/windows/condition.hpp>
-// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/condition.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#include <boost/interprocess/sync/spin/condition.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
Modified: trunk/boost/interprocess/sync/interprocess_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_mutex.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -31,9 +31,9 @@
#include <boost/interprocess/sync/posix/mutex.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
-//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
-// #include <boost/interprocess/sync/windows/mutex.hpp>
-// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#include <boost/interprocess/sync/spin/mutex.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
Modified: trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -43,9 +43,9 @@
#include <boost/interprocess/sync/posix/recursive_mutex.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
-//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
-// #include <boost/interprocess/sync/windows/recursive_mutex.hpp>
-// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/recursive_mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
Modified: trunk/boost/interprocess/sync/interprocess_semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_semaphore.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -29,9 +29,9 @@
#include <boost/interprocess/sync/posix/semaphore.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
-//#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
-// #include <boost/interprocess/sync/windows/semaphore.hpp>
-// #define BOOST_INTERPROCESS_USE_WINDOWS
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/semaphore.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#include <boost/interprocess/sync/spin/semaphore.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
Modified: trunk/boost/interprocess/sync/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/named_condition.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -22,7 +22,12 @@
#include <boost/interprocess/detail/interprocess_tester.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
-#include <boost/interprocess/sync/shm/named_condition.hpp>
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/named_condition.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
+#else
+ #include <boost/interprocess/sync/shm/named_condition.hpp>
+#endif
//!\file
//!Describes a named condition class for inter-process synchronization
@@ -110,7 +115,12 @@
/// @cond
private:
- ipcdetail::shm_named_condition m_cond;
+ #if defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ typedef ipcdetail::windows_named_condition condition_type;
+ #else
+ typedef ipcdetail::shm_named_condition condition_type;
+ #endif
+ condition_type m_cond;
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction()
@@ -160,7 +170,7 @@
{ return m_cond.timed_wait(lock, abs_time, pred); }
inline bool named_condition::remove(const char *name)
-{ return ipcdetail::shm_named_condition::remove(name); }
+{ return condition_type::remove(name); }
/// @endcond
Modified: trunk/boost/interprocess/sync/named_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/named_mutex.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -24,7 +24,11 @@
#include <boost/interprocess/permissions.hpp>
#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
-#include <boost/interprocess/sync/posix/named_mutex.hpp>
+ #include <boost/interprocess/sync/posix/named_mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/named_mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
#else
#include <boost/interprocess/sync/shm/named_mutex.hpp>
#endif
@@ -104,15 +108,20 @@
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
- #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
- typedef ipcdetail::posix_named_mutex impl_t;
- impl_t m_mut;
+ #if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES)
+ typedef ipcdetail::posix_named_mutex impl_t;
+ impl_t m_mut;
+ #undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES
+ #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ typedef ipcdetail::windows_named_mutex impl_t;
+ impl_t m_mut;
+ #undef BOOST_INTERPROCESS_USE_WINDOWS
#else
- typedef ipcdetail::shm_named_mutex impl_t;
- impl_t m_mut;
- public:
- interprocess_mutex *mutex() const
- { return m_mut.mutex(); }
+ typedef ipcdetail::shm_named_mutex impl_t;
+ impl_t m_mut;
+ public:
+ interprocess_mutex *mutex() const
+ { return m_mut.mutex(); }
#endif
/// @endcond
Modified: trunk/boost/interprocess/sync/named_recursive_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_recursive_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/named_recursive_mutex.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -20,7 +20,12 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/permissions.hpp>
-#include <boost/interprocess/sync/shm/named_recursive_mutex.hpp>
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/named_recursive_mutex.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
+#else
+ #include <boost/interprocess/sync/shm/named_recursive_mutex.hpp>
+#endif
//!\file
//!Describes a named named_recursive_mutex class for inter-process synchronization
@@ -97,7 +102,12 @@
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
- typedef ipcdetail::shm_named_recursive_mutex impl_t;
+ #if defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ typedef ipcdetail::windows_named_recursive_mutex impl_t;
+ #undef BOOST_INTERPROCESS_USE_WINDOWS
+ #else
+ typedef ipcdetail::shm_named_recursive_mutex impl_t;
+ #endif
impl_t m_mut;
/// @endcond
Modified: trunk/boost/interprocess/sync/named_semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/named_semaphore.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -25,6 +25,10 @@
#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES)
#include <boost/interprocess/sync/posix/named_semaphore.hpp>
+//Experimental...
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
+ #include <boost/interprocess/sync/windows/named_semaphore.hpp>
+ #define BOOST_INTERPROCESS_USE_WINDOWS
#else
#include <boost/interprocess/sync/shm/named_semaphore.hpp>
#endif
@@ -106,9 +110,12 @@
void dont_close_on_destruction();
#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES)
- typedef ipcdetail::posix_named_semaphore impl_t;
+ typedef ipcdetail::posix_named_semaphore impl_t;
+ #elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
+ #undef BOOST_INTERPROCESS_USE_WINDOWS
+ typedef ipcdetail::windows_named_semaphore impl_t;
#else
- typedef ipcdetail::shm_named_semaphore impl_t;
+ typedef ipcdetail::shm_named_semaphore impl_t;
#endif
impl_t m_sem;
/// @endcond
Modified: trunk/boost/interprocess/sync/shm/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/shm/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/shm/named_condition.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -28,7 +28,7 @@
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/permissions.hpp>
-#if defined BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
+#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#endif
@@ -42,7 +42,7 @@
namespace ipcdetail {
/// @cond
-namespace ipcdetail{ class interprocess_tester; }
+class interprocess_tester;
/// @endcond
//! A global condition variable that can be created by name.
@@ -147,6 +147,9 @@
void unlock() { l_.lock(); }
};
+ //If named mutex uses POSIX semaphores, then the shm based condition variable
+ //must use it's internal lock to wait, as sem_t does not store a pthread_mutex_t
+ //instance needed by pthread_mutex_cond_t
#if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
interprocess_mutex *mutex() const
{ return &static_cast<condition_holder*>(m_shmem.get_user_address())->mutex_; }
@@ -184,7 +187,7 @@
internal_lock.swap(internal_unlock);
return this->condition()->timed_wait(internal_unlock, abs_time);
}
- #else
+ #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
template<class Lock>
class lock_wrapper
{
@@ -210,7 +213,7 @@
private:
Lock &l_;
};
- #endif
+ #endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
friend class boost::interprocess::ipcdetail::interprocess_tester;
void dont_close_on_destruction();
Modified: trunk/boost/interprocess/sync/windows/condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/condition.hpp (original)
+++ trunk/boost/interprocess/sync/windows/condition.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -20,133 +20,8 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/sync/windows/semaphore.hpp>
#include <boost/interprocess/sync/windows/mutex.hpp>
-#include <boost/cstdint.hpp>
-#include <limits>
+#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp>
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-//
-// Condition variable algorithm taken from pthreads-win32 discussion.
-//
-// The algorithm was developed by Alexander Terekhov in colaboration with
-// Louis Thomas.
-//
-// Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
-//
-// semBlockLock - bin.semaphore
-// semBlockQueue - semaphore
-// mtxExternal - mutex or CS
-// mtxUnblockLock - mutex or CS
-// nWaitersGone - int
-// nWaitersBlocked - int
-// nWaitersToUnblock - int
-//
-// wait( timeout ) {
-//
-// [auto: register int result ] // error checking omitted
-// [auto: register int nSignalsWasLeft ]
-// [auto: register int nWaitersWasGone ]
-//
-// sem_wait( semBlockLock );
-// nWaitersBlocked++;
-// sem_post( semBlockLock );
-//
-// unlock( mtxExternal );
-// bTimedOut = sem_wait( semBlockQueue,timeout );
-//
-// lock( mtxUnblockLock );
-// if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
-// if ( bTimedOut ) { // timeout (or canceled)
-// if ( 0 != nWaitersBlocked ) {
-// nWaitersBlocked--;
-// }
-// else {
-// nWaitersGone++; // count spurious wakeups.
-// }
-// }
-// if ( 0 == --nWaitersToUnblock ) {
-// if ( 0 != nWaitersBlocked ) {
-// sem_post( semBlockLock ); // open the gate.
-// nSignalsWasLeft = 0; // do not open the gate
-// // below again.
-// }
-// else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
-// nWaitersGone = 0;
-// }
-// }
-// }
-// else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
-// // spurious semaphore :-)
-// sem_wait( semBlockLock );
-// nWaitersBlocked -= nWaitersGone; // something is going on here
-// // - test of timeouts? :-)
-// sem_post( semBlockLock );
-// nWaitersGone = 0;
-// }
-// unlock( mtxUnblockLock );
-//
-// if ( 1 == nSignalsWasLeft ) {
-// if ( 0 != nWaitersWasGone ) {
-// // sem_adjust( semBlockQueue,-nWaitersWasGone );
-// while ( nWaitersWasGone-- ) {
-// sem_wait( semBlockQueue ); // better now than spurious later
-// }
-// } sem_post( semBlockLock ); // open the gate
-// }
-//
-// lock( mtxExternal );
-//
-// return ( bTimedOut ) ? ETIMEOUT : 0;
-// }
-//
-// signal(bAll) {
-//
-// [auto: register int result ]
-// [auto: register int nSignalsToIssue]
-//
-// lock( mtxUnblockLock );
-//
-// if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
-// if ( 0 == nWaitersBlocked ) { // NO-OP
-// return unlock( mtxUnblockLock );
-// }
-// if (bAll) {
-// nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
-// nWaitersBlocked = 0;
-// }
-// else {
-// nSignalsToIssue = 1;
-// nWaitersToUnblock++;
-// nWaitersBlocked--;
-// }
-// }
-// else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
-// sem_wait( semBlockLock ); // close the gate
-// if ( 0 != nWaitersGone ) {
-// nWaitersBlocked -= nWaitersGone;
-// nWaitersGone = 0;
-// }
-// if (bAll) {
-// nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
-// nWaitersBlocked = 0;
-// }
-// else {
-// nSignalsToIssue = nWaitersToUnblock = 1;
-// nWaitersBlocked--;
-// }
-// }
-// else { // NO-OP
-// return unlock( mtxUnblockLock );
-// }
-//
-// unlock( mtxUnblockLock );
-// sem_post( semBlockQueue,nSignalsToIssue );
-// return result;
-// }
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
namespace boost {
namespace interprocess {
@@ -156,6 +31,7 @@
{
windows_condition(const windows_condition &);
windows_condition &operator=(const windows_condition &);
+
public:
windows_condition();
~windows_condition();
@@ -217,162 +93,71 @@
private:
- template<class InterprocessMutex>
- bool do_timed_wait(bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut);
- void do_signal (bool broadcast);
+ struct condition_data
+ {
+ typedef boost::int32_t integer_type;
+ typedef windows_semaphore semaphore_type;
+ typedef windows_mutex mutex_type;
+
+ condition_data()
+ : m_nwaiters_blocked(0)
+ , m_nwaiters_gone(0)
+ , m_nwaiters_to_unblock(0)
+ , m_sem_block_queue(0)
+ , m_sem_block_lock(1)
+ , m_mtx_unblock_lock()
+ {}
+
+ integer_type &get_nwaiters_blocked()
+ { return m_nwaiters_blocked; }
+
+ integer_type &get_nwaiters_gone()
+ { return m_nwaiters_gone; }
+
+ integer_type &get_nwaiters_to_unblock()
+ { return m_nwaiters_to_unblock; }
+
+ semaphore_type &get_sem_block_queue()
+ { return m_sem_block_queue; }
+
+ semaphore_type &get_sem_block_lock()
+ { return m_sem_block_lock; }
+
+ mutex_type &get_mtx_unblock_lock()
+ { return m_mtx_unblock_lock; }
+
+ boost::int32_t m_nwaiters_blocked;
+ boost::int32_t m_nwaiters_gone;
+ boost::int32_t m_nwaiters_to_unblock;
+ windows_semaphore m_sem_block_queue;
+ windows_semaphore m_sem_block_lock;
+ windows_mutex m_mtx_unblock_lock;
+ } m_condition_data;
- boost::int32_t m_nwaiters_blocked;
- boost::int32_t m_nwaiters_gone;
- boost::int32_t m_nwaiters_to_unblock;
- windows_semaphore m_sem_block_queue;
- windows_semaphore m_sem_block_lock;
- windows_mutex m_mtx_unblock_lock;
+ typedef condition_algorithm_8a<condition_data> algorithm_type;
};
inline windows_condition::windows_condition()
- : m_nwaiters_blocked(0)
- , m_nwaiters_gone(0)
- , m_nwaiters_to_unblock(0)
- , m_sem_block_queue(0)
- , m_sem_block_lock(1)
- , m_mtx_unblock_lock()
+ : m_condition_data()
{}
inline windows_condition::~windows_condition()
{}
inline void windows_condition::notify_one()
-{ this->do_signal(false); }
+{ algorithm_type::signal(m_condition_data, false); }
inline void windows_condition::notify_all()
-{ this->do_signal(true); }
-
-inline void windows_condition::do_signal(bool broadcast)
-{
- boost::int32_t nsignals_to_issue;
-
- {
- scoped_lock<windows_mutex> locker(m_mtx_unblock_lock);
-
- if ( 0 != m_nwaiters_to_unblock ) { // the gate is closed!!!
- if ( 0 == m_nwaiters_blocked ) { // NO-OP
- //locker's destructor triggers m_mtx_unblock_lock.unlock()
- return;
- }
- if (broadcast) {
- m_nwaiters_to_unblock += nsignals_to_issue = m_nwaiters_blocked;
- m_nwaiters_blocked = 0;
- }
- else {
- nsignals_to_issue = 1;
- m_nwaiters_to_unblock++;
- m_nwaiters_blocked--;
- }
- }
- else if ( m_nwaiters_blocked > m_nwaiters_gone ) { // HARMLESS RACE CONDITION!
- m_sem_block_lock.wait(); // close the gate
- if ( 0 != m_nwaiters_gone ) {
- m_nwaiters_blocked -= m_nwaiters_gone;
- m_nwaiters_gone = 0;
- }
- if (broadcast) {
- nsignals_to_issue = m_nwaiters_to_unblock = m_nwaiters_blocked;
- m_nwaiters_blocked = 0;
- }
- else {
- nsignals_to_issue = m_nwaiters_to_unblock = 1;
- m_nwaiters_blocked--;
- }
- }
- else { // NO-OP
- //locker's destructor triggers m_mtx_unblock_lock.unlock()
- return;
- }
- //locker's destructor triggers m_mtx_unblock_lock.unlock()
- }
- m_sem_block_queue.post(nsignals_to_issue);
-}
+{ algorithm_type::signal(m_condition_data, true); }
template<class InterprocessMutex>
inline void windows_condition::do_wait(InterprocessMutex &mut)
-{ this->do_timed_wait(false, boost::posix_time::ptime(), mut); }
+{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); }
template<class InterprocessMutex>
inline bool windows_condition::do_timed_wait
(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
-{ return this->do_timed_wait(true, abs_time, mut); }
-
-template<class InterprocessMutex>
-inline bool windows_condition::do_timed_wait
- (bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal)
-{
- //Initialize to avoid warnings
- boost::int32_t nsignals_was_left = 0;
- boost::int32_t nwaiters_was_gone = 0;
-
- m_sem_block_lock.wait();
- ++m_nwaiters_blocked;
- m_sem_block_lock.post();
-
- struct scoped_unlock
- {
- InterprocessMutex & mut;
- scoped_unlock(InterprocessMutex & m)
- : mut(m)
- { m.unlock(); }
-
- ~scoped_unlock()
- { mut.lock(); }
- } unlocker(mtxExternal);
-
-
- bool bTimedOut = tout_enabled ? !m_sem_block_queue.timed_wait(abs_time) : (m_sem_block_queue.wait(), false);
-
- {
- scoped_lock<windows_mutex> locker(m_mtx_unblock_lock);
- if ( 0 != (nsignals_was_left = m_nwaiters_to_unblock) ) {
- if ( bTimedOut ) { // timeout (or canceled)
- if ( 0 != m_nwaiters_blocked ) {
- m_nwaiters_blocked--;
- }
- else {
- m_nwaiters_gone++; // count spurious wakeups.
- }
- }
- if ( 0 == --m_nwaiters_to_unblock ) {
- if ( 0 != m_nwaiters_blocked ) {
- m_sem_block_lock.post(); // open the gate.
- nsignals_was_left = 0; // do not open the gate below again.
- }
- else if ( 0 != (nwaiters_was_gone = m_nwaiters_gone) ) {
- m_nwaiters_gone = 0;
- }
- }
- }
- else if ( (std::numeric_limits<boost::int32_t>::max)()/2
- == ++m_nwaiters_gone ) { // timeout/canceled or spurious semaphore :-)
- m_sem_block_lock.wait();
- m_nwaiters_blocked -= m_nwaiters_gone; // something is going on here - test of timeouts? :-)
- m_sem_block_lock.post();
- m_nwaiters_gone = 0;
- }
- //locker's destructor triggers m_mtx_unblock_lock.unlock()
- }
-
- if ( 1 == nsignals_was_left ) {
- if ( 0 != nwaiters_was_gone ) {
- // sem_adjust( m_sem_block_queue,-nwaiters_was_gone );
- while ( nwaiters_was_gone-- ) {
- m_sem_block_queue.wait(); // better now than spurious later
- }
- }
- m_sem_block_lock.post(); // open the gate
- }
-
- //mtxExternal.lock(); called from unlocker
-
- return ( bTimedOut ) ? false : true;
-}
+{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); }
} //namespace ipcdetail
} //namespace interprocess
Modified: trunk/boost/interprocess/sync/windows/mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/mutex.hpp (original)
+++ trunk/boost/interprocess/sync/windows/mutex.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -19,8 +19,9 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
-#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -51,7 +52,7 @@
: id_()
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//Create mutex with the initial count
bool open_or_created;
handles.obtain_mutex(this->id_, &open_or_created);
@@ -64,68 +65,44 @@
inline windows_mutex::~windows_mutex()
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
handles.destroy_handle(this->id_);
}
inline void windows_mutex::lock(void)
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//This can throw
- void *hnd = handles.obtain_mutex(this->id_);
- unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time);
- if(ret == winapi::wait_failed){
- error_info err(winapi::get_last_error());
- throw interprocess_exception(err);
- }
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ mut.lock();
}
inline bool windows_mutex::try_lock(void)
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//This can throw
- void *hnd = handles.obtain_mutex(this->id_);
- unsigned long ret = winapi::wait_for_single_object(hnd, 0);
- if(ret == winapi::wait_failed){
- error_info err(winapi::get_last_error());
- throw interprocess_exception(err);
- }
- return ret != winapi::wait_timeout;
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ return mut.try_lock();
}
inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->lock();
- return true;
- }
- boost::posix_time::ptime now
- = boost::posix_time::microsec_clock::universal_time();
-
- unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds();
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//This can throw
- void *hnd = handles.obtain_mutex(this->id_);
- unsigned long ret = winapi::wait_for_single_object(hnd, ms);
- if(ret == winapi::wait_failed){
- error_info err(winapi::get_last_error());
- throw interprocess_exception(err);
- }
- return ret != winapi::wait_timeout;
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ return mut.timed_lock(abs_time);
}
inline void windows_mutex::unlock(void)
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//This can throw
- void *hnd = handles.obtain_mutex(this->id_);
- int ret = winapi::release_mutex(hnd);
- (void)ret;
- assert(ret);
+ winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
+ return mut.unlock();
}
} //namespace ipcdetail {
Added: trunk/boost/interprocess/sync/windows/named_condition.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/named_condition.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,331 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP
+#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/windows/named_sync.hpp>
+#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
+#include <boost/interprocess/sync/detail/condition_algorithm_8a.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_named_condition
+{
+ /// @cond
+
+ //Non-copyable
+ windows_named_condition();
+ windows_named_condition(const windows_named_condition &);
+ windows_named_condition &operator=(const windows_named_condition &);
+ /// @endcond
+
+ public:
+ windows_named_condition(create_only_t, const char *name, const permissions &perm = permissions());
+
+ windows_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions());
+
+ windows_named_condition(open_only_t, const char *name);
+
+ ~windows_named_condition();
+
+ //!If there is a thread waiting on *this, change that
+ //!thread's state to ready. Otherwise there is no effect.*/
+ void notify_one();
+
+ //!Change the state of all threads waiting on *this to ready.
+ //!If there are no waiting threads, notify_all() has no effect.
+ void notify_all();
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), and then reacquires the lock.
+ template <typename L>
+ void wait(L& lock);
+
+ //!The same as:
+ //!while (!pred()) wait(lock)
+ template <typename L, typename Pr>
+ void wait(L& lock, Pr pred);
+
+ //!Releases the lock on the named_mutex object associated with lock, blocks
+ //!the current thread of execution until readied by a call to
+ //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
+ //!and then reacquires the lock.
+ //!Returns: false if time abs_time is reached, otherwise true.
+ template <typename L>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time);
+
+ //!The same as: while (!pred()) {
+ //! if (!timed_wait(lock, abs_time)) return pred();
+ //! } return true;
+ template <typename L, typename Pr>
+ bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred);
+
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class interprocess_tester;
+ void dont_close_on_destruction();
+
+ template <class InterprocessMutex>
+ void do_wait(InterprocessMutex& lock);
+
+ template <class InterprocessMutex>
+ bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex& lock);
+
+ struct condition_data
+ {
+ typedef boost::int32_t integer_type;
+ typedef winapi_semaphore_wrapper semaphore_type;
+ typedef winapi_mutex_wrapper mutex_type;
+
+ integer_type &get_nwaiters_blocked()
+ { return m_nwaiters_blocked; }
+
+ integer_type &get_nwaiters_gone()
+ { return m_nwaiters_gone; }
+
+ integer_type &get_nwaiters_to_unblock()
+ { return m_nwaiters_to_unblock; }
+
+ semaphore_type &get_sem_block_queue()
+ { return m_sem_block_queue; }
+
+ semaphore_type &get_sem_block_lock()
+ { return m_sem_block_lock; }
+
+ mutex_type &get_mtx_unblock_lock()
+ { return m_mtx_unblock_lock; }
+
+ integer_type m_nwaiters_blocked;
+ integer_type m_nwaiters_gone;
+ integer_type m_nwaiters_to_unblock;
+ winapi_semaphore_wrapper m_sem_block_queue;
+ winapi_semaphore_wrapper m_sem_block_lock;
+ winapi_mutex_wrapper m_mtx_unblock_lock;
+ } m_condition_data;
+
+ typedef condition_algorithm_8a<condition_data> algorithm_type;
+
+ class named_cond_callbacks : public windows_named_sync_interface
+ {
+ typedef __int64 sem_count_t;
+ mutable sem_count_t sem_counts [2];
+
+ public:
+ named_cond_callbacks(condition_data &cond_data)
+ : m_condition_data(cond_data)
+ {}
+
+ virtual std::size_t get_data_size() const
+ { return sizeof(sem_counts); }
+
+ virtual const void *buffer_with_final_data_to_file()
+ {
+ sem_counts[0] = m_condition_data.m_sem_block_queue.value();
+ sem_counts[1] = m_condition_data.m_sem_block_lock.value();
+ return &sem_counts;
+ }
+
+ virtual const void *buffer_with_init_data_to_file()
+ {
+ sem_counts[0] = 0;
+ sem_counts[1] = 1;
+ return &sem_counts;
+ }
+
+ virtual void *buffer_to_store_init_data_from_file()
+ { return &sem_counts; }
+
+ virtual bool open(create_enum_t, const char *id_name)
+ {
+ m_condition_data.m_nwaiters_blocked = 0;
+ m_condition_data.m_nwaiters_gone = 0;
+ m_condition_data.m_nwaiters_to_unblock = 0;
+
+ //Now open semaphores and mutex.
+ //Use local variables + swap to guarantee consistent
+ //initialization and cleanup in case any opening fails
+ permissions perm;
+ perm.set_unrestricted();
+ std::string aux_str = "Global\\bipc.cond.";
+ aux_str += id_name;
+ std::size_t pos = aux_str.size();
+
+ //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))
+ 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))
+ return false;
+ aux_str.erase(pos);
+
+ //mtx_unblock_lock
+ aux_str += "_ul";
+ winapi_mutex_wrapper mtx_unblock_lock;
+ if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm))
+ return false;
+
+ //All ok, commit data
+ m_condition_data.m_sem_block_queue.swap(sem_block_queue);
+ m_condition_data.m_sem_block_lock.swap(sem_block_lock);
+ m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock);
+ return true;
+ }
+
+ virtual void close()
+ {
+ m_condition_data.m_sem_block_queue.close();
+ m_condition_data.m_sem_block_lock.close();
+ m_condition_data.m_mtx_unblock_lock.close();
+ m_condition_data.m_nwaiters_blocked = 0;
+ m_condition_data.m_nwaiters_gone = 0;
+ m_condition_data.m_nwaiters_to_unblock = 0;
+ }
+
+ virtual ~named_cond_callbacks()
+ {}
+
+ private:
+ condition_data &m_condition_data;
+ };
+
+ windows_named_sync m_named_sync;
+ /// @endcond
+};
+
+inline windows_named_condition::~windows_named_condition()
+{
+ named_cond_callbacks callbacks(m_condition_data);
+ m_named_sync.close(callbacks);
+}
+
+inline void windows_named_condition::dont_close_on_destruction()
+{}
+
+inline windows_named_condition::windows_named_condition
+ (create_only_t, const char *name, const permissions &perm)
+ : m_condition_data()
+{
+ named_cond_callbacks callbacks(m_condition_data);
+ m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
+}
+
+inline windows_named_condition::windows_named_condition
+ (open_or_create_t, const char *name, const permissions &perm)
+ : m_condition_data()
+{
+ named_cond_callbacks callbacks(m_condition_data);
+ m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
+}
+
+inline windows_named_condition::windows_named_condition(open_only_t, const char *name)
+ : m_condition_data()
+{
+ named_cond_callbacks callbacks(m_condition_data);
+ m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
+}
+
+inline void windows_named_condition::notify_one()
+{ algorithm_type::signal(m_condition_data, false); }
+
+inline void windows_named_condition::notify_all()
+{ algorithm_type::signal(m_condition_data, true); }
+
+template<class InterprocessMutex>
+inline void windows_named_condition::do_wait(InterprocessMutex &mut)
+{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); }
+
+template<class InterprocessMutex>
+inline bool windows_named_condition::do_timed_wait
+ (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut)
+{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); }
+
+template <typename L>
+inline void windows_named_condition::wait(L& lock)
+{
+ if (!lock)
+ throw lock_exception();
+ this->do_wait(*lock.mutex());
+}
+
+template <typename L, typename Pr>
+inline void windows_named_condition::wait(L& lock, Pr pred)
+{
+ if (!lock)
+ throw lock_exception();
+ while (!pred())
+ this->do_wait(*lock.mutex());
+}
+
+template <typename L>
+inline bool windows_named_condition::timed_wait
+ (L& lock, const boost::posix_time::ptime &abs_time)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+ return this->do_timed_wait(abs_time, *lock.mutex());
+}
+
+template <typename L, typename Pr>
+inline bool windows_named_condition::timed_wait
+ (L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
+ if (!lock)
+ throw lock_exception();
+
+ while (!pred()){
+ if(!this->do_timed_wait(abs_time, *lock.mutex())){
+ return pred();
+ }
+ }
+ return true;
+}
+
+inline bool windows_named_condition::remove(const char *name)
+{
+ return windows_named_sync::remove(name);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_HPP
Added: trunk/boost/interprocess/sync/windows/named_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/named_mutex.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,175 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
+#define BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/sync/windows/named_sync.hpp>
+#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <limits>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+
+
+class windows_named_mutex
+{
+ /// @cond
+
+ //Non-copyable
+ windows_named_mutex();
+ windows_named_mutex(const windows_named_mutex &);
+ windows_named_mutex &operator=(const windows_named_mutex &);
+ /// @endcond
+
+ public:
+ windows_named_mutex(create_only_t, const char *name, const permissions &perm = permissions());
+
+ windows_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
+
+ windows_named_mutex(open_only_t, const char *name);
+
+ ~windows_named_mutex();
+
+ void unlock();
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class interprocess_tester;
+ void dont_close_on_destruction();
+ winapi_mutex_wrapper m_mtx_wrapper;
+ windows_named_sync m_named_sync;
+
+ class named_mut_callbacks : public windows_named_sync_interface
+ {
+ public:
+ named_mut_callbacks(winapi_mutex_wrapper &mtx_wrapper)
+ : m_mtx_wrapper(mtx_wrapper)
+ {}
+
+ virtual std::size_t get_data_size() const
+ { return 0u; }
+
+ virtual const void *buffer_with_init_data_to_file()
+ { return 0; }
+
+ virtual const void *buffer_with_final_data_to_file()
+ { return 0; }
+
+ virtual void *buffer_to_store_init_data_from_file()
+ { return 0; }
+
+ virtual bool open(create_enum_t, const char *id_name)
+ {
+ std::string aux_str = "Global\\bipc.mut.";
+ aux_str += id_name;
+ //
+ permissions mut_perm;
+ mut_perm.set_unrestricted();
+ return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm);
+ }
+
+ virtual void close()
+ {
+ m_mtx_wrapper.close();
+ }
+
+ virtual ~named_mut_callbacks()
+ {}
+
+ private:
+ winapi_mutex_wrapper& m_mtx_wrapper;
+ };
+ /// @endcond
+};
+
+inline windows_named_mutex::~windows_named_mutex()
+{
+ named_mut_callbacks callbacks(m_mtx_wrapper);
+ m_named_sync.close(callbacks);
+}
+
+inline void windows_named_mutex::dont_close_on_destruction()
+{}
+
+inline windows_named_mutex::windows_named_mutex
+ (create_only_t, const char *name, const permissions &perm)
+ : m_mtx_wrapper()
+{
+ named_mut_callbacks callbacks(m_mtx_wrapper);
+ m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
+}
+
+inline windows_named_mutex::windows_named_mutex
+ (open_or_create_t, const char *name, const permissions &perm)
+ : m_mtx_wrapper()
+{
+ named_mut_callbacks callbacks(m_mtx_wrapper);
+ m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
+}
+
+inline windows_named_mutex::windows_named_mutex(open_only_t, const char *name)
+ : m_mtx_wrapper()
+{
+ named_mut_callbacks callbacks(m_mtx_wrapper);
+ m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
+}
+
+inline void windows_named_mutex::unlock()
+{
+ m_mtx_wrapper.unlock();
+}
+
+inline void windows_named_mutex::lock()
+{
+ m_mtx_wrapper.lock();
+}
+
+inline bool windows_named_mutex::try_lock()
+{
+ return m_mtx_wrapper.try_lock();
+}
+
+inline bool windows_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
+{
+ return m_mtx_wrapper.timed_lock(abs_time);
+}
+
+inline bool windows_named_mutex::remove(const char *name)
+{
+ return windows_named_sync::remove(name);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
\ No newline at end of file
Added: trunk/boost/interprocess/sync/windows/named_recursive_mutex.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/named_recursive_mutex.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,58 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP
+#define BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/windows/named_mutex.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+
+class windows_named_recursive_mutex
+ //Windows mutexes based on CreateMutex are already recursive...
+ : public windows_named_mutex
+{
+ /// @cond
+
+ //Non-copyable
+ windows_named_recursive_mutex();
+ windows_named_recursive_mutex(const windows_named_mutex &);
+ windows_named_recursive_mutex &operator=(const windows_named_mutex &);
+ /// @endcond
+
+ public:
+ windows_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions())
+ : windows_named_mutex(create_only_t(), name, perm)
+ {}
+
+ windows_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions())
+ : windows_named_mutex(open_or_create_t(), name, perm)
+ {}
+
+ windows_named_recursive_mutex(open_only_t, const char *name)
+ : windows_named_mutex(open_only_t(), name)
+ {}
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_WINDOWS_RECURSIVE_NAMED_MUTEX_HPP
Added: trunk/boost/interprocess/sync/windows/named_semaphore.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/named_semaphore.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,175 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP
+#define BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/sync/windows/named_sync.hpp>
+#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+
+
+class windows_named_semaphore
+{
+ /// @cond
+
+ //Non-copyable
+ windows_named_semaphore();
+ windows_named_semaphore(const windows_named_semaphore &);
+ windows_named_semaphore &operator=(const windows_named_semaphore &);
+ /// @endcond
+
+ public:
+ windows_named_semaphore(create_only_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
+
+ windows_named_semaphore(open_or_create_t, const char *name, unsigned int initialCount, const permissions &perm = permissions());
+
+ windows_named_semaphore(open_only_t, const char *name);
+
+ ~windows_named_semaphore();
+
+ void post();
+ void wait();
+ bool try_wait();
+ bool timed_wait(const boost::posix_time::ptime &abs_time);
+
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ friend class interprocess_tester;
+ void dont_close_on_destruction();
+ winapi_semaphore_wrapper m_sem_wrapper;
+ windows_named_sync m_named_sync;
+
+ class named_sem_callbacks : public windows_named_sync_interface
+ {
+ public:
+ typedef __int64 sem_count_t;
+ named_sem_callbacks(winapi_semaphore_wrapper &sem_wrapper, sem_count_t sem_cnt)
+ : m_sem_wrapper(sem_wrapper), m_sem_count(sem_cnt)
+ {}
+
+ virtual std::size_t get_data_size() const
+ { return sizeof(sem_count_t); }
+
+ virtual const void *buffer_with_final_data_to_file()
+ { return &m_sem_count; }
+
+ virtual const void *buffer_with_init_data_to_file()
+ { return &m_sem_count; }
+
+ virtual void *buffer_to_store_init_data_from_file()
+ { return &m_sem_count; }
+
+ virtual bool open(create_enum_t, const char *id_name)
+ {
+ std::string aux_str = "Global\\bipc.sem.";
+ aux_str += id_name;
+ //
+ 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);
+ }
+
+ virtual void close()
+ {
+ m_sem_wrapper.close();
+ }
+
+ virtual ~named_sem_callbacks()
+ {}
+
+ private:
+ sem_count_t m_sem_count;
+ winapi_semaphore_wrapper& m_sem_wrapper;
+ };
+
+ /// @endcond
+};
+
+inline windows_named_semaphore::~windows_named_semaphore()
+{
+ named_sem_callbacks callbacks(m_sem_wrapper, m_sem_wrapper.value());
+ m_named_sync.close(callbacks);
+}
+
+inline void windows_named_semaphore::dont_close_on_destruction()
+{}
+
+inline windows_named_semaphore::windows_named_semaphore
+ (create_only_t, const char *name, unsigned int initial_count, const permissions &perm)
+ : m_sem_wrapper()
+{
+ named_sem_callbacks callbacks(m_sem_wrapper, initial_count);
+ m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
+}
+
+inline windows_named_semaphore::windows_named_semaphore
+ (open_or_create_t, const char *name, unsigned int initial_count, const permissions &perm)
+ : m_sem_wrapper()
+{
+ named_sem_callbacks callbacks(m_sem_wrapper, initial_count);
+ m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
+}
+
+inline windows_named_semaphore::windows_named_semaphore(open_only_t, const char *name)
+ : m_sem_wrapper()
+{
+ named_sem_callbacks callbacks(m_sem_wrapper, 0);
+ m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
+}
+
+inline void windows_named_semaphore::post()
+{
+ m_sem_wrapper.post();
+}
+
+inline void windows_named_semaphore::wait()
+{
+ m_sem_wrapper.wait();
+}
+
+inline bool windows_named_semaphore::try_wait()
+{
+ return m_sem_wrapper.try_wait();
+}
+
+inline bool windows_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
+{
+ return m_sem_wrapper.timed_wait(abs_time);
+}
+
+inline bool windows_named_semaphore::remove(const char *name)
+{
+ return windows_named_sync::remove(name);
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SEMAPHORE_HPP
Added: trunk/boost/interprocess/sync/windows/named_sync.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/named_sync.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,215 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP
+#define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <string>
+#include <cassert>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class windows_named_sync_interface
+{
+ public:
+ virtual std::size_t get_data_size() const = 0;
+ virtual const void *buffer_with_final_data_to_file() = 0;
+ virtual const void *buffer_with_init_data_to_file() = 0;
+ virtual void *buffer_to_store_init_data_from_file() = 0;
+ virtual bool open(create_enum_t creation_type, const char *id_name) = 0;
+ virtual void close() = 0;
+ virtual ~windows_named_sync_interface() = 0;
+};
+
+inline windows_named_sync_interface::~windows_named_sync_interface()
+{}
+
+class windows_named_sync
+{
+ /// @cond
+
+ //Non-copyable
+ windows_named_sync(const windows_named_sync &);
+ windows_named_sync &operator=(const windows_named_sync &);
+ /// @endcond
+
+ public:
+ windows_named_sync();
+ void open_or_create(create_enum_t creation_type, const char *name, const permissions &perm, windows_named_sync_interface &sync_interface);
+ void close(windows_named_sync_interface &sync_interface);
+
+ static bool remove(const char *name);
+
+ /// @cond
+ private:
+ void *m_file_hnd;
+
+ /// @endcond
+};
+
+inline windows_named_sync::windows_named_sync()
+ : m_file_hnd(winapi::invalid_handle_value)
+{}
+
+inline void windows_named_sync::close(windows_named_sync_interface &sync_interface)
+{
+ const std::size_t buflen = sync_interface.get_data_size();
+ const std::size_t sizeof_file_info = sizeof(sync_id::internal_type) + buflen;
+ winapi::interprocess_overlapped overlapped;
+ if(winapi::lock_file_ex
+ (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){
+ if(winapi::set_file_pointer_ex(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){
+ const void *buf = sync_interface.buffer_with_final_data_to_file();
+
+ unsigned long written_or_read = 0;
+ if(winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0)){
+ //...
+ }
+ }
+ }
+ sync_interface.close();
+ if(m_file_hnd != winapi::invalid_handle_value){
+ winapi::close_handle(m_file_hnd);
+ m_file_hnd = winapi::invalid_handle_value;
+ }
+}
+
+inline void windows_named_sync::open_or_create
+ ( create_enum_t creation_type
+ , const char *name
+ , const permissions &perm
+ , 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
+ {
+ create_tmp_and_clean_old_and_get_filename(name, aux_str);
+ //Create a file with required permissions.
+ m_file_hnd = winapi::create_file
+ ( aux_str.c_str()
+ , winapi::generic_read | winapi::generic_write
+ , creation_type == DoOpen ? winapi::open_existing :
+ (creation_type == DoCreate ? winapi::create_new : winapi::open_always)
+ , 0
+ , (winapi::interprocess_security_attributes*)perm.get_permissions());
+
+ //Obtain OS error in case something has failed
+ error_info err;
+ bool success = false;
+ 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;
+ winapi::interprocess_overlapped overlapped;
+ if(winapi::lock_file_ex
+ (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){
+ __int64 filesize = 0;
+ //Obtain the unique id to open the native semaphore.
+ //If file size was created
+ if(winapi::get_file_size(m_file_hnd, filesize)){
+ unsigned long written_or_read = 0;
+ 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;
+ 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) &&
+ written_or_read == sizeof(unique_id_val) &&
+ winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) &&
+ written_or_read == buflen ){
+ success = true;
+ }
+ winapi::get_file_size(m_file_hnd, filesize);
+ assert(filesize == sizeof_file_info);
+ }
+ else{
+ void *buf = sync_interface.buffer_to_store_init_data_from_file();
+ if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) &&
+ written_or_read == sizeof(unique_id_val) &&
+ winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0) &&
+ written_or_read == buflen ){
+ success = true;
+ }
+ }
+ if(success){
+ //Now create a global semaphore name based on the unique id
+ char unique_id_name[sizeof(unique_id_val)*2+1];
+ std::size_t name_suffix_length = sizeof(unique_id_name);
+ bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length);
+ success = sync_interface.open(creation_type, unique_id_name);
+ }
+ }
+
+ //Obtain OS error in case something has failed
+ err = system_error_code();
+
+ //If this fails we have no possible rollback so don't check the return
+ if(!winapi::unlock_file_ex(m_file_hnd, 0, sizeof_file_info, 0, &overlapped)){
+ err = system_error_code();
+ }
+ }
+ else{
+ //Obtain OS error in case something has failed
+ err = system_error_code();
+ }
+ }
+ else{
+ err = system_error_code();
+ }
+
+ if(!success){
+ if(m_file_hnd != winapi::invalid_handle_value){
+ winapi::close_handle(m_file_hnd);
+ m_file_hnd = winapi::invalid_handle_value;
+ }
+ //Throw as something went wrong
+ throw interprocess_exception(err);
+ }
+ }
+}
+
+inline bool windows_named_sync::remove(const char *name)
+{
+ try{
+ //Make sure a temporary path is created for shared memory
+ std::string semfile;
+ ipcdetail::tmp_filename(name, semfile);
+ return winapi::unlink_file(semfile.c_str());
+ }
+ catch(...){
+ return false;
+ }
+}
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP
Modified: trunk/boost/interprocess/sync/windows/semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/windows/semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/windows/semaphore.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -19,8 +19,9 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
-#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
#include <boost/interprocess/sync/windows/sync_utils.hpp>
+#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -50,7 +51,7 @@
: id_()
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//Force smeaphore creation with the initial count
bool open_or_created;
handles.obtain_semaphore(this->id_, initialCount, &open_or_created);
@@ -63,69 +64,43 @@
inline windows_semaphore::~windows_semaphore()
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
handles.destroy_handle(this->id_);
}
inline void windows_semaphore::wait(void)
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//This can throw
- void *hnd = handles.obtain_semaphore(this->id_, 0);
- unsigned long ret = winapi::wait_for_single_object(hnd, winapi::infinite_time);
- if(ret == winapi::wait_failed){
- error_info err(winapi::get_last_error());
- throw interprocess_exception(err);
- }
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
+ sem.wait();
}
inline bool windows_semaphore::try_wait(void)
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//This can throw
- void *hnd = handles.obtain_semaphore(this->id_, 0);
- unsigned long ret = winapi::wait_for_single_object(hnd, 0);
- if(ret == winapi::wait_failed){
- error_info err(winapi::get_last_error());
- throw interprocess_exception(err);
- }
- return ret != winapi::wait_timeout;
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
+ return sem.try_wait();
}
inline bool windows_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
{
- if(abs_time == boost::posix_time::pos_infin){
- this->wait();
- return true;
- }
- boost::posix_time::ptime now
- = boost::posix_time::microsec_clock::universal_time();
-
- unsigned long ms = (unsigned long)(abs_time-now).total_milliseconds();
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
+ windows_intermodule_singleton<sync_handles>::get();
//This can throw
- void *hnd = handles.obtain_semaphore(this->id_, 0);
- unsigned long ret = winapi::wait_for_single_object(hnd, ms);
- if(ret == winapi::wait_failed){
- error_info err(winapi::get_last_error());
- throw interprocess_exception(err);
- }
- return ret != winapi::wait_timeout;
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
+ return sem.timed_wait(abs_time);
}
inline void windows_semaphore::post(long release_count)
{
sync_handles &handles =
- intermodule_singleton<sync_handles>::get();
- //This can throw
- void *hnd = handles.obtain_semaphore(this->id_, 0);
- long prev_count;
- int ret = winapi::release_semaphore(hnd, release_count, &prev_count);
- (void)ret;
- assert(ret);
+ windows_intermodule_singleton<sync_handles>::get();
+ winapi_semaphore_functions sem(handles.obtain_semaphore(this->id_, 0));
+ sem.post(release_count);
}
} //namespace ipcdetail {
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-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -21,6 +21,8 @@
#include <boost/interprocess/sync/spin/mutex.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
+#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 <cstddef>
@@ -32,6 +34,7 @@
{
const std::size_t need_mem = mem_length*2+1;
if(out_length < need_mem){
+ out_length = need_mem;
return false;
}
@@ -51,10 +54,14 @@
struct sync_id
{
+ typedef __int64 internal_type;
+ internal_type rand;
+
sync_id()
{ winapi::query_performance_counter(&rand); }
- __int64 rand;
+ explicit sync_id(internal_type val)
+ { rand = val; }
friend std::size_t hash_value(const sync_id &m)
{ return boost::hash_value(m.rand); }
@@ -62,16 +69,7 @@
friend bool operator==(const sync_id &l, const sync_id &r)
{ return l.rand == r.rand; }
};
-/*
-#define BOOST_NO_LONG_LONG ss
-
-#if defined(BOOST_NO_LONG_LONG)
-#error "defined(BOOST_NO_LONG_LONG)"
-#else
-#error "NOT defined(BOOST_NO_LONG_LONG)"
-#endif
-*/
class sync_handles
{
public:
@@ -108,20 +106,24 @@
{
NameBuf name;
fill_name(name, id);
- void *hnd_val = winapi::open_or_create_semaphore
- (name, (long)initial_count, (long)(((unsigned long)(-1))>>1), unrestricted_security.get_attributes());
- erase_and_throw_if_error(hnd_val, id);
- return hnd_val;
+ 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);
+ return sem_wrapper.release();
}
void* open_or_create_mutex(const sync_id &id)
{
NameBuf name;
fill_name(name, id);
- void *hnd_val = winapi::open_or_create_mutex
- (name, false, unrestricted_security.get_attributes());
- erase_and_throw_if_error(hnd_val, id);
- return hnd_val;
+ permissions unrestricted_security;
+ 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);
+ return mtx_wrapper.release();
}
public:
@@ -158,7 +160,6 @@
}
private:
- winapi::interprocess_all_access_security unrestricted_security;
spin_mutex mtx_;
map_type map_;
};
Added: trunk/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,163 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <limits>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class winapi_mutex_functions
+{
+ /// @cond
+
+ //Non-copyable
+ winapi_mutex_functions(const winapi_mutex_functions &);
+ winapi_mutex_functions &operator=(const winapi_mutex_functions &);
+ /// @endcond
+
+ public:
+ winapi_mutex_functions(void *mtx_hnd)
+ : m_mtx_hnd(mtx_hnd)
+ {}
+
+ void unlock()
+ {
+ winapi::release_mutex(m_mtx_hnd);
+ }
+
+ void lock()
+ {
+ if(winapi::wait_for_single_object(m_mtx_hnd, winapi::infinite_time) != winapi::wait_object_0){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ }
+
+ bool try_lock()
+ {
+ unsigned long ret = winapi::wait_for_single_object(m_mtx_hnd, 0);
+ if(ret == winapi::wait_object_0){
+ return true;
+ }
+ else if(ret == winapi::wait_timeout){
+ return false;
+ }
+ else{
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ }
+
+ bool timed_lock(const boost::posix_time::ptime &abs_time)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+
+ unsigned long ret = winapi::wait_for_single_object
+ (m_mtx_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds());
+ if(ret == winapi::wait_object_0){
+ return true;
+ }
+ else if(ret == winapi::wait_timeout){
+ return false;
+ }
+ else{
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ }
+
+ /// @cond
+ protected:
+ void *m_mtx_hnd;
+ /// @endcond
+};
+
+//Swappable mutex wrapper
+class winapi_mutex_wrapper
+ : public winapi_mutex_functions
+{
+ /// @cond
+
+ //Non-copyable
+ winapi_mutex_wrapper(const winapi_mutex_wrapper &);
+ winapi_mutex_wrapper &operator=(const winapi_mutex_wrapper &);
+ /// @endcond
+
+ public:
+ winapi_mutex_wrapper(void *mtx_hnd = winapi::invalid_handle_value)
+ : winapi_mutex_functions(mtx_hnd)
+ {}
+
+ ~winapi_mutex_wrapper()
+ { this->close(); }
+
+ void *release()
+ {
+ void *hnd = m_mtx_hnd;
+ m_mtx_hnd = winapi::invalid_handle_value;
+ return hnd;
+ }
+
+ void *handle() const
+ { return m_mtx_hnd; }
+
+ bool open_or_create(const char *name, const permissions &perm)
+ {
+ if(m_mtx_hnd == winapi::invalid_handle_value){
+ m_mtx_hnd = winapi::open_or_create_mutex
+ ( name
+ , false
+ , (winapi::interprocess_security_attributes*)perm.get_permissions()
+ );
+ return m_mtx_hnd != winapi::invalid_handle_value;
+ }
+ else{
+ return false;
+ }
+ }
+
+ void close()
+ {
+ if(m_mtx_hnd != winapi::invalid_handle_value){
+ winapi::close_handle(m_mtx_hnd);
+ m_mtx_hnd = winapi::invalid_handle_value;
+ }
+ }
+
+ void swap(winapi_mutex_wrapper &other)
+ { void *tmp = m_mtx_hnd; m_mtx_hnd = other.m_mtx_hnd; other.m_mtx_hnd = tmp; }
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
Added: trunk/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp 2012-04-11 02:27:48 EDT (Wed, 11 Apr 2012)
@@ -0,0 +1,176 @@
+ //////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP
+#define BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/win32_api.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <limits>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+class winapi_semaphore_functions
+{
+ /// @cond
+
+ //Non-copyable
+ winapi_semaphore_functions(const winapi_semaphore_functions &);
+ winapi_semaphore_functions &operator=(const winapi_semaphore_functions &);
+ /// @endcond
+
+ public:
+ winapi_semaphore_functions(void *hnd)
+ : m_sem_hnd(hnd)
+ {}
+
+ void post(long count = 1)
+ {
+ long prev_count;
+ winapi::release_semaphore(m_sem_hnd, count, &prev_count);
+ }
+
+ void wait()
+ {
+ if(winapi::wait_for_single_object(m_sem_hnd, winapi::infinite_time) != winapi::wait_object_0){
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ }
+
+ bool try_wait()
+ {
+ unsigned long ret = winapi::wait_for_single_object(m_sem_hnd, 0);
+ if(ret == winapi::wait_object_0){
+ return true;
+ }
+ else if(ret == winapi::wait_timeout){
+ return false;
+ }
+ else{
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ }
+
+ bool timed_wait(const boost::posix_time::ptime &abs_time)
+ {
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+
+ unsigned long ret = winapi::wait_for_single_object
+ (m_sem_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds());
+ if(ret == winapi::wait_object_0){
+ return true;
+ }
+ else if(ret == winapi::wait_timeout){
+ return false;
+ }
+ else{
+ error_info err = system_error_code();
+ throw interprocess_exception(err);
+ }
+ }
+
+ unsigned int 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){
+ return 0;
+ }
+ return info.count;
+ }
+
+ /// @cond
+ protected:
+ void *m_sem_hnd;
+ /// @endcond
+};
+
+
+//Swappable semaphore wrapper
+class winapi_semaphore_wrapper
+ : public winapi_semaphore_functions
+{
+ winapi_semaphore_wrapper(const winapi_semaphore_wrapper &);
+ winapi_semaphore_wrapper &operator=(const winapi_semaphore_wrapper &);
+
+ public:
+
+ winapi_semaphore_wrapper(void *hnd = winapi::invalid_handle_value)
+ : winapi_semaphore_functions(hnd)
+ {}
+
+ ~winapi_semaphore_wrapper()
+ { this->close(); }
+
+ void *release()
+ {
+ void *hnd = m_sem_hnd;
+ m_sem_hnd = winapi::invalid_handle_value;
+ return hnd;
+ }
+
+ void *handle() const
+ { return m_sem_hnd; }
+
+ bool open_or_create(const char *name, long sem_count, const permissions &perm)
+ {
+ if(m_sem_hnd == winapi::invalid_handle_value){
+ m_sem_hnd = winapi::open_or_create_semaphore
+ ( name
+ , sem_count
+ , (std::numeric_limits<long>::max)()
+ , (winapi::interprocess_security_attributes*)perm.get_permissions()
+ );
+ return m_sem_hnd != winapi::invalid_handle_value;
+ }
+ else{
+ return false;
+ }
+ }
+
+ void close()
+ {
+ if(m_sem_hnd != winapi::invalid_handle_value){
+ winapi::close_handle(m_sem_hnd);
+ m_sem_hnd = winapi::invalid_handle_value;
+ }
+ }
+
+ void swap(winapi_semaphore_wrapper &other)
+ { void *tmp = m_sem_hnd; m_sem_hnd = other.m_sem_hnd; other.m_sem_hnd = tmp; }
+};
+
+} //namespace ipcdetail {
+} //namespace interprocess {
+} //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP
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