update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -26,6 +26,7 @@
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/type_traits.hpp>

View File

@@ -220,8 +220,7 @@ class cache_impl
BOOST_CATCH(...){
this->cached_deallocation(chain);
BOOST_RETHROW
}
BOOST_CATCH_END
} BOOST_CATCH_END
}
void cached_deallocation(void *ptr)

View File

@@ -26,6 +26,7 @@
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/type_traits.hpp>

View File

@@ -26,6 +26,7 @@
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
#include <boost/interprocess/containers/version_type.hpp>
@@ -97,7 +98,7 @@ class private_adaptive_pool_base
typedef typename ipcdetail::add_reference
<const value_type>::type const_reference;
typedef typename segment_manager::size_type size_type;
typedef typename segment_manager::size_type difference_type;
typedef typename segment_manager::difference_type difference_type;
typedef boost::interprocess::version_type
<private_adaptive_pool_base, Version> version;
typedef boost::container::dtl::transform_multiallocation_chain

View File

@@ -26,6 +26,7 @@
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/interprocess/allocators/detail/node_pool.hpp>
#include <boost/interprocess/containers/version_type.hpp>

View File

@@ -111,7 +111,7 @@ anonymous_shared_memory(std::size_t size, void *address = 0)
}
#else
{
windows_shared_memory anonymous_mapping(create_only, 0, read_write, size);
windows_shared_memory anonymous_mapping(create_only, (char*)0, read_write, size);
return mapped_region(anonymous_mapping, read_write, 0, size, address);
}

View File

@@ -26,7 +26,7 @@ namespace boost {
namespace interprocess {
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef int allocation_type;
using boost::container::allocation_type;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
static const allocation_type allocate_new = boost::container::allocate_new;
static const allocation_type expand_fwd = boost::container::expand_fwd;

View File

@@ -27,6 +27,14 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/cstdint.hpp>
#if !defined(_AIX)
#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL(label) label ":\n\t"
#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " " label "\n\t"
#else
#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL(label)
#define BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " $" offset "\n\t"
#endif
namespace boost{
namespace interprocess{
namespace ipcdetail{
@@ -64,7 +72,12 @@ inline boost::uint32_t atomic_cas32
#if defined( _MSC_VER )
extern "C" void _ReadWriteBarrier(void);
#pragma intrinsic(_ReadWriteBarrier)
#define BOOST_INTERPROCESS_READ_WRITE_BARRIER _ReadWriteBarrier()
#define BOOST_INTERPROCESS_READ_WRITE_BARRIER \
BOOST_INTERPROCESS_DISABLE_DEPRECATED_WARNING \
_ReadWriteBarrier() \
BOOST_INTERPROCESS_RESTORE_WARNING
#elif defined(__GNUC__)
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
#define BOOST_INTERPROCESS_READ_WRITE_BARRIER __sync_synchronize()
@@ -81,13 +94,13 @@ namespace ipcdetail{
//! "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 winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; }
{ return (boost::uint32_t)winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; }
//! 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 winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; }
{ return (boost::uint32_t)winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; }
//! Atomically read an boost::uint32_t from memory
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
@@ -101,7 +114,7 @@ inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
//! "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)
{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val); }
{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), (long)val); }
//! Compare an boost::uint32_t's value with "cmp".
//! If they are the same swap the value with "with"
@@ -111,7 +124,7 @@ inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
//! 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 winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp); }
{ return (boost::uint32_t)winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), (long)with, (long)cmp); }
} //namespace ipcdetail{
} //namespace interprocess{
@@ -153,7 +166,7 @@ inline boost::uint32_t atomic_add32
// int r = *pw;
// *mem += val;
// return r;
int r;
boost::uint32_t r;
asm volatile
(
@@ -218,14 +231,17 @@ inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32
{
boost::uint32_t prev, temp;
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");
asm volatile
(
BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,0,%2\n\t"
"add %1,%0,%3\n\t"
"stwcx. %1,0,%2\n\t"
BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&r" (prev), "=&r" (temp)
: "b" (mem), "r" (val)
: "cc", "memory"
);
return prev;
}
@@ -240,16 +256,19 @@ inline boost::uint32_t atomic_cas32
{
boost::uint32_t prev;
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" (with), "r" (cmp)
: "cc", "memory");
asm volatile
(
BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,0,%1\n\t"
"cmpw %0,%3\n\t"
BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "2f", "+12")
"stwcx. %2,0,%1\n\t"
BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("2")
: "=&r"(prev)
: "b" (mem), "r" (with), "r" (cmp)
: "cc", "memory"
);
return prev;
}

View File

@@ -0,0 +1,127 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2020-2021. 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_CHAR_WCHAR_HOLDER_HPP
#define BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <cwchar>
#include <cstring>
namespace boost {
namespace interprocess {
class char_wchar_holder
{
public:
char_wchar_holder()
: m_str(), m_is_wide()
{
m_str.n = 0;
}
char_wchar_holder(const char *nstr)
: m_str(), m_is_wide()
{
m_str.n = new char [std::strlen(nstr)+1];
std::strcpy(m_str.n, nstr);
}
char_wchar_holder(const wchar_t *wstr)
: m_str(), m_is_wide(true)
{
m_str.w = new wchar_t [std::wcslen(wstr)+1];
std::wcscpy(m_str.w, wstr);
}
char_wchar_holder& operator=(const char *nstr)
{
char *tmp = new char [std::strlen(nstr)+1];
this->delete_mem();
m_str.n = tmp;
std::strcpy(m_str.n, nstr);
return *this;
}
char_wchar_holder& operator=(const wchar_t *wstr)
{
wchar_t *tmp = new wchar_t [std::wcslen(wstr)+1];
this->delete_mem();
m_str.w = tmp;
std::wcscpy(m_str.w, wstr);
return *this;
}
char_wchar_holder& operator=(const char_wchar_holder &other)
{
if (other.m_is_wide)
*this = other.getn();
else
*this = other.getw();
return *this;
}
~char_wchar_holder()
{
this->delete_mem();
}
wchar_t *getw() const
{ return m_is_wide ? m_str.w : 0; }
char *getn() const
{ return !m_is_wide ? m_str.n : 0; }
void swap(char_wchar_holder& other)
{
char_wchar tmp;
std::memcpy(&tmp, &m_str, sizeof(char_wchar));
std::memcpy(&m_str, &other.m_str, sizeof(char_wchar));
std::memcpy(&other.m_str, &tmp, sizeof(char_wchar));
//
bool b_tmp(m_is_wide);
m_is_wide = other.m_is_wide;
other.m_is_wide = b_tmp;
}
private:
void delete_mem()
{
if(m_is_wide)
delete [] m_str.w;
else
delete [] m_str.n;
}
union char_wchar
{
char *n;
wchar_t *w;
} m_str;
bool m_is_wide;
};
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP

View File

@@ -15,4 +15,9 @@
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wshadow"
# pragma GCC diagnostic ignored "-Wsign-conversion"
# pragma GCC diagnostic ignored "-Wconversion"
# if (BOOST_GCC >= 100000)
# pragma GCC diagnostic ignored "-Warith-conversion"
# endif
#endif

View File

@@ -58,6 +58,34 @@ class file_wrapper
file_wrapper(open_only_t, const char *name, mode_t mode)
{ this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a file object with name "name" and mode "mode", with the access mode "mode"
//!If the file previously exists, throws an error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
file_wrapper(create_only_t, const wchar_t *name, mode_t mode, const permissions &perm = permissions())
{ this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); }
//!Tries to create a file with name "name" and mode "mode", with the
//!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
//!Otherwise throws an error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
file_wrapper(open_or_create_t, const wchar_t *name, mode_t mode, const permissions &perm = permissions())
{ this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); }
//!Tries to open a file with name "name", with the access mode "mode".
//!If the file does not previously exist, it throws an error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
file_wrapper(open_only_t, const wchar_t *name, mode_t mode)
{ this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Moves the ownership of "moved"'s file to *this.
//!After the call, "moved" does not represent any file.
//!Does not throw
@@ -110,24 +138,21 @@ class file_wrapper
//!Closes a previously opened file mapping. Never throws.
void priv_close();
//!Closes a previously opened file mapping. Never throws.
bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm);
template <class CharT>
bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm);
file_handle_t m_handle;
mode_t m_mode;
std::string m_filename;
};
inline file_wrapper::file_wrapper()
: m_handle(file_handle_t(ipcdetail::invalid_file()))
, m_mode(read_only), m_filename()
, m_mode(read_only)
{}
inline file_wrapper::~file_wrapper()
{ this->priv_close(); }
inline const char *file_wrapper::get_name() const
{ return m_filename.c_str(); }
inline bool file_wrapper::get_size(offset_t &size) const
{ return get_file_size((file_handle_t)m_handle, size); }
@@ -135,7 +160,6 @@ inline void file_wrapper::swap(file_wrapper &other)
{
(simple_swap)(m_handle, other.m_handle);
(simple_swap)(m_mode, other.m_mode);
m_filename.swap(other.m_filename);
}
inline mapping_handle_t file_wrapper::get_mapping_handle() const
@@ -144,14 +168,10 @@ inline mapping_handle_t file_wrapper::get_mapping_handle() const
inline mode_t file_wrapper::get_mode() const
{ return m_mode; }
template <class CharT>
inline bool file_wrapper::priv_open_or_create
(ipcdetail::create_enum_t type,
const char *filename,
mode_t mode,
const permissions &perm = permissions())
( ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm)
{
m_filename = filename;
if(mode != read_only && mode != read_write){
error_info err(mode_error);
throw interprocess_exception(err);
@@ -190,7 +210,7 @@ inline bool file_wrapper::remove(const char *filename)
inline void file_wrapper::truncate(offset_t length)
{
if(!truncate_file(m_handle, length)){
if(!truncate_file(m_handle, (std::size_t)length)){
error_info err(system_error_code());
throw interprocess_exception(err);
}

View File

@@ -54,14 +54,14 @@ struct placement_destroy : public in_place_interface
: in_place_interface(::boost::container::dtl::alignment_of<T>::value, sizeof(T), typeid(T).name())
{}
virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed)
virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) BOOST_OVERRIDE
{
T* memory = static_cast<T*>(mem);
for(destroyed = 0; destroyed < num; ++destroyed)
(memory++)->~T();
}
virtual void construct_n(void *, std::size_t, std::size_t &) {}
virtual void construct_n(void *, std::size_t, std::size_t &) BOOST_OVERRIDE {}
private:
void destroy(void *mem)

View File

@@ -33,7 +33,7 @@ namespace interprocess{
namespace ipcdetail{
//Now this class is a singleton, initializing the singleton in
//the first get() function call if LazyInit is false. If true
//the first get() function call if LazyInit is true. If false
//then the singleton will be initialized when loading the module.
template<typename C, bool LazyInit = true, bool Phoenix = false>
class intermodule_singleton

View File

@@ -34,6 +34,7 @@
#include <cstdlib>
#include <cstring>
#include <string>
#include <typeinfo>
#include <sstream>
namespace boost{
@@ -120,7 +121,7 @@ class intermodule_singleton_common
}
}
if(previous_module_singleton_initialized == Uninitialized){
try{
BOOST_TRY{
//Now initialize the global map, this function must solve concurrency
//issues between threads of several modules
initialize_global_map_handle();
@@ -142,11 +143,11 @@ class intermodule_singleton_common
//before this one. Now marked as initialized
atomic_write32(&this_module_singleton_initialized, Initialized);
}
catch(...){
BOOST_CATCH(...){
//Mark singleton failed to initialize
atomic_write32(&this_module_singleton_initialized, Broken);
throw;
}
BOOST_RETHROW
} BOOST_CATCH_END
}
//If previous state was initializing, this means that another winner thread is
//trying to initialize the singleton. Just wait until completes its work.
@@ -231,7 +232,7 @@ class intermodule_singleton_common
}
else{ //(tmp == Uninitialized)
//If not initialized try it again?
try{
BOOST_TRY{
//Remove old global map from the system
intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
//in-place construction of the global map class
@@ -254,10 +255,10 @@ class intermodule_singleton_common
break;
}
}
catch(...){
BOOST_CATCH(...){
//
throw;
}
BOOST_RETHROW
} BOOST_CATCH_END
}
}
}
@@ -405,17 +406,17 @@ class intermodule_singleton_impl
<ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
if(!rcount){
C *p = new C;
try{
BOOST_TRY{
ref_count_ptr val(p, 0u);
rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
<ThreadSafeGlobalMap>::insert(m_map, typeid(C).name(), val);
}
catch(...){
BOOST_CATCH(...){
intermodule_singleton_helpers::thread_safe_global_map_dependant
<ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
delete p;
throw;
}
BOOST_RETHROW
} BOOST_CATCH_END
}
//if(Phoenix){
std::atexit(&atexit_work);

File diff suppressed because it is too large Load Diff

View File

@@ -91,19 +91,19 @@ class basic_managed_global_memory
public: //functions
basic_managed_global_memory (open_or_create_t open_or_create,
basic_managed_global_memory (open_or_create_t,
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,
, base2_t(open_or_create_t(), 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,
basic_managed_global_memory (open_only_t , const char* name,
const void *addr = 0)
: base_t()
, base2_t(open_only, name, read_write, addr,
, base2_t(open_only_t(), name, read_write, addr,
create_open_func_t(get_this_pointer(),
DoOpen))
{}

View File

@@ -110,48 +110,48 @@ class basic_managed_memory_impl
typedef basic_managed_memory_impl
<CharType, MemoryAlgorithm, IndexType, Offset> self_t;
protected:
template<class ManagedMemory>
static bool grow(const char *filename, size_type extra_bytes)
template<class ManagedMemory, class CharT>
static bool grow(const CharT *filename, size_type extra_bytes)
{
typedef typename ManagedMemory::device_type device_type;
//Increase file size
try{
BOOST_TRY{
offset_t old_size;
{
device_type f(open_or_create, filename, read_write);
if(!f.get_size(old_size))
return false;
f.truncate(old_size + extra_bytes);
f.truncate(old_size + static_cast<offset_t>(extra_bytes));
}
ManagedMemory managed_memory(open_only, filename);
//Grow always works
managed_memory.self_t::grow(extra_bytes);
}
catch(...){
BOOST_CATCH(...){
return false;
}
} BOOST_CATCH_END
return true;
}
template<class ManagedMemory>
static bool shrink_to_fit(const char *filename)
template<class ManagedMemory, class CharT>
static bool shrink_to_fit(const CharT *filename)
{
typedef typename ManagedMemory::device_type device_type;
size_type new_size;
try{
BOOST_TRY{
ManagedMemory managed_memory(open_only, filename);
managed_memory.get_size();
managed_memory.self_t::shrink_to_fit();
new_size = managed_memory.get_size();
}
catch(...){
BOOST_CATCH(...){
return false;
}
} BOOST_CATCH_END
//Decrease file size
{
device_type f(open_or_create, filename, read_write);
f.truncate(new_size);
f.truncate(static_cast<offset_t>(new_size));
}
return true;
}
@@ -177,12 +177,12 @@ class basic_managed_memory_impl
//throw if constructor allocates memory. So we must catch it.
BOOST_TRY{
//Let's construct the allocator in memory
BOOST_ASSERT((0 == (std::size_t)addr % boost::move_detail::alignment_of<segment_manager>::value));
mp_header = ::new(addr, boost_container_new_t()) segment_manager(size);
}
BOOST_CATCH(...){
return false;
}
BOOST_CATCH_END
} BOOST_CATCH_END
return true;
}

View File

@@ -1,429 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-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_MANAGED_MULTI_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/managed_memory_impl.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/interprocess/detail/multi_segment_services.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/containers/list.hpp>//list
#include <boost/interprocess/mapped_region.hpp> //mapped_region
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> //managed_open_or_create_impl
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/streams/vectorstream.hpp>
#include <boost/intrusive/detail/minimal_pair_header.hpp>
#include <string> //string
#include <new> //bad_alloc
#include <ostream>//std::ends
#include <boost/assert.hpp>
//These includes needed to fulfill default template parameters of
//predeclarations in interprocess_fwd.hpp
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
//!\file
//!Describes a named shared memory object allocation user class.
namespace boost {
namespace interprocess {
//TODO: We must somehow obtain the permissions of the first segment
//to apply them to subsequent segments
//-Use GetSecurityInfo?
//-Change everything to use only a shared memory object expanded via truncate()?
//!A basic shared memory named object creation class. Initializes the
//!shared memory segment. Inherits all basic functionality from
//!basic_managed_memory_impl<CharType, MemoryAlgorithm, IndexType>
template
<
class CharType,
class MemoryAlgorithm,
template<class IndexConfig> class IndexType
>
class basic_managed_multi_shared_memory
: public ipcdetail::basic_managed_memory_impl
<CharType, MemoryAlgorithm, IndexType>
{
typedef basic_managed_multi_shared_memory
<CharType, MemoryAlgorithm, IndexType> self_t;
typedef ipcdetail::basic_managed_memory_impl
<CharType, MemoryAlgorithm, IndexType> base_t;
typedef typename MemoryAlgorithm::void_pointer void_pointer;
typedef typename ipcdetail::
managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment, true, false> managed_impl;
typedef typename void_pointer::segment_group_id segment_group_id;
typedef typename base_t::size_type size_type;
////////////////////////////////////////////////////////////////////////
//
// Some internal helper structs/functors
//
////////////////////////////////////////////////////////////////////////
//!This class defines an operator() that creates a shared memory
//!of the requested size. The rest of the parameters are
//!passed in the constructor. The class a template parameter
//!to be used with create_from_file/create_from_istream functions
//!of basic_named_object classes
// class segment_creator
// {
// public:
// segment_creator(shared_memory &shmem,
// const char *mem_name,
// const void *addr)
// : m_shmem(shmem), m_mem_name(mem_name), m_addr(addr){}
//
// void *operator()(size_type size)
// {
// if(!m_shmem.create(m_mem_name, size, m_addr))
// return 0;
// return m_shmem.get_address();
// }
// private:
// shared_memory &m_shmem;
// const char *m_mem_name;
// const void *m_addr;
// };
class group_services
: public multi_segment_services
{
public:
typedef std::pair<void *, size_type> result_type;
typedef basic_managed_multi_shared_memory frontend_t;
typedef typename
basic_managed_multi_shared_memory::void_pointer void_pointer;
typedef typename void_pointer::segment_group_id segment_group_id;
group_services(frontend_t *const frontend)
: mp_frontend(frontend), m_group(0), m_min_segment_size(0){}
virtual std::pair<void *, size_type> create_new_segment(size_type alloc_size)
{ (void)alloc_size;
/*
//We should allocate an extra byte so that the
//[base_addr + alloc_size] byte belongs to this segment
alloc_size += 1;
//If requested size is less than minimum, update that
alloc_size = (m_min_segment_size > alloc_size) ?
m_min_segment_size : alloc_size;
if(mp_frontend->priv_new_segment(create_open_func::DoCreate,
alloc_size, 0, permissions())){
typename shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin();
return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1);
}*/
return result_type(static_cast<void *>(0), 0);
}
virtual bool update_segments ()
{ return true; }
virtual ~group_services(){}
void set_group(segment_group_id group)
{ m_group = group; }
segment_group_id get_group() const
{ return m_group; }
void set_min_segment_size(size_type min_segment_size)
{ m_min_segment_size = min_segment_size; }
size_type get_min_segment_size() const
{ return m_min_segment_size; }
private:
frontend_t * const mp_frontend;
segment_group_id m_group;
size_type m_min_segment_size;
};
//!Functor to execute atomically when opening or creating a shared memory
//!segment.
struct create_open_func
{
enum type_t { DoCreate, DoOpen, DoOpenOrCreate };
typedef typename
basic_managed_multi_shared_memory::void_pointer void_pointer;
create_open_func(self_t * const frontend,
type_t type, size_type segment_number)
: mp_frontend(frontend), m_type(type), m_segment_number(segment_number){}
bool operator()(void *addr, size_type size, bool created) const
{
if(((m_type == DoOpen) && created) ||
((m_type == DoCreate) && !created))
return false;
segment_group_id group = mp_frontend->m_group_services.get_group();
bool mapped = false;
bool impl_done = false;
//Associate this newly created segment as the
//segment id = 0 of this group
void_pointer::insert_mapping
( group
, static_cast<char*>(addr) - managed_impl::ManagedOpenOrCreateUserOffset
, size + managed_impl::ManagedOpenOrCreateUserOffset);
//Check if this is the master segment
if(!m_segment_number){
//Create or open the Interprocess machinery
if((impl_done = created ?
mp_frontend->create_impl(addr, size) : mp_frontend->open_impl(addr, size))){
return true;
}
}
else{
return true;
}
//This is the cleanup part
//---------------
if(impl_done){
mp_frontend->close_impl();
}
if(mapped){
bool ret = void_pointer::erase_last_mapping(group);
BOOST_ASSERT(ret);(void)ret;
}
return false;
}
static std::size_t get_min_size()
{
const size_type sz = self_t::segment_manager::get_min_size();
if(sz > std::size_t(-1)){
//The minimum size is not representable by std::size_t
BOOST_ASSERT(false);
return std::size_t(-1);
}
else{
return static_cast<std::size_t>(sz);
}
}
self_t * const mp_frontend;
type_t m_type;
size_type m_segment_number;
};
//!Functor to execute atomically when closing a shared memory segment.
struct close_func
{
typedef typename
basic_managed_multi_shared_memory::void_pointer void_pointer;
close_func(self_t * const frontend)
: mp_frontend(frontend){}
void operator()(const mapped_region &region, bool last) const
{
if(last) mp_frontend->destroy_impl();
else mp_frontend->close_impl();
}
self_t * const mp_frontend;
};
//Friend declarations
friend struct basic_managed_multi_shared_memory::create_open_func;
friend struct basic_managed_multi_shared_memory::close_func;
friend class basic_managed_multi_shared_memory::group_services;
typedef list<managed_impl> shmem_list_t;
basic_managed_multi_shared_memory *get_this_pointer()
{ return this; }
public:
basic_managed_multi_shared_memory(create_only_t,
const char *name,
size_type size,
const permissions &perm = permissions())
: m_group_services(get_this_pointer())
{
priv_open_or_create(create_open_func::DoCreate,name, size, perm);
}
basic_managed_multi_shared_memory(open_or_create_t,
const char *name,
size_type size,
const permissions &perm = permissions())
: m_group_services(get_this_pointer())
{
priv_open_or_create(create_open_func::DoOpenOrCreate, name, size, perm);
}
basic_managed_multi_shared_memory(open_only_t, const char *name)
: m_group_services(get_this_pointer())
{
priv_open_or_create(create_open_func::DoOpen, name, 0, permissions());
}
~basic_managed_multi_shared_memory()
{ this->priv_close(); }
private:
bool priv_open_or_create(typename create_open_func::type_t type,
const char *name,
size_type size,
const permissions &perm)
{
if(!m_shmem_list.empty())
return false;
typename void_pointer::segment_group_id group = 0;
BOOST_TRY{
m_root_name = name;
//Insert multi segment services and get a group identifier
group = void_pointer::new_segment_group(&m_group_services);
size = void_pointer::round_size(size);
m_group_services.set_group(group);
m_group_services.set_min_segment_size(size);
if(group){
if(this->priv_new_segment(type, size, 0, perm)){
return true;
}
}
}
BOOST_CATCH(const std::bad_alloc&){
}
BOOST_CATCH_END
if(group){
void_pointer::delete_group(group);
}
return false;
}
bool priv_new_segment(typename create_open_func::type_t type,
size_type size,
const void *addr,
const permissions &perm)
{
BOOST_TRY{
//Get the number of groups of this multi_segment group
size_type segment_id = m_shmem_list.size();
//Format the name of the shared memory: append segment number.
boost::interprocess::basic_ovectorstream<boost::interprocess::string> formatter;
//Pre-reserve string size
size_type str_size = m_root_name.length()+10;
if(formatter.vector().size() < str_size){
//This can throw.
formatter.reserve(str_size);
}
//Format segment's name
formatter << m_root_name
<< static_cast<unsigned int>(segment_id) << std::ends;
//This functor will be executed when constructing
create_open_func func(this, type, segment_id);
const char *name = formatter.vector().c_str();
//This can throw.
managed_impl mshm;
switch(type){
case create_open_func::DoCreate:
{
managed_impl shm(create_only, name, size, read_write, addr, func, perm);
mshm = boost::move(shm);
}
break;
case create_open_func::DoOpen:
{
managed_impl shm(open_only, name,read_write, addr, func);
mshm = boost::move(shm);
}
break;
case create_open_func::DoOpenOrCreate:
{
managed_impl shm(open_or_create, name, size, read_write, addr, func, perm);
mshm = boost::move(shm);
}
break;
default:
return false;
break;
}
//This can throw.
m_shmem_list.push_back(boost::move(mshm));
return true;
}
BOOST_CATCH(const std::bad_alloc&){
}
BOOST_CATCH_END
return false;
}
//!Frees resources. Never throws.
void priv_close()
{
if(!m_shmem_list.empty()){
bool ret;
//Obtain group identifier
segment_group_id group = m_group_services.get_group();
//Erase main segment and its resources
//typename shmem_list_t::iterator itbeg = m_shmem_list.begin(),
// itend = m_shmem_list.end(),
// it = itbeg;
//(*itbeg)->close_with_func(close_func(this));
//Delete group. All mappings are erased too.
ret = void_pointer::delete_group(group);
(void)ret;
BOOST_ASSERT(ret);
m_shmem_list.clear();
}
}
private:
shmem_list_t m_shmem_list;
group_services m_group_services;
std::string m_root_name;
};
typedef basic_managed_multi_shared_memory
< char
, rbtree_best_fit<mutex_family, intersegment_ptr<void> >
, iset_index>
managed_multi_shared_memory;
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP

View File

@@ -33,40 +33,14 @@
#include <boost/interprocess/permissions.hpp>
#include <boost/container/detail/type_traits.hpp> //alignment_of, aligned_storage
#include <boost/interprocess/sync/spin/wait.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
#include <boost/move/move.hpp>
#include <boost/cstdint.hpp>
namespace boost {
namespace interprocess {
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail{ class interprocess_tester; }
template<class DeviceAbstraction>
struct managed_open_or_create_impl_device_id_t
{
typedef const char *type;
};
#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
class xsi_shared_memory_file_wrapper;
class xsi_key;
template<>
struct managed_open_or_create_impl_device_id_t<xsi_shared_memory_file_wrapper>
{
typedef xsi_key type;
};
#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
namespace ipcdetail {
template <bool StoreDevice, class DeviceAbstraction>
class managed_open_or_create_impl_device_holder
{
@@ -98,8 +72,11 @@ class managed_open_or_create_impl
{
//Non-copyable
BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl)
typedef bool_<FileBased> file_like_t;
static const unsigned MaxCreateOrOpenTries = BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_MAX_TRIES;
static const unsigned MaxInitializeTimeSec = BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_TIMEOUT_SEC;
typedef typename managed_open_or_create_impl_device_id_t<DeviceAbstraction>::type device_id_t;
typedef managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> DevHolder;
enum
{
@@ -109,21 +86,21 @@ class managed_open_or_create_impl
CorruptedSegment
};
static const std::size_t RequiredAlignment =
MemAlignment ? MemAlignment
: boost::container::dtl::alignment_of< boost::container::dtl::max_align_t >::value
;
public:
static const std::size_t
ManagedOpenOrCreateUserOffset =
ct_rounded_size
< sizeof(boost::uint32_t)
, MemAlignment ? (MemAlignment) :
(::boost::container::dtl::alignment_of
< ::boost::container::dtl::max_align_t >::value)
>::value;
static const std::size_t ManagedOpenOrCreateUserOffset =
ct_rounded_size<sizeof(boost::uint32_t), RequiredAlignment>::value;
managed_open_or_create_impl()
{}
template <class DeviceId>
managed_open_or_create_impl(create_only_t,
const device_id_t & id,
const DeviceId & id,
std::size_t size,
mode_t mode,
const void *addr,
@@ -139,8 +116,9 @@ class managed_open_or_create_impl
, null_mapped_region_function());
}
template <class DeviceId>
managed_open_or_create_impl(open_only_t,
const device_id_t & id,
const DeviceId & id,
mode_t mode,
const void *addr)
{
@@ -154,9 +132,9 @@ class managed_open_or_create_impl
, null_mapped_region_function());
}
template <class DeviceId>
managed_open_or_create_impl(open_or_create_t,
const device_id_t & id,
const DeviceId & id,
std::size_t size,
mode_t mode,
const void *addr,
@@ -172,9 +150,9 @@ class managed_open_or_create_impl
, null_mapped_region_function());
}
template <class ConstructFunc>
template <class DeviceId, class ConstructFunc>
managed_open_or_create_impl(create_only_t,
const device_id_t & id,
const DeviceId & id,
std::size_t size,
mode_t mode,
const void *addr,
@@ -191,9 +169,9 @@ class managed_open_or_create_impl
, construct_func);
}
template <class ConstructFunc>
template <class DeviceId, class ConstructFunc>
managed_open_or_create_impl(open_only_t,
const device_id_t & id,
const DeviceId & id,
mode_t mode,
const void *addr,
const ConstructFunc &construct_func)
@@ -208,9 +186,9 @@ class managed_open_or_create_impl
, construct_func);
}
template <class ConstructFunc>
template <class DeviceId, class ConstructFunc>
managed_open_or_create_impl(open_or_create_t,
const device_id_t & id,
const DeviceId & id,
std::size_t size,
mode_t mode,
const void *addr,
@@ -263,7 +241,6 @@ class managed_open_or_create_impl
const mapped_region &get_mapped_region() const
{ return m_mapped_region; }
DeviceAbstraction &get_device()
{ return this->DevHolder::get_device(); }
@@ -291,38 +268,203 @@ class managed_open_or_create_impl
{ return size == std::size_t(offset_t(size)); }
//These are templatized to allow explicit instantiations
template<bool dummy>
static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t size, const permissions &perm, false_ file_like)
template<bool dummy, class DeviceId>
static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t size, const permissions &perm, false_ /*file_like*/)
{
(void)file_like;
DeviceAbstraction tmp(create_only, id, read_write, size, perm);
tmp.swap(dev);
}
template<bool dummy>
static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t, const permissions &perm, true_ file_like)
template<bool dummy, class DeviceId>
static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t, const permissions &perm, true_ /*file_like*/)
{
(void)file_like;
DeviceAbstraction tmp(create_only, id, read_write, perm);
tmp.swap(dev);
}
template <class ConstructFunc> inline
template <class DeviceId>
static bool do_create_else_open(DeviceAbstraction &dev, const DeviceId & id, std::size_t size, const permissions &perm)
{
//This loop is very ugly, but brute force is sometimes better
//than diplomacy. In POSIX file-based resources we can' know if we
//effectively created the file or not (there is no ERROR_ALREADY_EXISTS equivalent),
//so we try to create exclusively and fallback to open if already exists, with
//some retries if opening also fails because the file does not exist
//(there is a race, the creator just removed the file after creating it).
//
//We'll put a maximum retry limit just to avoid possible deadlocks, we don't
//want to support pathological use cases.
spin_wait swait;
unsigned tries = 0;
while(1){
BOOST_TRY{
create_device<FileBased>(dev, id, size, perm, file_like_t());
return true;
}
BOOST_CATCH(interprocess_exception &ex){
#ifndef BOOST_NO_EXCEPTIONS
if(ex.get_error_code() != already_exists_error){
BOOST_RETHROW
}
else if (++tries == MaxCreateOrOpenTries) {
//File existing when trying to create, but non-existing when
//trying to open, and tried MaxCreateOrOpenTries times. Something fishy
//is happening here and we can't solve it
throw interprocess_exception(error_info(corrupted_error));
}
else{
BOOST_TRY{
DeviceAbstraction tmp(open_only, id, read_write);
dev.swap(tmp);
return false;
}
BOOST_CATCH(interprocess_exception &e){
if(e.get_error_code() != not_found_error){
BOOST_RETHROW
}
}
BOOST_CATCH(...){
BOOST_RETHROW
} BOOST_CATCH_END
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
BOOST_CATCH(...){
BOOST_RETHROW
} BOOST_CATCH_END
swait.yield();
}
return false;
}
template <class ConstructFunc>
static void do_map_after_create
(DeviceAbstraction &dev, mapped_region &final_region,
std::size_t size, const void *addr, ConstructFunc construct_func)
{
BOOST_TRY{
//If this throws, we are lost
truncate_device<FileBased>(dev, static_cast<offset_t>(size), file_like_t());
//If the following throws, we will truncate the file to 1
mapped_region region(dev, read_write, 0, 0, addr);
boost::uint32_t *patomic_word = 0; //avoid gcc warning
patomic_word = static_cast<boost::uint32_t*>(region.get_address());
boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment);
if(previous == UninitializedSegment){
BOOST_TRY{
construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
, size - ManagedOpenOrCreateUserOffset, true);
//All ok, just move resources to the external mapped region
final_region.swap(region);
}
BOOST_CATCH(...){
atomic_write32(patomic_word, CorruptedSegment);
BOOST_RETHROW
} BOOST_CATCH_END
atomic_write32(patomic_word, InitializedSegment);
}
else{
atomic_write32(patomic_word, CorruptedSegment);
throw interprocess_exception(error_info(corrupted_error));
}
}
BOOST_CATCH(...){
BOOST_TRY{
truncate_device<FileBased>(dev, 1u, file_like_t());
}
BOOST_CATCH(...){
}
BOOST_CATCH_END
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class ConstructFunc>
static void do_map_after_open
( DeviceAbstraction &dev, mapped_region &final_region
, const void *addr, ConstructFunc construct_func
, bool ronly, bool cow)
{
const usduration TimeoutSec(usduration_seconds(MaxInitializeTimeSec));
if(FileBased){
offset_t filesize = 0;
spin_wait swait;
//If a file device was used, the creator might be truncating the device, so wait
//until the file size is enough to map the initial word
ustime ustime_start = microsec_clock<ustime>::universal_time();
while(1){
if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
error_info err = system_error_code();
throw interprocess_exception(err);
}
if (filesize != 0)
break;
else {
//More than MaxZeroTruncateTimeSec seconds waiting to the creator
//to minimally increase the size of the file: something bad has happened
const usduration elapsed(microsec_clock<ustime>::universal_time() - ustime_start);
if (elapsed > TimeoutSec){
throw interprocess_exception(error_info(corrupted_error));
}
swait.yield();
}
}
//The creator detected an error creating the file and signalled it with size 1
if(filesize == 1){
throw interprocess_exception(error_info(corrupted_error));
}
}
mapped_region region(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr);
boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
boost::uint32_t value = atomic_read32(patomic_word);
if (value != InitializedSegment){
ustime ustime_start = microsec_clock<ustime>::universal_time();
spin_wait swait;
while ((value = atomic_read32(patomic_word)) != InitializedSegment){
if(value == CorruptedSegment){
throw interprocess_exception(error_info(corrupted_error));
}
//More than MaxZeroTruncateTimeSec seconds waiting to the creator
//to minimally increase the size of the file: something bad has happened
const usduration elapsed(microsec_clock<ustime>::universal_time() - ustime_start);
if (elapsed > TimeoutSec){
throw interprocess_exception(error_info(corrupted_error));
}
swait.yield();
}
//The size of the file might have grown while Uninitialized -> Initializing, so remap
{
mapped_region null_map;
region.swap(null_map);
}
mapped_region final_size_map(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr);
final_size_map.swap(region);
}
construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
, region.get_size() - ManagedOpenOrCreateUserOffset
, false);
//All ok, just move resources to the external mapped region
final_region.swap(region);
}
template <class DeviceId, class ConstructFunc> inline
void priv_open_or_create
(create_enum_t type,
const device_id_t & id,
const DeviceId & id,
std::size_t size,
mode_t mode, const void *addr,
const permissions &perm,
ConstructFunc construct_func)
{
typedef bool_<FileBased> file_like_t;
(void)mode;
bool created = false;
bool ronly = false;
bool cow = false;
DeviceAbstraction dev;
if(type != DoOpen){
//Check if the requested size is enough to build the managed metadata
const std::size_t func_min_size = construct_func.get_min_size();
@@ -330,149 +472,39 @@ class managed_open_or_create_impl
size < (func_min_size + ManagedOpenOrCreateUserOffset) ){
throw interprocess_exception(error_info(size_error));
}
//Check size can be represented by offset_t (used by truncate)
if (!check_offset_t_size<FileBased>(size, file_like_t())){
throw interprocess_exception(error_info(size_error));
}
}
//Check size can be represented by offset_t (used by truncate)
if(type != DoOpen && !check_offset_t_size<FileBased>(size, file_like_t())){
throw interprocess_exception(error_info(size_error));
}
if(type == DoOpen && mode == read_write){
DeviceAbstraction tmp(open_only, id, read_write);
//Now create the device (file, shm file, etc.)
DeviceAbstraction dev;
(void)mode;
bool created = false;
bool ronly = false;
bool cow = false;
if(type == DoOpen){
DeviceAbstraction tmp(open_only, id, mode == read_write ? read_write : read_only);
tmp.swap(dev);
created = false;
}
else if(type == DoOpen && mode == read_only){
DeviceAbstraction tmp(open_only, id, read_only);
tmp.swap(dev);
created = false;
ronly = true;
}
else if(type == DoOpen && mode == copy_on_write){
DeviceAbstraction tmp(open_only, id, read_only);
tmp.swap(dev);
created = false;
cow = true;
ronly = mode == read_only;
cow = mode == copy_on_write;
}
else if(type == DoCreate){
create_device<FileBased>(dev, id, size, perm, file_like_t());
created = true;
}
else if(type == DoOpenOrCreate){
//This loop is very ugly, but brute force is sometimes better
//than diplomacy. If someone knows how to open or create a
//file and know if we have really created it or just open it
//drop me a e-mail!
bool completed = false;
spin_wait swait;
while(!completed){
try{
create_device<FileBased>(dev, id, size, perm, file_like_t());
created = true;
completed = true;
}
catch(interprocess_exception &ex){
if(ex.get_error_code() != already_exists_error){
throw;
}
else{
try{
DeviceAbstraction tmp(open_only, id, read_write);
dev.swap(tmp);
created = false;
completed = true;
}
catch(interprocess_exception &e){
if(e.get_error_code() != not_found_error){
throw;
}
}
catch(...){
throw;
}
}
}
catch(...){
throw;
}
swait.yield();
}
else { //DoOpenOrCreate
created = this->do_create_else_open(dev, id, size, perm);
}
if(created){
try{
//If this throws, we are lost
truncate_device<FileBased>(dev, size, file_like_t());
//If the following throws, we will truncate the file to 1
mapped_region region(dev, read_write, 0, 0, addr);
boost::uint32_t *patomic_word = 0; //avoid gcc warning
patomic_word = static_cast<boost::uint32_t*>(region.get_address());
boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment);
if(previous == UninitializedSegment){
try{
construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
, size - ManagedOpenOrCreateUserOffset, true);
//All ok, just move resources to the external mapped region
m_mapped_region.swap(region);
}
catch(...){
atomic_write32(patomic_word, CorruptedSegment);
throw;
}
atomic_write32(patomic_word, InitializedSegment);
}
else if(previous == InitializingSegment || previous == InitializedSegment){
throw interprocess_exception(error_info(already_exists_error));
}
else{
throw interprocess_exception(error_info(corrupted_error));
}
}
catch(...){
try{
truncate_device<FileBased>(dev, 1u, file_like_t());
}
catch(...){
}
throw;
}
this->do_map_after_create(dev, m_mapped_region, size, addr, construct_func);
}
else{
if(FileBased){
offset_t filesize = 0;
spin_wait swait;
while(filesize == 0){
if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
error_info err = system_error_code();
throw interprocess_exception(err);
}
swait.yield();
}
if(filesize == 1){
throw interprocess_exception(error_info(corrupted_error));
}
}
mapped_region region(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr);
boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
boost::uint32_t value = atomic_read32(patomic_word);
spin_wait swait;
while(value == InitializingSegment || value == UninitializedSegment){
swait.yield();
value = atomic_read32(patomic_word);
}
if(value != InitializedSegment)
throw interprocess_exception(error_info(corrupted_error));
construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
, region.get_size() - ManagedOpenOrCreateUserOffset
, false);
//All ok, just move resources to the external mapped region
m_mapped_region.swap(region);
this->do_map_after_open(dev, m_mapped_region, addr, construct_func, ronly, cow);
}
if(StoreDevice){
this->DevHolder::get_device() = boost::move(dev);
}

View File

@@ -66,7 +66,7 @@ struct CtorArgN : public placement_destroy<T>
virtual void construct_n(void *mem
, std::size_t num
, std::size_t &constructed)
, std::size_t &constructed) BOOST_OVERRIDE
{
T* memory = static_cast<T*>(mem);
for(constructed = 0; constructed < num; ++constructed){
@@ -200,7 +200,7 @@ struct CtorArg##N : placement_destroy<T>\
CtorArg##N ( BOOST_MOVE_UREF##N )\
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
\
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) BOOST_OVERRIDE\
{\
T* memory = static_cast<T*>(mem);\
for(constructed = 0; constructed < num; ++constructed){\
@@ -230,7 +230,7 @@ struct CtorIt##N : public placement_destroy<T>\
CtorIt##N ( BOOST_MOVE_VAL##N )\
BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\
\
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)\
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) BOOST_OVERRIDE\
{\
T* memory = static_cast<T*>(mem);\
for(constructed = 0; constructed < num; ++constructed){\

View File

@@ -23,23 +23,24 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/errors.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/static_assert.hpp>
#include <string>
#include <limits>
#include <climits>
#include <string>
#include <boost/move/detail/type_traits.hpp> //make_unsigned
#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
# include <wchar.h> //wcsxxx()
#else
# ifdef BOOST_HAS_UNISTD_H
# include <fcntl.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <errno.h>
# include <cstdio>
# include <dirent.h>
# include <cerrno>
# include <cstdio>
# if 0
# include <sys/file.h>
# endif
@@ -99,10 +100,26 @@ inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
{ return hnd.handle; }
inline bool create_directory(const char *path)
template<class CharT>
inline bool create_directory(const CharT *path)
{ return winapi::create_directory(path); }
inline bool remove_directory(const char *path)
template<class CharT>
inline bool open_or_create_directory(const CharT *path)
{
//If fails, check that it's because it already exists
return create_directory(path)
|| error_info(system_error_code()).get_error_code() == already_exists_error;
}
template<class CharT>
inline bool open_or_create_shared_directory(const CharT *path)
{
return open_or_create_directory(path);
}
template <class CharT>
inline bool remove_directory(const CharT *path)
{ return winapi::remove_directory(path); }
inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
@@ -115,15 +132,33 @@ inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &r
return false;
}
required_len = winapi::get_temp_path(buf_len, buffer);
const bool ret = !(buf_len < required_len);
const bool ret = required_len && (buf_len > required_len);
if(ret && buffer[required_len-1] == '\\'){
buffer[required_len-1] = 0;
buffer[required_len-1] = '\0';
}
return ret;
}
inline bool get_temporary_path(wchar_t *buffer, std::size_t buf_len, std::size_t &required_len)
{
required_len = 0;
//std::size_t is always bigger or equal than unsigned long in Windows systems
//In case std::size_t is bigger than unsigned long
unsigned long buf = buf_len;
if(buf_len != buf){ //maybe overflowed
return false;
}
required_len = winapi::get_temp_path(buf_len, buffer);
const bool ret = !(buf_len < required_len);
if(ret && buffer[required_len-1] == L'\\'){
buffer[required_len-1] = L'\0';
}
return ret;
}
template<class CharT>
inline file_handle_t create_new_file
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
(const CharT *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
@@ -131,8 +166,9 @@ inline file_handle_t create_new_file
, (winapi::interprocess_security_attributes*)perm.get_permissions());
}
template <class CharT>
inline file_handle_t create_or_open_file
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
(const CharT *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
@@ -140,8 +176,9 @@ inline file_handle_t create_or_open_file
, (winapi::interprocess_security_attributes*)perm.get_permissions());
}
template<class CharT>
inline file_handle_t open_existing_file
(const char *name, mode_t mode, bool temporary = false)
(const CharT *name, mode_t mode, bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
@@ -151,6 +188,9 @@ inline file_handle_t open_existing_file
inline bool delete_file(const char *name)
{ return winapi::unlink_file(name); }
inline bool delete_file(const wchar_t *name)
{ return winapi::unlink_file(name); }
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
offset_t filesize;
@@ -158,8 +198,8 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
return false;
typedef ::boost::move_detail::make_unsigned<offset_t>::type uoffset_t;
const uoffset_t max_filesize = uoffset_t((std::numeric_limits<offset_t>::max)());
const uoffset_t uoff_size = uoffset_t(size);
const uoffset_t max_filesize = uoffset_t(-1)/2u;
const uoffset_t uoff_size = uoffset_t(size);
//Avoid unused variable warnings in 32 bit systems
if(uoff_size > max_filesize){
winapi::set_last_error(winapi::error_file_too_large);
@@ -167,12 +207,12 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
}
if(offset_t(size) > filesize){
if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
if(!winapi::set_file_pointer(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
for(std::size_t remaining = size - std::size_t(filesize), write_size = 0
;remaining > 0
;remaining -= write_size){
const std::size_t DataSize = 512;
@@ -186,7 +226,7 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size)
}
}
else{
if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
if(!winapi::set_file_pointer(hnd, size, 0, winapi::file_begin)){
return false;
}
if(!winapi::set_end_of_file(hnd)){
@@ -200,10 +240,10 @@ inline bool get_file_size(file_handle_t hnd, offset_t &size)
{ return winapi::get_file_size(hnd, size); }
inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
{ return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); }
{ return winapi::set_file_pointer(hnd, off, 0, (unsigned long) pos); }
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
{ return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
{ return winapi::set_file_pointer(hnd, 0, &off, winapi::file_current); }
inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
{
@@ -239,7 +279,8 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
acquired = false, true : false;
}
return (acquired = true);
acquired = true;
return true;
}
inline bool release_file_lock(file_handle_t hnd)
@@ -268,32 +309,75 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
return winapi::get_last_error() == winapi::error_lock_violation ?
acquired = false, true : false;
}
return (acquired = true);
acquired = true;
return true;
}
inline bool release_file_lock_sharable(file_handle_t hnd)
{ return release_file_lock(hnd); }
template<class CharT>
struct os_file_traits;
template<>
struct os_file_traits<char>
{
static const char *any_file()
{ return "\\*.*"; }
static const char *backslash()
{ return "\\"; }
static char dot()
{ return '.'; }
typedef winapi::win32_find_data_a win32_find_data_t;
static int cmp(const char *a, const char *b)
{ return std::strcmp(a, b); }
};
template<>
struct os_file_traits<wchar_t>
{
static const wchar_t *any_file()
{ return L"\\*.*"; }
static const wchar_t *backslash()
{ return L"\\"; }
static wchar_t dot()
{ return L'.'; }
typedef winapi::win32_find_data_w win32_find_data_t;
static int cmp(const wchar_t *a, const wchar_t *b)
{ return std::wcscmp(a, b); }
};
template<class CharT>
inline bool delete_subdirectories_recursive
(const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
(const std::basic_string<CharT> &refcstrRootDirectory, const CharT *dont_delete_this, unsigned int count)
{
bool bSubdirectory = false; // Flag, indicating whether
// subdirectories have been found
void * hFile; // Handle to directory
std::string strFilePath; // Filepath
std::string strPattern; // Pattern
winapi::win32_find_data FileInformation; // File information
std::basic_string<CharT> strFilePath; // Filepath
std::basic_string<CharT> strPattern; // Pattern
typedef os_file_traits<CharT> traits_t;
typename traits_t::win32_find_data_t FileInformation; // File information
//Find all files and directories
strPattern = refcstrRootDirectory + "\\*.*";
strPattern = refcstrRootDirectory + traits_t::any_file();
hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
if(hFile != winapi::invalid_handle_value){
do{
//If it's not "." or ".." or the pointed root_level dont_delete_this erase it
if(FileInformation.cFileName[0] != '.' &&
!(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
if(FileInformation.cFileName[0] != traits_t::dot() &&
!(dont_delete_this && count == 0 && traits_t::cmp(dont_delete_this, FileInformation.cFileName) == 0)){
strFilePath.erase();
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
strFilePath = refcstrRootDirectory + traits_t::backslash() + FileInformation.cFileName;
//If it's a directory, go recursive
if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
@@ -340,7 +424,8 @@ inline bool delete_subdirectories_recursive
}
//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
template <class CharT>
inline bool delete_subdirectories(const std::basic_string<CharT> &refcstrRootDirectory, const CharT *dont_delete_this)
{
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
}
@@ -350,7 +435,7 @@ template<class Function>
inline bool for_each_file_in_dir(const char *dir, Function f)
{
void * hFile; // Handle to directory
winapi::win32_find_data FileInformation; // File information
winapi::win32_find_data_a FileInformation; // File information
//Get base directory
std::string str(dir);
@@ -423,7 +508,27 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
{ return hnd.handle; }
inline bool create_directory(const char *path)
{ return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
{
::mode_t m = ::mode_t(0777);
return ::mkdir(path, m) == 0;
}
inline bool open_or_create_directory(const char *path)
{
::mode_t m = ::mode_t(0777);
return ::mkdir(path, m) == 0 || (errno == EEXIST);
}
inline bool open_or_create_shared_directory(const char *path)
{
const ::mode_t m = ::mode_t(01777);
const bool created = ::mkdir(path, m) == 0;
const bool created_or_exists = created || (errno == EEXIST);
//Try to maximize the chance that the sticky bit is set in shared dirs
//created with old versions that did not set it (for security reasons)
const bool chmoded = ::chmod(path, m) == 0;
return created ? chmoded : created_or_exists;
}
inline bool remove_directory(const char *path)
{ return ::rmdir(path) == 0; }
@@ -457,7 +562,7 @@ inline file_handle_t create_or_open_file
int ret = -1;
//We need a loop to change permissions correctly using fchmod, since
//with "O_CREAT only" ::open we don't know if we've created or opened the file.
while(1){
while(true){
ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
if(ret >= 0){
::fchmod(ret, perm.get_permissions());
@@ -488,7 +593,8 @@ inline bool delete_file(const char *name)
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
typedef boost::move_detail::make_unsigned<off_t>::type uoff_t;
if(uoff_t((std::numeric_limits<off_t>::max)()) < size){
BOOST_STATIC_ASSERT(( sizeof(uoff_t) >= sizeof(std::size_t) ));
if( uoff_t(-1)/2u < uoff_t(size) ){
errno = EINVAL;
return false;
}
@@ -543,7 +649,7 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
int ret = ::fcntl(hnd, F_SETLK, &lock);
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
acquired = false, true : false;
(acquired = false, true) : false;
}
return (acquired = true);
}
@@ -578,7 +684,7 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
int ret = ::fcntl(hnd, F_SETLK, &lock);
if(ret == -1){
return (errno == EAGAIN || errno == EACCES) ?
acquired = false, true : false;
(acquired = false, true) : false;
}
return (acquired = true);
}
@@ -711,22 +817,10 @@ inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
inline bool open_or_create_directory(const char *dir_name)
{
//If fails, check that it's because it already exists
if(!create_directory(dir_name)){
error_info info(system_error_code());
if(info.get_error_code() != already_exists_error){
return false;
}
}
return true;
}
inline std::string get_temporary_path()
{
std::size_t required_len = 0;
get_temporary_path(0, 0, required_len);
get_temporary_path((char*)0, 0, required_len);
std::string ret_str(required_len, char(0));
get_temporary_path(&ret_str[0], ret_str.size(), required_len);
while(!ret_str.empty() && !ret_str[ret_str.size()-1]){
@@ -736,6 +830,23 @@ inline std::string get_temporary_path()
return ret_str;
}
#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES
inline std::wstring get_temporary_wpath()
{
std::size_t required_len = 0;
get_temporary_path((wchar_t*)0, 0, required_len);
std::wstring ret_str(required_len, char(0));
get_temporary_path(&ret_str[0], ret_str.size(), required_len);
while(!ret_str.empty() && !ret_str[ret_str.size()-1]){
ret_str.erase(ret_str.size()-1);
}
return ret_str;
}
#endif
} //namespace ipcdetail{
} //namespace interprocess {
} //namespace boost {

View File

@@ -33,13 +33,12 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <cstddef>
#include <ostream>
#if defined(BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
# include <process.h>
# include <boost/winapi/thread.hpp>
#else
# include <pthread.h>
# include <unistd.h>
@@ -158,7 +157,7 @@ inline OS_highres_count_t get_current_system_highres_count()
if(!winapi::query_performance_counter(&count)){
count = winapi::get_tick_count();
}
return count;
return (OS_highres_count_t)count;
}
inline void zero_highres_count(OS_highres_count_t &count)
@@ -229,7 +228,7 @@ inline long double get_current_process_creation_time()
inline unsigned int get_num_cores()
{
winapi::system_info sysinfo;
winapi::interprocess_system_info sysinfo;
winapi::get_system_info( &sysinfo );
//in Windows dw is long which is equal in bits to int
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
@@ -422,7 +421,7 @@ inline void thread_sleep_tick()
struct timespec rqt;
//Sleep for the half of the tick time
rqt.tv_sec = 0;
rqt.tv_nsec = get_system_tick_ns()/2;
rqt.tv_nsec = (long)get_system_tick_ns()/2;
::nanosleep(&rqt, 0);
}
@@ -519,9 +518,9 @@ inline void get_pid_str(pid_str_t &pid_str)
#if defined(BOOST_INTERPROCESS_WINDOWS)
inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg )
inline int thread_create( OS_thread_t * thread, boost::ipwinapiext::LPTHREAD_START_ROUTINE_ start_routine, void* arg )
{
void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
void* h = boost::ipwinapiext::CreateThread(0, 0, start_routine, arg, 0, 0);
if( h != 0 ){
thread->m_handle = h;
@@ -530,9 +529,6 @@ inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_rout
else{
return 1;
}
thread->m_handle = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
return thread->m_handle != 0;
}
inline void thread_join( OS_thread_t thread)
@@ -576,7 +572,7 @@ class os_thread_func_ptr_deleter
#if defined(BOOST_INTERPROCESS_WINDOWS)
inline unsigned __stdcall launch_thread_routine( void * pv )
inline boost::winapi::DWORD_ __stdcall launch_thread_routine(boost::winapi::LPVOID_ pv)
{
os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
pt->run();
@@ -605,7 +601,7 @@ class launch_thread_impl
: f_( f )
{}
void run()
virtual void run() BOOST_OVERRIDE
{ f_(); }
private:

View File

@@ -52,7 +52,7 @@ static void create_tmp_subdir_and_get_pid_based_filepath
create_shared_dir_and_clean_old(s);
s += "/";
s += subdir_name;
if(!open_or_create_directory(s.c_str())){
if(!open_or_create_shared_directory(s.c_str())){
error_info err = system_error_code();
throw interprocess_exception(err);
}
@@ -152,7 +152,7 @@ struct thread_safe_global_map_dependant<managed_global_memory>
static void apply_gmem_erase_logic(const char *filepath, const char *filename)
{
int fd = GMemMarkToBeRemoved;
try{
BOOST_TRY{
std::string str;
//If the filename is current process lock file, then avoid it
if(check_if_filename_complies_with_pid
@@ -167,21 +167,21 @@ struct thread_safe_global_map_dependant<managed_global_memory>
//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_map_base_name());
try{
BOOST_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){
BOOST_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);
}
}
} BOOST_CATCH_END
}
catch(...){
BOOST_CATCH(...){
}
} BOOST_CATCH_END
if(fd >= 0){
close_lock_file(fd);
}

View File

@@ -1,51 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-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_POSIX_TIMES_WRK_HPP
#define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
//workaround to avoid winsock redefines when using date-time
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#endif //#ifndef WIN32_LEAN_AND_MEAN
#endif //#ifdef _WIN32
#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
namespace boost {
namespace interprocess {
typedef boost::date_time::microsec_clock<boost::posix_time::ptime> microsec_clock;
}
}
#ifdef _WIN32
#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#endif //#ifdef _WIN32
#endif //#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP

View File

@@ -1,41 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-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_PTIME_WRK_HPP
#define BOOST_INTERPROCESS_PTIME_WRK_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
//workaround to avoid winsock redefines when using date-time
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#endif //#ifndef WIN32_LEAN_AND_MEAN
#endif //#ifdef _WIN32
#include <boost/date_time/posix_time/ptime.hpp>
#ifdef _WIN32
#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
#endif //#ifdef _WIN32
#endif //#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP

View File

@@ -194,7 +194,8 @@ class robust_spin_mutex
robust_spin_mutex();
void lock();
bool try_lock();
bool timed_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
void unlock();
void consistent();
bool previous_owner_dead();
@@ -216,7 +217,7 @@ class robust_spin_mutex
template<class Mutex>
inline robust_spin_mutex<Mutex>::robust_spin_mutex()
: mtx(), owner(get_invalid_process_id()), state(correct_state)
: mtx(), owner((boost::uint32_t)get_invalid_process_id()), state(correct_state)
{}
template<class Mutex>
@@ -236,7 +237,7 @@ inline bool robust_spin_mutex<Mutex>::try_lock()
}
if (mtx.try_lock()){
atomic_write32(&this->owner, get_current_process_id());
atomic_write32(&this->owner, static_cast<boost::uint32_t>(get_current_process_id()));
return true;
}
else{
@@ -250,14 +251,15 @@ inline bool robust_spin_mutex<Mutex>::try_lock()
}
template<class Mutex>
template<class TimePoint>
inline bool robust_spin_mutex<Mutex>::timed_lock
(const boost::posix_time::ptime &abs_time)
(const TimePoint &abs_time)
{ return try_based_timed_lock(*this, abs_time); }
template<class Mutex>
inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t own, std::string &s)
{
robust_emulation_helpers::create_and_get_robust_lock_file_path(s, own);
robust_emulation_helpers::create_and_get_robust_lock_file_path(s, (OS_process_id_t)own);
}
template<class Mutex>
@@ -276,7 +278,7 @@ inline bool robust_spin_mutex<Mutex>::robust_check()
template<class Mutex>
inline bool robust_spin_mutex<Mutex>::check_if_owner_dead_and_take_ownership_atomically()
{
boost::uint32_t cur_owner = get_current_process_id();
boost::uint32_t cur_owner = static_cast<boost::uint32_t>(get_current_process_id());
boost::uint32_t old_owner = atomic_read32(&this->owner), old_owner2;
//The cas loop guarantees that only one thread from this or another process
//will succeed taking ownership
@@ -298,7 +300,7 @@ template<class Mutex>
inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t own)
{
//If owner is an invalid id, then it's clear it's dead
if(own == (boost::uint32_t)get_invalid_process_id()){
if(own == static_cast<boost::uint32_t>(get_invalid_process_id())){
return true;
}
@@ -362,7 +364,7 @@ inline void robust_spin_mutex<Mutex>::unlock()
atomic_write32(&this->state, broken_state);
}
//Write an invalid owner to minimize pid reuse possibility
atomic_write32(&this->owner, get_invalid_process_id());
atomic_write32(&this->owner, static_cast<boost::uint32_t>(get_invalid_process_id()));
mtx.unlock();
}

View File

@@ -35,6 +35,7 @@
#include <boost/intrusive/pointer_traits.hpp>
// move/detail
#include <boost/move/detail/type_traits.hpp> //make_unsigned
#include <boost/move/detail/force_ptr.hpp>
// other boost
#include <boost/assert.hpp> //BOOST_ASSERT
#include <boost/core/no_exceptions_support.hpp>
@@ -92,7 +93,7 @@ struct block_header
: m_value_bytes(val_bytes)
, m_num_char((unsigned short)num_char)
, m_value_alignment((unsigned char)val_alignment)
, m_alloc_type_sizeof_char( (al_type << 5u) | ((unsigned char)szof_char & 0x1F) )
, m_alloc_type_sizeof_char( (unsigned char)((al_type << 5u) | ((unsigned char)szof_char & 0x1F)) )
{};
template<class T>
@@ -102,7 +103,7 @@ struct block_header
size_type total_size() const
{
if(alloc_type() != anonymous_type){
return name_offset() + (m_num_char+1)*sizeof_char();
return name_offset() + (m_num_char+1u)*sizeof_char();
}
else{
return this->value_offset() + m_value_bytes;
@@ -130,7 +131,7 @@ struct block_header
template<class CharType>
CharType *name() const
{
return const_cast<CharType*>(reinterpret_cast<const CharType*>
return const_cast<CharType*>(move_detail::force_ptr<const CharType*>
(reinterpret_cast<const char*>(this) + name_offset()));
}
@@ -175,7 +176,7 @@ struct block_header
{
block_header * hdr =
const_cast<block_header*>
(reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) -
(move_detail::force_ptr<const block_header*>(reinterpret_cast<const char*>(value) -
get_rounded_size(sizeof(block_header), algn)));
(void)sz;
//Some sanity checks
@@ -188,7 +189,7 @@ struct block_header
static block_header<size_type> *from_first_header(Header *header)
{
block_header<size_type> * hdr =
reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) +
move_detail::force_ptr<block_header<size_type>*>(reinterpret_cast<char*>(header) +
get_rounded_size( size_type(sizeof(Header))
, size_type(::boost::container::dtl::alignment_of<block_header<size_type> >::value)));
//Some sanity checks
@@ -199,7 +200,7 @@ struct block_header
static Header *to_first_header(block_header<size_type> *bheader)
{
Header * hdr =
reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
move_detail::force_ptr<Header*>(reinterpret_cast<char*>(bheader) -
get_rounded_size( size_type(sizeof(Header))
, size_type(::boost::container::dtl::alignment_of<block_header<size_type> >::value)));
//Some sanity checks
@@ -219,8 +220,7 @@ inline void array_construct(void *mem, std::size_t num, in_place_interface &tabl
std::size_t destroyed = 0;
table.destroy_n(mem, constructed, destroyed);
BOOST_RETHROW
}
BOOST_CATCH_END
} BOOST_CATCH_END
}
template<class CharT>
@@ -280,7 +280,7 @@ struct intrusive_value_type_impl
block_header<size_type> *get_block_header() const
{
return const_cast<block_header<size_type>*>
(reinterpret_cast<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
(move_detail::force_ptr<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
}
@@ -292,7 +292,7 @@ struct intrusive_value_type_impl
static intrusive_value_type_impl *get_intrusive_value_type(block_header<size_type> *hdr)
{
return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
return move_detail::force_ptr<intrusive_value_type_impl*>(reinterpret_cast<char*>(hdr) -
get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
}
@@ -472,7 +472,7 @@ class segment_manager_iterator_value_adaptor<Iterator, false>
const void *value() const
{
return reinterpret_cast<block_header<size_type>*>
return move_detail::force_ptr<block_header<size_type>*>
(to_raw_pointer(m_val->second.m_ptr))->value();
}

View File

@@ -34,9 +34,33 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
template<class CharT>
struct shared_dir_constants;
template<>
struct shared_dir_constants<char>
{
static char dir_separator()
{ return '/'; }
static const char *dir_interprocess()
{ return "/boost_interprocess"; }
};
template<>
struct shared_dir_constants<wchar_t>
{
static wchar_t dir_separator()
{ return L'/'; }
static const wchar_t *dir_interprocess()
{ return L"/boost_interprocess"; }
};
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
#if defined(BOOST_INTERPROCESS_WINDOWS)
//This type will initialize the stamp
template<class CharT>
struct windows_bootstamp
{
windows_bootstamp()
@@ -49,12 +73,13 @@ namespace ipcdetail {
}
//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;
std::basic_string<CharT> stamp;
};
inline void get_bootstamp(std::string &s, bool add = false)
template <class CharT>
inline void get_bootstamp(std::basic_string<CharT> &s, bool add = false)
{
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
const windows_bootstamp<CharT> &bootstamp = windows_intermodule_singleton<windows_bootstamp<CharT> >::get();
if(add){
s += bootstamp.stamp;
}
@@ -102,7 +127,8 @@ namespace ipcdetail {
#endif
#endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
inline void get_shared_dir_root(std::string &dir_path)
template <class CharT>
inline void get_shared_dir_root(std::basic_string<CharT> &dir_path)
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
winapi::get_shared_documents_folder(dir_path);
@@ -115,8 +141,8 @@ inline void get_shared_dir_root(std::string &dir_path)
error_info err = system_error_code();
throw interprocess_exception(err);
}
//Remove final null.
dir_path += "/boost_interprocess";
dir_path += shared_dir_constants<CharT>::dir_interprocess();
}
#if defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC) && defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
@@ -129,57 +155,75 @@ inline void get_shared_dir_root(std::string &dir_path)
// get_shared_dir
void get_shared_dir(std::string &shared_dir);
// When BOOST_INTERPROCESS_SHARED_DIR_FUNC is defined, users have to implement
// get_shared_dir
void get_shared_dir(std::wstring &shared_dir);
#else
#if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
inline void get_shared_dir(std::string &shared_dir)
{
#if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH)
shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH;
#else
shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH;
}
#endif
#if defined(BOOST_INTERPROCESS_SHARED_DIR_WPATH)
inline void get_shared_dir(std::wstring &shared_dir)
{
shared_dir = BOOST_INTERPROCESS_SHARED_DIR_WPATH;
}
#endif
template<class CharT>
inline void get_shared_dir(std::basic_string<CharT> &shared_dir)
{
get_shared_dir_root(shared_dir);
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
shared_dir += "/";
shared_dir += shared_dir_constants<CharT>::dir_separator();
get_bootstamp(shared_dir, true);
#endif
#endif
}
#endif
inline void shared_filepath(const char *filename, std::string &filepath)
template<class CharT>
inline void shared_filepath(const CharT *filename, std::basic_string<CharT> &filepath)
{
get_shared_dir(filepath);
filepath += "/";
filepath += shared_dir_constants<CharT>::dir_separator();
filepath += filename;
}
inline void create_shared_dir_and_clean_old(std::string &shared_dir)
template<class CharT>
inline void create_shared_dir_and_clean_old(std::basic_string<CharT> &shared_dir)
{
#if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) || defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC)
get_shared_dir(shared_dir);
#else
//First get the temp directory
std::string root_shared_dir;
std::basic_string<CharT> root_shared_dir;
get_shared_dir_root(root_shared_dir);
//If fails, check that it's because already exists
if(!create_directory(root_shared_dir.c_str())){
if(!open_or_create_shared_directory(root_shared_dir.c_str())){
error_info info(system_error_code());
if(info.get_error_code() != already_exists_error){
throw interprocess_exception(info);
}
throw interprocess_exception(info);
}
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
get_shared_dir(shared_dir);
//If fails, check that it's because already exists
if(!create_directory(shared_dir.c_str())){
if(!open_or_create_shared_directory(shared_dir.c_str())){
error_info info(system_error_code());
if(info.get_error_code() != already_exists_error){
throw interprocess_exception(info);
}
throw interprocess_exception(info);
}
//Now erase all old directories created in the previous boot sessions
std::string subdir = shared_dir;
std::basic_string<CharT> subdir = shared_dir;
subdir.erase(0, root_shared_dir.size()+1);
delete_subdirectories(root_shared_dir, subdir.c_str());
#else
@@ -188,17 +232,19 @@ inline void create_shared_dir_and_clean_old(std::string &shared_dir)
#endif
}
inline void create_shared_dir_cleaning_old_and_get_filepath(const char *filename, std::string &shared_dir)
template<class CharT>
inline void create_shared_dir_cleaning_old_and_get_filepath(const CharT *filename, std::basic_string<CharT> &shared_dir)
{
create_shared_dir_and_clean_old(shared_dir);
shared_dir += "/";
shared_dir += shared_dir_constants<CharT>::dir_separator();
shared_dir += filename;
}
inline void add_leading_slash(const char *name, std::string &new_name)
template<class CharT>
inline void add_leading_slash(const CharT *name, std::basic_string<CharT> &new_name)
{
if(name[0] != '/'){
new_name = '/';
if(name[0] != shared_dir_constants<CharT>::dir_separator()){
new_name = shared_dir_constants<CharT>::dir_separator();
}
new_name += name;
}

View File

@@ -0,0 +1,388 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2021-2021.
//
// 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_TIMED_UTILS_HPP
#define BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/intrusive/detail/mpl.hpp>
#include <ctime>
#include <boost/cstdint.hpp>
//The following is used to support high precision time clocks
#ifdef BOOST_HAS_GETTIMEOFDAY
#include <sys/time.h>
#endif
#ifdef BOOST_HAS_FTIME
#include <time.h>
#include <boost/winapi/time.hpp>
#endif
namespace boost {
namespace interprocess {
namespace ipcdetail {
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(time_duration_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(clock)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep_type)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(rep)
template<class T>
struct enable_if_ptime
: enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
{};
template<class T>
struct disable_if_ptime
: enable_if_c< ! BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, time_duration_type) >
{};
template<class T>
struct enable_if_ptime_duration
: enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep_type) >
{};
template<class T>
struct enable_if_time_point
: enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, clock) >
{};
template<class T>
struct enable_if_duration
: enable_if_c< BOOST_INTRUSIVE_HAS_TYPE(boost::interprocess::ipcdetail::, T, rep) >
{};
#if defined(BOOST_INTERPROCESS_HAS_REENTRANT_STD_FUNCTIONS)
inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
{
// gmtime_r() not in namespace std???
#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
std::tm tmp;
if(!gmtime_r(t,&tmp))
result = 0;
else
*result = tmp;
#else
result = gmtime_r(t, result);
#endif
return result;
}
#else // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
#if defined(__clang__) // Clang has to be checked before MSVC
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
# pragma warning(push) // preserve warning settings
# pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8
#endif
inline std::tm* interprocess_gmtime(const std::time_t* t, std::tm* result)
{
result = std::gmtime(t);
return result;
}
#if defined(__clang__) // Clang has to be checked before MSVC
# pragma clang diagnostic pop
#elif (defined(_MSC_VER) && (_MSC_VER >= 1400))
# pragma warning(pop) // restore warnings to previous state
#endif
#endif // BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS
#if defined(BOOST_HAS_FTIME)
/*!
* The function converts file_time into number of microseconds elapsed since 1970-Jan-01
*
* \note Only dates after 1970-Jan-01 are supported. Dates before will be wrapped.
*/
inline boost::uint64_t file_time_to_microseconds(const boost::winapi::FILETIME_ & ft)
{
// shift is difference between 1970-Jan-01 & 1601-Jan-01
// in 100-nanosecond units
const boost::uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
// 100-nanos since 1601-Jan-01
boost::uint64_t ft_as_integer = (static_cast< boost::uint64_t >(ft.dwHighDateTime) << 32) | static_cast< boost::uint64_t >(ft.dwLowDateTime);
ft_as_integer -= shift; // filetime is now 100-nanos since 1970-Jan-01
return (ft_as_integer / 10U); // truncate to microseconds
}
#endif
class ustime;
class usduration
{
public:
friend class ustime;
explicit usduration(boost::uint64_t microsecs)
: m_microsecs(microsecs)
{}
boost::uint64_t get_microsecs() const
{ return m_microsecs; }
bool operator < (const usduration &other) const
{ return m_microsecs < other.m_microsecs; }
bool operator > (const usduration &other) const
{ return m_microsecs > other.m_microsecs; }
bool operator <= (const usduration &other) const
{ return m_microsecs <= other.m_microsecs; }
bool operator >= (const usduration &other) const
{ return m_microsecs >= other.m_microsecs; }
private:
boost::uint64_t m_microsecs;
};
class ustime
{
public:
explicit ustime(boost::uint64_t microsecs)
: m_microsecs(microsecs)
{}
ustime &operator += (const usduration &other)
{ m_microsecs += other.m_microsecs; return *this; }
ustime operator + (const usduration &other)
{ ustime r(*this); r += other; return r; }
ustime &operator -= (const usduration &other)
{ m_microsecs -= other.m_microsecs; return *this; }
ustime operator - (const usduration &other)
{ ustime r(*this); r -= other; return r; }
friend usduration operator - (const ustime &l, const ustime &r)
{ return usduration(l.m_microsecs - r.m_microsecs); }
bool operator < (const ustime &other) const
{ return m_microsecs < other.m_microsecs; }
bool operator > (const ustime &other) const
{ return m_microsecs > other.m_microsecs; }
bool operator <= (const ustime &other) const
{ return m_microsecs <= other.m_microsecs; }
bool operator >= (const ustime &other) const
{ return m_microsecs >= other.m_microsecs; }
boost::uint64_t get_microsecs() const
{ return m_microsecs; }
private:
boost::uint64_t m_microsecs;
};
inline usduration usduration_milliseconds(boost::uint64_t millisec)
{ return usduration(millisec*1000u); }
inline usduration usduration_seconds(boost::uint64_t sec)
{ return usduration(sec*uint64_t(1000000u)); }
template<class TimeType, class Enable = void>
class microsec_clock;
template<class TimeType>
class microsec_clock<TimeType, typename enable_if_ptime<TimeType>::type>
{
private:
typedef typename TimeType::date_type date_type;
typedef typename TimeType::time_duration_type time_duration_type;
typedef typename time_duration_type::rep_type resolution_traits_type;
public:
static TimeType universal_time()
{
#ifdef BOOST_HAS_GETTIMEOFDAY
timeval tv;
gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
std::time_t t = tv.tv_sec;
boost::uint32_t sub_sec = static_cast<boost::uint32_t>(tv.tv_usec);
#elif defined(BOOST_HAS_FTIME)
boost::winapi::FILETIME_ ft;
boost::winapi::GetSystemTimeAsFileTime(&ft);
boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
// and cannot be before 1970-Jan-01
std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
// microseconds -- static casts suppress warnings
boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
#else
#error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
#endif
std::tm curr;
std::tm* curr_ptr = interprocess_gmtime(&t, &curr);
date_type d(static_cast< typename date_type::year_type::value_type >(curr_ptr->tm_year + 1900),
static_cast< typename date_type::month_type::value_type >(curr_ptr->tm_mon + 1),
static_cast< typename date_type::day_type::value_type >(curr_ptr->tm_mday));
//The following line will adjust the fractional second tick in terms
//of the current time system. For example, if the time system
//doesn't support fractional seconds then res_adjust returns 0
//and all the fractional seconds return 0.
unsigned adjust = static_cast< unsigned >(resolution_traits_type::res_adjust() / 1000000);
time_duration_type td(static_cast< typename time_duration_type::hour_type >(curr_ptr->tm_hour),
static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
static_cast< typename time_duration_type::fractional_seconds_type >(sub_sec * adjust)
);
return TimeType(d,td);
}
};
template<>
class microsec_clock<ustime>
{
public:
static ustime universal_time()
{
#ifdef BOOST_HAS_GETTIMEOFDAY
timeval tv;
gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
boost::uint64_t micros = boost::uint64_t(tv.tv_sec)*1000000;
micros += (boost::uint64_t)tv.tv_usec;
#elif defined(BOOST_HAS_FTIME)
boost::winapi::FILETIME_ ft;
boost::winapi::GetSystemTimeAsFileTime(&ft);
boost::uint64_t micros = file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
// and cannot be before 1970-Jan-01
#else
#error "Unsupported date-time error: neither gettimeofday nor FILETIME support is detected"
#endif
return ustime(micros);
}
};
template<class TimePoint>
class microsec_clock<TimePoint, typename enable_if_time_point<TimePoint>::type>
{
public:
static TimePoint universal_time()
{ return TimePoint::clock::now(); }
};
template<class TimePoint>
inline TimePoint delay_ms(unsigned msecs, typename enable_if_ptime<TimePoint>::type* = 0)
{
typedef typename TimePoint::time_duration_type time_duration_type;
typedef typename time_duration_type::rep_type resolution_traits_type;
time_duration_type td(msecs*1000*resolution_traits_type::res_adjust());
TimePoint tp(microsec_clock<TimePoint>::universal_time());
return (tp += td);
}
template<class TimePoint>
inline bool is_pos_infinity(const TimePoint &abs_time, typename enable_if_ptime<TimePoint>::type* = 0)
{
return abs_time.is_pos_infinity();
}
template<class TimePoint>
inline bool is_pos_infinity(const TimePoint &, typename disable_if_ptime<TimePoint>::type* = 0)
{
return false;
}
/*
template<class Duration>
inline ustime duration_to_timepoint(const Duration &dur, typename enable_if_ptime<Duration>::type* = 0)
{
return dur.is_pos_infinity();
}
template<class Duration>
inline bool duration_to_timepoint(const Duration &, typename disable_if_ptime<Duration>::type* = 0)
{
return false;
}
*/
// duration_to_milliseconds
template<class Duration>
inline boost::uint64_t duration_to_milliseconds(const Duration &abs_time, typename enable_if_ptime_duration<Duration>::type* = 0)
{
return static_cast<boost::uint64_t>(abs_time.total_milliseconds());
}
template<class Duration>
inline boost::uint64_t duration_to_milliseconds(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
{
const double factor = double(Duration::period::num)*1000.0/double(Duration::period::den);
return static_cast<boost::uint64_t>(double(d.count())*factor);
}
inline boost::uint64_t duration_to_milliseconds(const usduration &d)
{
return d.get_microsecs()/1000;
}
// duration_to_usduration
template<class Duration>
inline usduration duration_to_usduration(const Duration &d, typename enable_if_ptime_duration<Duration>::type* = 0)
{
return usduration(static_cast<boost::uint64_t>(d.total_microseconds()));
}
template<class Duration>
inline usduration duration_to_usduration(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
{
const double factor = double(Duration::period::num)*1000000.0/double(Duration::period::den);
return usduration(static_cast<boost::uint64_t>(double(d.count())*factor));
}
// duration_to_ustime
template<class Duration>
inline ustime duration_to_ustime(const Duration &d)
{
return microsec_clock<ustime>::universal_time() + (duration_to_usduration)(d);
}
} //namespace ipcdetail {
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TIMED_UTILS_HPP

View File

@@ -87,7 +87,7 @@ struct ct_rounded_size
};
// Gennaro Prota wrote this. Thanks!
template <int p, int n = 4>
template <std::size_t p, std::size_t n = 4>
struct ct_max_pow2_less
{
static const std::size_t c = 2*n < p;
@@ -163,8 +163,8 @@ template<class T, class OffsetType>
class pointer_offset_caster<T*, OffsetType>
{
public:
BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(OffsetType offset)
: m_offset(offset)
BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(OffsetType off)
: m_offset(off)
{}
BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(const volatile T *p)

File diff suppressed because it is too large Load Diff

View File

@@ -138,7 +138,7 @@ class windows_semaphore_based_map
name = "bipc_gmap_sem_map_";
name += pid_creation_time;
success = success && m_sem_map.open_or_create
(name.c_str(), initial_count, max_count, perm, created);
(name.c_str(), (long)initial_count, (long)max_count, perm, created);
if(!success){
delete m;
//winapi_xxx wrappers do the cleanup...
@@ -163,8 +163,8 @@ class windows_semaphore_based_map
boost::uint32_t addr_uint32;
} caster;
caster.addr = 0;
caster.addr_uint32 = m_sem_map.limit();
caster.addr_uint32 = caster.addr_uint32 << 2;
caster.addr_uint32 = boost::uint32_t(m_sem_map.limit());
caster.addr_uint32 = caster.addr_uint32 << 2u;
return *static_cast<map_type*>(caster.addr);
}
else{
@@ -173,11 +173,12 @@ class windows_semaphore_based_map
void *addr;
boost::uint64_t addr_uint64;
} caster;
boost::uint32_t max_count(m_sem_map.limit()), initial_count(m_sem_map.value());
boost::uint32_t max_count(boost::uint32_t(m_sem_map.limit()))
, initial_count(boost::uint32_t(m_sem_map.value()));
//Clear quasi-top bit
max_count &= boost::uint32_t(0xBFFFFFFF);
caster.addr_uint64 = max_count;
caster.addr_uint64 = caster.addr_uint64 << 32;
caster.addr_uint64 = caster.addr_uint64 << 32u;
caster.addr_uint64 |= boost::uint64_t(initial_count) << 2;
return *static_cast<map_type*>(caster.addr);
}

View File

@@ -19,12 +19,18 @@
# pragma once
#endif
#if defined(BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION) && defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
#error "BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION && BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION can't be defined at the same time"
#endif
//#define BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#define BOOST_INTERPROCESS_WINDOWS
#define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
#if !defined(BOOST_INTERPROCESS_FORCE_NATIVE_EMULATION) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
#define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
#endif
#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
//Define this to connect with shared memory created with versions < 1.54
//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME
#else
#include <unistd.h>
@@ -65,6 +71,13 @@
#endif
#endif
//////////////////////////////////////////////////////
// BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
//////////////////////////////////////////////////////
#if (_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L)
#define BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
#endif
//////////////////////////////////////////////////////
// _POSIX_SHARED_MEMORY_OBJECTS (POSIX.1b/POSIX.4)
//////////////////////////////////////////////////////
@@ -149,6 +162,14 @@
(defined (_FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))
#define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T
#endif
//////////////////////////////////////////////////////
//posix_fallocate
//////////////////////////////////////////////////////
#if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
#define BOOST_INTERPROCESS_POSIX_FALLOCATE
#endif
#endif //!defined(BOOST_INTERPROCESS_WINDOWS)
#if defined(BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_POSIX_MAPPED_FILES)
@@ -170,6 +191,18 @@
#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
#endif
// Max open or create tries with managed memory segments
#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_MAX_TRIES
#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_MAX_TRIES 20u
#endif
// Maximum timeout in seconds with open or create tries with managed memory segments
// waiting the creator to initialize the shared memory
#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_TIMEOUT_SEC
#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_INITIALIZE_TIMEOUT_SEC 300u
#endif
//Other switches
//BOOST_INTERPROCESS_MSG_QUEUE_USES_CIRC_INDEX
//message queue uses a circular queue as index instead of an array (better performance)
@@ -190,14 +223,40 @@
#define BOOST_INTERPROCESS_FORCEINLINE inline
#elif defined(BOOST_INTERPROCESS_FORCEINLINE_IS_BOOST_FORCELINE)
#define BOOST_INTERPROCESS_FORCEINLINE BOOST_FORCEINLINE
#elif defined(BOOST_MSVC) && defined(_DEBUG)
//"__forceinline" and MSVC seems to have some bugs in debug mode
#elif defined(BOOST_MSVC) && (_MSC_VER < 1900 || defined(_DEBUG))
//"__forceinline" and MSVC seems to have some bugs in old versions and in debug mode
#define BOOST_INTERPROCESS_FORCEINLINE inline
#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
#elif defined(BOOST_GCC) && (__GNUC__ <= 5)
//Older GCCs have problems with forceinline
#define BOOST_INTERPROCESS_FORCEINLINE inline
#else
#define BOOST_INTERPROCESS_FORCEINLINE BOOST_FORCEINLINE
#endif
#ifdef BOOST_WINDOWS
#define BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES
#ifdef __clang__
#define BOOST_INTERPROCESS_DISABLE_DEPRECATED_WARNING _Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
#define BOOST_INTERPROCESS_RESTORE_WARNING _Pragma("clang diagnostic pop")
#else // __clang__
#define BOOST_INTERPROCESS_DISABLE_DEPRECATED_WARNING __pragma(warning(push)) \
__pragma(warning(disable : 4996))
#define BOOST_INTERPROCESS_RESTORE_WARNING __pragma(warning(pop))
#endif // __clang__
#endif
#if defined(BOOST_HAS_THREADS)
# if defined(_MSC_VER) || defined(__MWERKS__) || defined(__MINGW32__) || defined(__BORLANDC__)
//no reentrant posix functions (eg: localtime_r)
# elif (!defined(__hpux) || (defined(__hpux) && defined(_REENTRANT)))
# define BOOST_INTERPROCESS_HAS_REENTRANT_STD_FUNCTIONS
# endif
#endif
#include <boost/core/no_exceptions_support.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP

View File

@@ -34,14 +34,13 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <stdarg.h>
#include <string>
#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
# include <errno.h> //Errors
# include <cerrno> //Errors
# include <cstring> //strerror
# else //ifdef BOOST_HAS_UNISTD_H
# error Unknown platform
@@ -57,7 +56,7 @@ namespace interprocess {
inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
return winapi::get_last_error();
return (int)winapi::get_last_error();
#else
return errno; // GCC 3.1 won't accept ::errno
#endif
@@ -73,7 +72,7 @@ inline void fill_system_message(int sys_err_code, std::string &str)
winapi::format_message_from_system |
winapi::format_message_ignore_inserts,
0,
sys_err_code,
(unsigned long)sys_err_code,
winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language
reinterpret_cast<char *>(&lpMsgBuf),
0,
@@ -124,7 +123,8 @@ enum error_code_t
invalid_argument,
timeout_when_locking_error,
timeout_when_waiting_error,
owner_dead_error
owner_dead_error,
not_recoverable
};
typedef int native_error_t;

View File

@@ -36,17 +36,17 @@ namespace interprocess {
class BOOST_SYMBOL_VISIBLE interprocess_exception : public std::exception
{
public:
interprocess_exception(const char *err)
interprocess_exception(const char *err) BOOST_NOEXCEPT
: m_err(other_error)
{
try { m_str = err; }
catch (...) {}
BOOST_TRY { m_str = err; }
BOOST_CATCH(...) {} BOOST_CATCH_END
}
interprocess_exception(const error_info &err_info, const char *str = 0)
: m_err(err_info)
{
try{
BOOST_TRY{
if(m_err.get_native_error() != 0){
fill_system_message(m_err.get_native_error(), m_str);
}
@@ -57,18 +57,18 @@ class BOOST_SYMBOL_VISIBLE interprocess_exception : public std::exception
m_str = "boost::interprocess_exception::library_error";
}
}
catch(...){}
BOOST_CATCH(...){} BOOST_CATCH_END
}
virtual ~interprocess_exception() BOOST_NOEXCEPT_OR_NOTHROW {}
~interprocess_exception() BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE {}
virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{ return m_str.c_str(); }
native_error_t get_native_error()const { return m_err.get_native_error(); }
native_error_t get_native_error() const BOOST_NOEXCEPT { return m_err.get_native_error(); }
// Note: a value of other_error implies a library (rather than system) error
error_code_t get_error_code() const { return m_err.get_error_code(); }
error_code_t get_error_code() const BOOST_NOEXCEPT { return m_err.get_error_code(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -82,11 +82,11 @@ class BOOST_SYMBOL_VISIBLE interprocess_exception : public std::exception
class BOOST_SYMBOL_VISIBLE lock_exception : public interprocess_exception
{
public:
lock_exception()
: interprocess_exception(lock_error)
lock_exception(error_code_t err = lock_error) BOOST_NOEXCEPT
: interprocess_exception(err)
{}
virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
const char* what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{ return "boost::interprocess::lock_exception"; }
};
@@ -96,9 +96,10 @@ class BOOST_SYMBOL_VISIBLE lock_exception : public interprocess_exception
class BOOST_SYMBOL_VISIBLE bad_alloc : public interprocess_exception
{
public:
bad_alloc() : interprocess_exception("::boost::interprocess::bad_alloc"){}
virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
{ return "boost::interprocess::bad_alloc"; }
bad_alloc() : interprocess_exception("::boost::interprocess::bad_alloc") {}
const char* what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{ return "boost::interprocess::bad_alloc"; }
};
} // namespace interprocess {

View File

@@ -32,8 +32,8 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/simple_swap.hpp>
#include <boost/interprocess/detail/char_wchar_holder.hpp>
#include <boost/move/utility_core.hpp>
#include <string> //std::string
//!\file
//!Describes file_mapping and mapped region classes
@@ -52,7 +52,7 @@ class file_mapping
public:
//!Constructs an empty file mapping.
//!Does not throw
file_mapping();
file_mapping() BOOST_NOEXCEPT;
//!Opens a file mapping of file "filename", starting in offset
//!"file_offset", and the mapping's size will be "size". The mapping
@@ -60,10 +60,21 @@ class file_mapping
//!modes. Throws interprocess_exception on error.
file_mapping(const char *filename, mode_t mode);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Opens a file mapping of file "filename", starting in offset
//!"file_offset", and the mapping's size will be "size". The mapping
//!can be opened for read-only "read_only" or read-write "read_write"
//!modes. Throws interprocess_exception on error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
file_mapping(const wchar_t *filename, mode_t mode);
#endif
//!Moves the ownership of "moved"'s file mapping object to *this.
//!After the call, "moved" does not represent any file mapping object.
//!Does not throw
file_mapping(BOOST_RV_REF(file_mapping) moved)
file_mapping(BOOST_RV_REF(file_mapping) moved) BOOST_NOEXCEPT
: m_handle(file_handle_t(ipcdetail::invalid_file()))
, m_mode(read_only)
{ this->swap(moved); }
@@ -71,7 +82,7 @@ class file_mapping
//!Moves the ownership of "moved"'s file mapping to *this.
//!After the call, "moved" does not represent any file mapping.
//!Does not throw
file_mapping &operator=(BOOST_RV_REF(file_mapping) moved)
file_mapping &operator=(BOOST_RV_REF(file_mapping) moved) BOOST_NOEXCEPT
{
file_mapping tmp(boost::move(moved));
this->swap(tmp);
@@ -80,15 +91,15 @@ class file_mapping
//!Swaps to file_mappings.
//!Does not throw.
void swap(file_mapping &other);
void swap(file_mapping &other) BOOST_NOEXCEPT;
//!Returns access mode
//!used in the constructor
mode_t get_mode() const;
mode_t get_mode() const BOOST_NOEXCEPT;
//!Obtains the mapping handle
//!to be used with mapped_region
mapping_handle_t get_mapping_handle() const;
mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT;
//!Destroys the file mapping. All mapped regions created from this are still
//!valid. Does not throw
@@ -96,7 +107,7 @@ class file_mapping
//!Returns the name of the file
//!used in the constructor.
const char *get_name() const;
const char *get_name() const BOOST_NOEXCEPT;
//!Removes the file named "filename" even if it's been memory mapped.
//!Returns true on success.
@@ -104,17 +115,28 @@ class file_mapping
//!being used other processes and no deletion permission was shared.
static bool remove(const char *filename);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Removes the file named "filename" even if it's been memory mapped.
//!Returns true on success.
//!The function might fail in some operating systems if the file is
//!being used other processes and no deletion permission was shared.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *filename);
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
//!Closes a previously opened file mapping. Never throws.
void priv_close();
file_handle_t m_handle;
mode_t m_mode;
std::string m_filename;
char_wchar_holder m_filename;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
inline file_mapping::file_mapping()
inline file_mapping::file_mapping() BOOST_NOEXCEPT
: m_handle(file_handle_t(ipcdetail::invalid_file()))
, m_mode(read_only)
{}
@@ -122,20 +144,20 @@ inline file_mapping::file_mapping()
inline file_mapping::~file_mapping()
{ this->priv_close(); }
inline const char *file_mapping::get_name() const
{ return m_filename.c_str(); }
inline const char *file_mapping::get_name() const BOOST_NOEXCEPT
{ return m_filename.getn(); }
inline void file_mapping::swap(file_mapping &other)
inline void file_mapping::swap(file_mapping &other) BOOST_NOEXCEPT
{
(simple_swap)(m_handle, other.m_handle);
(simple_swap)(m_mode, other.m_mode);
m_filename.swap(other.m_filename);
}
inline mapping_handle_t file_mapping::get_mapping_handle() const
inline mapping_handle_t file_mapping::get_mapping_handle() const BOOST_NOEXCEPT
{ return ipcdetail::mapping_handle_from_file_handle(m_handle); }
inline mode_t file_mapping::get_mode() const
inline mode_t file_mapping::get_mode() const BOOST_NOEXCEPT
{ return m_mode; }
inline file_mapping::file_mapping
@@ -163,6 +185,35 @@ inline file_mapping::file_mapping
inline bool file_mapping::remove(const char *filename)
{ return ipcdetail::delete_file(filename); }
#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES
inline file_mapping::file_mapping
(const wchar_t *filename, mode_t mode)
: m_filename(filename)
{
//Check accesses
if (mode != read_write && mode != read_only){
error_info err = other_error;
throw interprocess_exception(err);
}
//Open file
m_handle = ipcdetail::open_existing_file(filename, mode);
//Check for error
if(m_handle == ipcdetail::invalid_file()){
error_info err = system_error_code();
this->priv_close();
throw interprocess_exception(err);
}
m_mode = mode;
}
inline bool file_mapping::remove(const wchar_t *filename)
{ return ipcdetail::delete_file(filename); }
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void file_mapping::priv_close()

View File

@@ -161,6 +161,7 @@ class iunordered_set_index
typedef typename index_type::bucket_type bucket_type;
typedef typename index_type::bucket_traits bucket_traits;
typedef typename index_type::size_type size_type;
typedef typename index_type::difference_type difference_type;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -203,7 +204,7 @@ class iunordered_set_index
(boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, buckets);
BOOST_ASSERT(buckets == shunk_p); (void)shunk_p;
bucket_ptr buckets_init = buckets + received_size;
bucket_ptr buckets_init = buckets + difference_type(received_size);
for(size_type i = 0; i < (old_size - received_size); ++i){
to_raw_pointer(buckets_init++)->~bucket_type();
}
@@ -219,7 +220,7 @@ class iunordered_set_index
bucket_ptr ret = alloc.allocation_command
(boost::interprocess::expand_fwd | boost::interprocess::allocate_new, new_num, received_size, reuse);
if(ret == old_buckets){
bucket_ptr buckets_init = old_buckets + old_num;
bucket_ptr buckets_init = old_buckets + difference_type(old_num);
for(size_type i = 0; i < (new_num - old_num); ++i){
::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type();
}
@@ -276,15 +277,15 @@ class iunordered_set_index
new_n = index_type::suggested_upper_bucket_count(new_n);
bucket_ptr new_p;
//This can throw
try{
BOOST_TRY{
if(old_p != bucket_ptr(&this->init_bucket))
new_p = expand_or_create_buckets(old_p, old_n, this->alloc, new_n);
else
new_p = create_buckets(this->alloc, new_n);
}
catch(...){
BOOST_CATCH(...){
return;
}
} BOOST_CATCH_END
//Rehashing does not throw, since neither the hash nor the
//comparison function can throw
this->rehash(bucket_traits(new_p, new_n));
@@ -312,12 +313,12 @@ class iunordered_set_index
if(sug_count >= cur_count)
return;
try{
BOOST_TRY{
shrink_buckets(old_p, cur_count, this->alloc, sug_count);
}
catch(...){
BOOST_CATCH(...){
return;
}
} BOOST_CATCH_END
//Rehashing does not throw, since neither the hash nor the
//comparison function can throw
@@ -340,10 +341,10 @@ class iunordered_set_index
iterator it = index_type::insert_commit(val, commit_data);
size_type cur_size = this->size();
if(cur_size > this->bucket_count()){
try{
BOOST_TRY{
this->reserve(cur_size);
}
catch(...){
BOOST_CATCH(...){
//Strong guarantee: if something goes wrong
//we should remove the insertion.
//
@@ -352,8 +353,8 @@ class iunordered_set_index
//throw only because of the memory allocation:
//the iterator has not been invalidated.
index_type::erase(it);
throw;
}
BOOST_RETHROW
} BOOST_CATCH_END
}
return it;
}

View File

@@ -28,6 +28,7 @@
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
#include <boost/interprocess/offset_ptr.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -37,6 +38,7 @@
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/move/detail/type_traits.hpp> //make_unsigned, alignment_of
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/move/detail/force_ptr.hpp>
#include <boost/assert.hpp>
#include <algorithm> //std::lower_bound
#include <cstddef> //std::size_t
@@ -54,16 +56,18 @@ namespace ipcdetail
{
template<class VoidPointer>
class msg_queue_initialization_func_t;
}
//Blocking modes
enum mqblock_types { blocking, timed, non_blocking };
//!A class that allows sending messages
//!between processes.
template<class VoidPointer>
class message_queue_t
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Blocking modes
enum block_t { blocking, timed, non_blocking };
message_queue_t();
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -79,7 +83,7 @@ class message_queue_t
//!Creates a process shared message queue with name "name". For this message queue,
//!the maximum number of messages will be "max_num_msg" and the maximum message size
//!will be "max_msg_size". Throws on error and if the queue was previously created.
message_queue_t(create_only_t create_only,
message_queue_t(create_only_t,
const char *name,
size_type max_num_msg,
size_type max_msg_size,
@@ -90,7 +94,7 @@ class message_queue_t
//!and the maximum message size will be "max_msg_size". If queue was previously
//!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters
//!are ignored. Throws on error.
message_queue_t(open_or_create_t open_or_create,
message_queue_t(open_or_create_t,
const char *name,
size_type max_num_msg,
size_type max_msg_size,
@@ -99,8 +103,45 @@ class message_queue_t
//!Opens a previously created process shared message queue with name "name".
//!If the queue was not previously created or there are no free resources,
//!throws an error.
message_queue_t(open_only_t open_only,
const char *name);
message_queue_t(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a process shared message queue with name "name". For this message queue,
//!the maximum number of messages will be "max_num_msg" and the maximum message size
//!will be "max_msg_size". Throws on error and if the queue was previously created.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
message_queue_t(create_only_t,
const wchar_t *name,
size_type max_num_msg,
size_type max_msg_size,
const permissions &perm = permissions());
//!Opens or creates a process shared message queue with name "name".
//!If the queue is created, the maximum number of messages will be "max_num_msg"
//!and the maximum message size will be "max_msg_size". If queue was previously
//!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters
//!are ignored. Throws on error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
message_queue_t(open_or_create_t,
const wchar_t *name,
size_type max_num_msg,
size_type max_msg_size,
const permissions &perm = permissions());
//!Opens a previously created process shared message queue with name "name".
//!If the queue was not previously created or there are no free resources,
//!throws an error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
message_queue_t(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. All opened message queues are still
@@ -129,8 +170,9 @@ class message_queue_t
//!the sender retries until time "abs_time" is reached. Returns true if
//!the message has been successfully sent. Returns false if timeout is reached.
//!Throws interprocess_error on error.
template<class TimePoint>
bool timed_send (const void *buffer, size_type buffer_size,
unsigned int priority, const boost::posix_time::ptime& abs_time);
unsigned int priority, const TimePoint& abs_time);
//!Receives a message from the message queue. The message is stored in buffer
//!"buffer", which has size "buffer_size". The received message has size
@@ -153,9 +195,10 @@ class message_queue_t
//!the receiver retries until time "abs_time" is reached. Returns true if
//!the message has been successfully sent. Returns false if timeout is reached.
//!Throws interprocess_error on error.
template<class TimePoint>
bool timed_receive (void *buffer, size_type buffer_size,
size_type &recvd_size,unsigned int &priority,
const boost::posix_time::ptime &abs_time);
const TimePoint &abs_time);
//!Returns the maximum number of messages allowed by the queue. The message
//!queue must be opened or created previously. Otherwise, returns 0.
@@ -175,26 +218,45 @@ class message_queue_t
//!Returns false on error. Never throws
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Removes the message queue from the system.
//!Returns false on error. Never throws
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef boost::posix_time::ptime ptime;
friend class ipcdetail::msg_queue_initialization_func_t<VoidPointer>;
bool do_receive(block_t block,
void *buffer, size_type buffer_size,
template<mqblock_types Block, class TimePoint>
bool do_receive(void *buffer, size_type buffer_size,
size_type &recvd_size, unsigned int &priority,
const ptime &abs_time);
const TimePoint &abs_time);
bool do_send(block_t block,
const void *buffer, size_type buffer_size,
unsigned int priority, const ptime &abs_time);
template<mqblock_types Block, class TimePoint>
bool do_send(const void *buffer, size_type buffer_size,
unsigned int priority, const TimePoint &abs_time);
//!Returns the needed memory size for the shared message queue.
//!Never throws
static size_type get_mem_size(size_type max_msg_size, size_type max_num_msg);
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
open_create_impl_t m_shmem;
template<class Lock, class TimePoint>
static bool do_cond_wait(ipcdetail::bool_<true>, interprocess_condition &cond, Lock &lock, const TimePoint &abs_time)
{ return cond.timed_wait(lock, abs_time); }
template<class Lock, class TimePoint>
static bool do_cond_wait(ipcdetail::bool_<false>, interprocess_condition &cond, Lock &lock, const TimePoint &)
{ cond.wait(lock); return true; }
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
@@ -346,24 +408,24 @@ class mq_hdr_t
msg_header &top_msg()
{
size_type pos = this->end_pos();
return *mp_index[pos ? --pos : m_max_num_msg - 1];
return *mp_index[difference_type(pos ? --pos : m_max_num_msg - 1)];
}
//!Returns the inserted message with bottom priority
msg_header &bottom_msg()
{ return *mp_index[m_cur_first_msg]; }
{ return *mp_index[difference_type(m_cur_first_msg)]; }
iterator inserted_ptr_begin() const
{ return &mp_index[m_cur_first_msg]; }
{ return &mp_index[difference_type(m_cur_first_msg)]; }
iterator inserted_ptr_end() const
{ return &mp_index[this->end_pos()]; }
{ return &mp_index[difference_type(this->end_pos())]; }
iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func)
{
iterator begin(this->inserted_ptr_begin()), end(this->inserted_ptr_end());
if(end < begin){
iterator idx_end = &mp_index[m_max_num_msg];
iterator idx_end = &mp_index[difference_type(m_max_num_msg)];
iterator ret = std::lower_bound(begin, idx_end, value, func);
if(idx_end == ret){
iterator idx_beg = &mp_index[0];
@@ -391,14 +453,14 @@ class mq_hdr_t
m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg;
--m_cur_first_msg;
++m_cur_num_msg;
return *mp_index[m_cur_first_msg];
return *mp_index[difference_type(m_cur_first_msg)];
}
else if(where == it_inserted_ptr_end){
++m_cur_num_msg;
return **it_inserted_ptr_end;
}
else{
size_type pos = where - &mp_index[0];
size_type pos = size_type(where - &mp_index[0]);
size_type circ_pos = pos >= m_cur_first_msg ? pos - m_cur_first_msg : pos + (m_max_num_msg - m_cur_first_msg);
//Check if it's more efficient to move back or move front
if(circ_pos < m_cur_num_msg/2){
@@ -406,7 +468,7 @@ class mq_hdr_t
//indicates two step insertion
if(!pos){
pos = m_max_num_msg;
where = &mp_index[m_max_num_msg-1];
where = &mp_index[difference_type(m_max_num_msg-1u)];
}
else{
--where;
@@ -423,7 +485,7 @@ class mq_hdr_t
std::copy( &mp_index[0] + second_segment_beg
, &mp_index[0] + second_segment_end
, &mp_index[0] + second_segment_beg - 1);
mp_index[m_max_num_msg-1] = mp_index[0];
mp_index[difference_type(m_max_num_msg-1u)] = mp_index[0];
}
std::copy( &mp_index[0] + first_segment_beg
, &mp_index[0] + first_segment_end
@@ -449,12 +511,12 @@ class mq_hdr_t
if(!unique_segment){
std::copy_backward( &mp_index[0] + second_segment_beg
, &mp_index[0] + second_segment_end
, &mp_index[0] + second_segment_end + 1);
mp_index[0] = mp_index[m_max_num_msg-1];
, &mp_index[0] + second_segment_end + 1u);
mp_index[0] = mp_index[difference_type(m_max_num_msg-1u)];
}
std::copy_backward( &mp_index[0] + first_segment_beg
, &mp_index[0] + first_segment_end
, &mp_index[0] + first_segment_end + 1);
, &mp_index[0] + first_segment_end + 1u);
*where = backup;
++m_cur_num_msg;
return **where;
@@ -468,7 +530,7 @@ class mq_hdr_t
//!Returns the inserted message with top priority
msg_header &top_msg()
{ return *mp_index[m_cur_num_msg-1]; }
{ return *mp_index[difference_type(m_cur_num_msg-1u)]; }
//!Returns the inserted message with bottom priority
msg_header &bottom_msg()
@@ -478,7 +540,7 @@ class mq_hdr_t
{ return &mp_index[0]; }
iterator inserted_ptr_end() const
{ return &mp_index[m_cur_num_msg]; }
{ return &mp_index[difference_type(m_cur_num_msg)]; }
iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func)
{ return std::lower_bound(this->inserted_ptr_begin(), this->inserted_ptr_end(), value, func); }
@@ -550,11 +612,11 @@ class mq_hdr_t
r_max_msg_size = ipcdetail::get_rounded_size<size_type>(m_max_msg_size, msg_hdr_align) + sizeof(msg_header);
//Pointer to the index
msg_hdr_ptr_t *index = reinterpret_cast<msg_hdr_ptr_t*>
msg_hdr_ptr_t *index = move_detail::force_ptr<msg_hdr_ptr_t*>
(reinterpret_cast<char*>(this)+r_hdr_size);
//Pointer to the first message header
msg_header *msg_hdr = reinterpret_cast<msg_header*>
msg_header *msg_hdr = move_detail::force_ptr<msg_header*>
(reinterpret_cast<char*>(this)+r_hdr_size+r_index_size);
//Initialize the pointer to the index
@@ -563,7 +625,7 @@ class mq_hdr_t
//Initialize the index so each slot points to a preallocated message
for(size_type i = 0; i < m_max_num_msg; ++i){
index[i] = msg_hdr;
msg_hdr = reinterpret_cast<msg_header*>
msg_hdr = move_detail::force_ptr<msg_header*>
(reinterpret_cast<char*>(msg_hdr)+r_max_msg_size);
}
}
@@ -622,8 +684,7 @@ class msg_queue_initialization_func_t
}
BOOST_CATCH(...){
return false;
}
BOOST_CATCH_END
} BOOST_CATCH_END
}
return true;
}
@@ -694,32 +755,83 @@ inline message_queue_t<VoidPointer>::message_queue_t(open_only_t, const char *na
ipcdetail::msg_queue_initialization_func_t<VoidPointer> ())
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class VoidPointer>
inline message_queue_t<VoidPointer>::message_queue_t(create_only_t,
const wchar_t *name,
size_type max_num_msg,
size_type max_msg_size,
const permissions &perm)
//Create shared memory and execute functor atomically
: m_shmem(create_only,
name,
get_mem_size(max_msg_size, max_num_msg),
read_write,
static_cast<void*>(0),
//Prepare initialization functor
ipcdetail::msg_queue_initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
perm)
{}
template<class VoidPointer>
inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t,
const wchar_t *name,
size_type max_num_msg,
size_type max_msg_size,
const permissions &perm)
//Create shared memory and execute functor atomically
: m_shmem(open_or_create,
name,
get_mem_size(max_msg_size, max_num_msg),
read_write,
static_cast<void*>(0),
//Prepare initialization functor
ipcdetail::msg_queue_initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
perm)
{}
template<class VoidPointer>
inline message_queue_t<VoidPointer>::message_queue_t(open_only_t, const wchar_t *name)
//Create shared memory and execute functor atomically
: m_shmem(open_only,
name,
read_write,
static_cast<void*>(0),
//Prepare initialization functor
ipcdetail::msg_queue_initialization_func_t<VoidPointer> ())
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class VoidPointer>
inline void message_queue_t<VoidPointer>::send
(const void *buffer, size_type buffer_size, unsigned int priority)
{ this->do_send(blocking, buffer, buffer_size, priority, ptime()); }
{ this->do_send<blocking>(buffer, buffer_size, priority, 0); }
template<class VoidPointer>
inline bool message_queue_t<VoidPointer>::try_send
(const void *buffer, size_type buffer_size, unsigned int priority)
{ return this->do_send(non_blocking, buffer, buffer_size, priority, ptime()); }
{ return this->do_send<non_blocking>(buffer, buffer_size, priority, 0); }
template<class VoidPointer>
template<class TimePoint>
inline bool message_queue_t<VoidPointer>::timed_send
(const void *buffer, size_type buffer_size
,unsigned int priority, const boost::posix_time::ptime &abs_time)
,unsigned int priority, const TimePoint &abs_time)
{
if(abs_time == boost::posix_time::pos_infin){
if(ipcdetail::is_pos_infinity(abs_time)){
this->send(buffer, buffer_size, priority);
return true;
}
return this->do_send(timed, buffer, buffer_size, priority, abs_time);
return this->do_send<timed>(buffer, buffer_size, priority, abs_time);
}
template<class VoidPointer>
inline bool message_queue_t<VoidPointer>::do_send(block_t block,
template<mqblock_types Block, class TimePoint>
inline bool message_queue_t<VoidPointer>::do_send(
const void *buffer, size_type buffer_size,
unsigned int priority, const boost::posix_time::ptime &abs_time)
unsigned int priority, const TimePoint &abs_time)
{
ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
//Check if buffer is smaller than maximum allowed
@@ -740,7 +852,7 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block,
#ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
++p_hdr->m_blocked_senders;
#endif
switch(block){
switch(Block){
case non_blocking :
#ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
--p_hdr->m_blocked_senders;
@@ -750,14 +862,14 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block,
case blocking :
do{
p_hdr->m_cond_send.wait(lock);
(void)do_cond_wait(ipcdetail::bool_<false>(), p_hdr->m_cond_send, lock, abs_time);
}
while (p_hdr->is_full());
break;
case timed :
do{
if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){
if(!do_cond_wait(ipcdetail::bool_<Block == timed>(), p_hdr->m_cond_send, lock, abs_time)) {
if(p_hdr->is_full()){
#ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
--p_hdr->m_blocked_senders;
@@ -781,8 +893,7 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block,
--p_hdr->m_blocked_senders;
#endif
BOOST_RETHROW;
}
BOOST_CATCH_END
} BOOST_CATCH_END
}
#if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
@@ -820,33 +931,35 @@ inline bool message_queue_t<VoidPointer>::do_send(block_t block,
template<class VoidPointer>
inline void message_queue_t<VoidPointer>::receive(void *buffer, size_type buffer_size,
size_type &recvd_size, unsigned int &priority)
{ this->do_receive(blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
{ this->do_receive<blocking>(buffer, buffer_size, recvd_size, priority, 0); }
template<class VoidPointer>
inline bool
message_queue_t<VoidPointer>::try_receive(void *buffer, size_type buffer_size,
size_type &recvd_size, unsigned int &priority)
{ return this->do_receive(non_blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
{ return this->do_receive<non_blocking>(buffer, buffer_size, recvd_size, priority, 0); }
template<class VoidPointer>
template<class TimePoint>
inline bool
message_queue_t<VoidPointer>::timed_receive(void *buffer, size_type buffer_size,
size_type &recvd_size, unsigned int &priority,
const boost::posix_time::ptime &abs_time)
const TimePoint &abs_time)
{
if(abs_time == boost::posix_time::pos_infin){
if(ipcdetail::is_pos_infinity(abs_time)){
this->receive(buffer, buffer_size, recvd_size, priority);
return true;
}
return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time);
return this->do_receive<timed>(buffer, buffer_size, recvd_size, priority, abs_time);
}
template<class VoidPointer>
template<mqblock_types Block, class TimePoint>
inline bool
message_queue_t<VoidPointer>::do_receive(block_t block,
message_queue_t<VoidPointer>::do_receive(
void *buffer, size_type buffer_size,
size_type &recvd_size, unsigned int &priority,
const boost::posix_time::ptime &abs_time)
const TimePoint &abs_time)
{
ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
//Check if buffer is big enough for any message
@@ -867,7 +980,7 @@ inline bool
#if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
++p_hdr->m_blocked_receivers;
#endif
switch(block){
switch(Block){
case non_blocking :
#if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
--p_hdr->m_blocked_receivers;
@@ -877,14 +990,14 @@ inline bool
case blocking :
do{
p_hdr->m_cond_recv.wait(lock);
(void)do_cond_wait(ipcdetail::bool_<false>(), p_hdr->m_cond_recv, lock, abs_time);
}
while (p_hdr->is_empty());
break;
case timed :
do{
if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){
if(!do_cond_wait(ipcdetail::bool_<Block == timed>(), p_hdr->m_cond_recv, lock, abs_time)) {
if(p_hdr->is_empty()){
#if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
--p_hdr->m_blocked_receivers;
@@ -910,8 +1023,7 @@ inline bool
--p_hdr->m_blocked_receivers;
#endif
BOOST_RETHROW;
}
BOOST_CATCH_END
} BOOST_CATCH_END
}
#ifdef BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
@@ -981,6 +1093,14 @@ template<class VoidPointer>
inline bool message_queue_t<VoidPointer>::remove(const char *name)
{ return shared_memory_object::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
template<class VoidPointer>
inline bool message_queue_t<VoidPointer>::remove(const wchar_t *name)
{ return shared_memory_object::remove(name); }
#endif
#else
//!Typedef for a default message queue

View File

@@ -60,10 +60,13 @@ class basic_managed_external_buffer
//!Default constructor. Does nothing.
//!Useful in combination with move semantics
basic_managed_external_buffer()
basic_managed_external_buffer() BOOST_NOEXCEPT
{}
//!Creates and places the segment manager. This can throw
//!The external memory supplied by the user shall be aligned to the maximum value between
//!`alignof(std::max_align_t)` and the strictest alignment of any over-aligned type to be built
//!inside that memory.
basic_managed_external_buffer
(create_only_t, void *addr, size_type size)
{
@@ -75,6 +78,9 @@ class basic_managed_external_buffer
}
//!Creates and places the segment manager. This can throw
//!The external memory supplied by the user shall be aligned to the maximum value between
//!`alignof(std::max_align_t)` and the strictest alignment of any over-aligned type to be built
//!inside that memory.
basic_managed_external_buffer
(open_only_t, void *addr, size_type size)
{
@@ -86,13 +92,13 @@ class basic_managed_external_buffer
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
basic_managed_external_buffer(BOOST_RV_REF(basic_managed_external_buffer) moved)
basic_managed_external_buffer(BOOST_RV_REF(basic_managed_external_buffer) moved) BOOST_NOEXCEPT
{
this->swap(moved);
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
basic_managed_external_buffer &operator=(BOOST_RV_REF(basic_managed_external_buffer) moved)
basic_managed_external_buffer &operator=(BOOST_RV_REF(basic_managed_external_buffer) moved) BOOST_NOEXCEPT
{
basic_managed_external_buffer tmp(boost::move(moved));
this->swap(tmp);
@@ -104,7 +110,7 @@ class basic_managed_external_buffer
//!Swaps the ownership of the managed heap memories managed by *this and other.
//!Never throws.
void swap(basic_managed_external_buffer &other)
void swap(basic_managed_external_buffer &other) BOOST_NOEXCEPT
{ base_t::swap(other); }
};

View File

@@ -63,7 +63,8 @@ class basic_managed_heap_memory
//!Default constructor. Does nothing.
//!Useful in combination with move semantics
basic_managed_heap_memory(){}
basic_managed_heap_memory() BOOST_NOEXCEPT
{}
//!Destructor. Liberates the heap memory holding the managed data.
//!Never throws.
@@ -82,11 +83,11 @@ class basic_managed_heap_memory
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
basic_managed_heap_memory(BOOST_RV_REF(basic_managed_heap_memory) moved)
basic_managed_heap_memory(BOOST_RV_REF(basic_managed_heap_memory) moved) BOOST_NOEXCEPT
{ this->swap(moved); }
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
basic_managed_heap_memory &operator=(BOOST_RV_REF(basic_managed_heap_memory) moved)
basic_managed_heap_memory &operator=(BOOST_RV_REF(basic_managed_heap_memory) moved) BOOST_NOEXCEPT
{
basic_managed_heap_memory tmp(boost::move(moved));
this->swap(tmp);
@@ -123,7 +124,7 @@ class basic_managed_heap_memory
//!Swaps the ownership of the managed heap memories managed by *this and other.
//!Never throws.
void swap(basic_managed_heap_memory &other)
void swap(basic_managed_heap_memory &other) BOOST_NOEXCEPT
{
base_t::swap(other);
m_heapmem.swap(other.m_heapmem);

View File

@@ -38,11 +38,29 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
template<class AllocationAlgorithm>
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct mfile_open_or_create
{
static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of
< segment_manager
< CharType
, AllocationAlgorithm
, IndexType>
>::value;
static const std::size_t final_segment_manager_alignment
= segment_manager_alignment > AllocationAlgorithm::Alignment
? segment_manager_alignment : AllocationAlgorithm::Alignment;
typedef ipcdetail::managed_open_or_create_impl
< file_wrapper, AllocationAlgorithm::Alignment, true, false> type;
< file_wrapper
, final_segment_manager_alignment
, true
, false> type;
};
} //namespace ipcdetail {
@@ -59,15 +77,17 @@ template
class basic_managed_mapped_file
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
: public ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
,ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
< CharType, AllocationAlgorithm, IndexType
, ipcdetail::mfile_open_or_create
<CharType, AllocationAlgorithm, IndexType>::type::ManagedOpenOrCreateUserOffset>
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
public:
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t;
ipcdetail::mfile_open_or_create<CharType, AllocationAlgorithm, IndexType>
::type::ManagedOpenOrCreateUserOffset> base_t;
typedef ipcdetail::file_wrapper device_type;
private:
@@ -90,7 +110,7 @@ class basic_managed_mapped_file
//!Creates mapped file and creates and places the segment manager.
//!This can throw.
basic_managed_mapped_file()
basic_managed_mapped_file() BOOST_NOEXCEPT
{}
//!Creates mapped file and creates and places the segment manager.
@@ -142,16 +162,84 @@ class basic_managed_mapped_file
ipcdetail::DoOpen))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates mapped file and creates and places the segment manager.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_mapped_file(create_only_t, const wchar_t *name,
size_type size, const void *addr = 0, const permissions &perm = permissions())
: m_mfile(create_only, name, size, read_write, addr,
create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm)
{}
//!Creates mapped file and creates and places the segment manager if
//!segment was not created. If segment was created it connects to the
//!segment.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_mapped_file (open_or_create_t,
const wchar_t *name, size_type size,
const void *addr = 0, const permissions &perm = permissions())
: m_mfile(open_or_create, name, size, read_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpenOrCreate), perm)
{}
//!Connects to a created mapped file and its segment manager.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_mapped_file (open_only_t, const wchar_t* name,
const void *addr = 0)
: m_mfile(open_only, name, read_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
{}
//!Connects to a created mapped file and its segment manager
//!in copy_on_write mode.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_mapped_file (open_copy_on_write_t, const wchar_t* name,
const void *addr = 0)
: m_mfile(open_only, name, copy_on_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
{}
//!Connects to a created mapped file and its segment manager
//!in read-only mode.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_mapped_file (open_read_only_t, const wchar_t* name,
const void *addr = 0)
: m_mfile(open_only, name, read_only, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_mapped_file(BOOST_RV_REF(basic_managed_mapped_file) moved)
basic_managed_mapped_file(BOOST_RV_REF(basic_managed_mapped_file) moved) BOOST_NOEXCEPT
{
this->swap(moved);
}
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_mapped_file &operator=(BOOST_RV_REF(basic_managed_mapped_file) moved)
basic_managed_mapped_file &operator=(BOOST_RV_REF(basic_managed_mapped_file) moved) BOOST_NOEXCEPT
{
basic_managed_mapped_file tmp(boost::move(moved));
this->swap(tmp);
@@ -169,7 +257,7 @@ class basic_managed_mapped_file
//!Swaps the ownership of the managed mapped memories managed by *this and other.
//!Never throws.
void swap(basic_managed_mapped_file &other)
void swap(basic_managed_mapped_file &other) BOOST_NOEXCEPT
{
base_t::swap(other);
m_mfile.swap(other.m_mfile);
@@ -201,6 +289,37 @@ class basic_managed_mapped_file
<basic_managed_mapped_file>(filename);
}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to resize mapped file so that we have room for
//!more objects.
//!
//!This function is not synchronized so no other thread or process should
//!be reading or writing the file
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool grow(const wchar_t *filename, size_type extra_bytes)
{
return base_t::template grow
<basic_managed_mapped_file>(filename, extra_bytes);
}
//!Tries to resize mapped file to minimized the size of the file.
//!
//!This function is not synchronized so no other thread or process should
//!be reading or writing the file
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool shrink_to_fit(const wchar_t *filename)
{
return base_t::template shrink_to_fit
<basic_managed_mapped_file>(filename);
}
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to find a previous named allocation address. Returns a memory
@@ -218,7 +337,8 @@ class basic_managed_mapped_file
}
private:
typename ipcdetail::mfile_open_or_create<AllocationAlgorithm>::type m_mfile;
typename ipcdetail::mfile_open_or_create
<CharType, AllocationAlgorithm, IndexType>::type m_mfile;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};

View File

@@ -37,11 +37,29 @@ namespace interprocess {
namespace ipcdetail {
template<class AllocationAlgorithm>
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct shmem_open_or_create
{
typedef ipcdetail::managed_open_or_create_impl
< shared_memory_object, AllocationAlgorithm::Alignment, true, false> type;
static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of
< segment_manager
< CharType
, AllocationAlgorithm
, IndexType>
>::value;
static const std::size_t final_segment_manager_alignment
= segment_manager_alignment > AllocationAlgorithm::Alignment
? segment_manager_alignment : AllocationAlgorithm::Alignment;
typedef ipcdetail::managed_open_or_create_impl
< shared_memory_object
, final_segment_manager_alignment
, true
, false> type;
};
} //namespace ipcdetail {
@@ -57,15 +75,18 @@ template
>
class basic_managed_shared_memory
: public ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
,ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
, private ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type
< CharType, AllocationAlgorithm, IndexType
, ipcdetail::shmem_open_or_create<CharType, AllocationAlgorithm, IndexType>::type::ManagedOpenOrCreateUserOffset>
, private ipcdetail::shmem_open_or_create<CharType, AllocationAlgorithm, IndexType>::type
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef typename ipcdetail::shmem_open_or_create
< CharType
, AllocationAlgorithm
, IndexType>::type base2_t;
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t;
typedef typename ipcdetail::shmem_open_or_create<AllocationAlgorithm>::type base2_t;
base2_t::ManagedOpenOrCreateUserOffset> base_t;
typedef ipcdetail::create_open_func<base_t> create_open_func_t;
@@ -151,6 +172,79 @@ class basic_managed_shared_memory
ipcdetail::DoOpen))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates shared memory and creates and places the segment manager.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_shared_memory(create_only_t, const wchar_t *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(), ipcdetail::DoCreate), perm)
{}
//!Creates shared memory and creates and places the segment manager if
//!segment was not created. If segment was created it connects to the
//!segment.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_shared_memory (open_or_create_t,
const wchar_t *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(),
ipcdetail::DoOpenOrCreate), perm)
{}
//!Connects to a created shared memory and its segment manager.
//!in copy_on_write mode.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_shared_memory (open_copy_on_write_t, const wchar_t* name,
const void *addr = 0)
: base_t()
, base2_t(open_only, name, copy_on_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
{}
//!Connects to a created shared memory and its segment manager.
//!in read-only mode.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_shared_memory (open_read_only_t, const wchar_t* name,
const void *addr = 0)
: base_t()
, base2_t(open_only, name, read_only, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
{}
//!Connects to a created shared memory and its segment manager.
//!This can throw.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
basic_managed_shared_memory (open_only_t, const wchar_t* name,
const void *addr = 0)
: base_t()
, base2_t(open_only, name, read_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_shared_memory(BOOST_RV_REF(basic_managed_shared_memory) moved)
@@ -197,6 +291,38 @@ class basic_managed_shared_memory
return base_t::template shrink_to_fit
<basic_managed_shared_memory>(shmname);
}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to resize the managed shared memory object so that we have
//!room for more objects.
//!
//!This function is not synchronized so no other thread or process should
//!be reading or writing the file
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool grow(const wchar_t *shmname, size_type extra_bytes)
{
return base_t::template grow
<basic_managed_shared_memory>(shmname, extra_bytes);
}
//!Tries to resize the managed shared memory to minimized the size of the file.
//!
//!This function is not synchronized so no other thread or process should
//!be reading or writing the file
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool shrink_to_fit(const wchar_t *shmname)
{
return base_t::template shrink_to_fit
<basic_managed_shared_memory>(shmname);
}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Tries to find a previous named allocation address. Returns a memory

View File

@@ -38,13 +38,32 @@ namespace interprocess {
namespace ipcdetail {
template<class AllocationAlgorithm>
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct wshmem_open_or_create
{
static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of
< segment_manager
< CharType
, AllocationAlgorithm
, IndexType>
>::value;
static const std::size_t final_segment_manager_alignment
= segment_manager_alignment > AllocationAlgorithm::Alignment
? segment_manager_alignment : AllocationAlgorithm::Alignment;
typedef ipcdetail::managed_open_or_create_impl
< windows_shared_memory, AllocationAlgorithm::Alignment, false, false> type;
< windows_shared_memory
, final_segment_manager_alignment
, false
, false> type;
};
} //namespace ipcdetail {
//!A basic managed windows shared memory creation class. Initializes the
@@ -67,13 +86,15 @@ template
class basic_managed_windows_shared_memory
: public ipcdetail::basic_managed_memory_impl
< CharType, AllocationAlgorithm, IndexType
, ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
, ipcdetail::wshmem_open_or_create
<CharType, AllocationAlgorithm, IndexType>::type::ManagedOpenOrCreateUserOffset>
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t;
< CharType, AllocationAlgorithm, IndexType
, ipcdetail::wshmem_open_or_create
<CharType, AllocationAlgorithm, IndexType>::type::ManagedOpenOrCreateUserOffset> base_t;
typedef ipcdetail::create_open_func<base_t> create_open_func_t;
basic_managed_windows_shared_memory *get_this_pointer()
@@ -89,7 +110,7 @@ class basic_managed_windows_shared_memory
//!Default constructor. Does nothing.
//!Useful in combination with move semantics
basic_managed_windows_shared_memory()
basic_managed_windows_shared_memory() BOOST_NOEXCEPT
{}
//!Creates shared memory and creates and places the segment manager.
@@ -143,15 +164,57 @@ class basic_managed_windows_shared_memory
create_open_func_t(get_this_pointer(), ipcdetail::DoOpen))
{}
//!Creates shared memory and creates and places the segment manager if
//!segment was not created. If segment was created it connects to the
//!segment.
//!This can throw.
basic_managed_windows_shared_memory
(open_or_create_t,
const wchar_t *name, size_type size,
const void *addr = 0,
const permissions &perm = permissions())
: m_wshm(open_or_create, name, size, read_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpenOrCreate), perm)
{}
//!Connects to a created shared memory and its segment manager.
//!This can throw.
basic_managed_windows_shared_memory
(open_only_t, const wchar_t* name, const void *addr = 0)
: m_wshm(open_only, name, read_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpen))
{}
//!Connects to a created shared memory and its segment manager
//!in copy_on_write mode.
//!This can throw.
basic_managed_windows_shared_memory
(open_copy_on_write_t, const wchar_t* name, const void *addr = 0)
: m_wshm(open_only, name, copy_on_write, addr,
create_open_func_t(get_this_pointer(), ipcdetail::DoOpen))
{}
//!Connects to a created shared memory and its segment manager
//!in read-only mode.
//!This can throw.
basic_managed_windows_shared_memory
(open_read_only_t, const wchar_t* name, const void *addr = 0)
: base_t()
, m_wshm(open_only, name, read_only, addr,
create_open_func_t(get_this_pointer(), ipcdetail::DoOpen))
{}
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_windows_shared_memory
(BOOST_RV_REF(basic_managed_windows_shared_memory) moved)
(BOOST_RV_REF(basic_managed_windows_shared_memory) moved) BOOST_NOEXCEPT
{ this->swap(moved); }
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_windows_shared_memory &operator=(BOOST_RV_REF(basic_managed_windows_shared_memory) moved)
basic_managed_windows_shared_memory &operator=(BOOST_RV_REF(basic_managed_windows_shared_memory) moved) BOOST_NOEXCEPT
{
basic_managed_windows_shared_memory tmp(boost::move(moved));
this->swap(tmp);
@@ -168,7 +231,7 @@ class basic_managed_windows_shared_memory
//!Swaps the ownership of the managed mapped memories managed by *this and other.
//!Never throws.
void swap(basic_managed_windows_shared_memory &other)
void swap(basic_managed_windows_shared_memory &other) BOOST_NOEXCEPT
{
base_t::swap(other);
m_wshm.swap(other.m_wshm);
@@ -191,7 +254,8 @@ class basic_managed_windows_shared_memory
}
private:
typename ipcdetail::wshmem_open_or_create<AllocationAlgorithm>::type m_wshm;
typename ipcdetail::wshmem_open_or_create
<CharType, AllocationAlgorithm, IndexType>::type m_wshm;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};

View File

@@ -42,13 +42,32 @@ namespace interprocess {
namespace ipcdetail {
template<class AllocationAlgorithm>
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
struct xsishmem_open_or_create
{
typedef ipcdetail::managed_open_or_create_impl //!FileBased, StoreDevice
< xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true> type;
static const std::size_t segment_manager_alignment = boost::move_detail::alignment_of
< segment_manager
< CharType
, AllocationAlgorithm
, IndexType>
>::value;
static const std::size_t final_segment_manager_alignment
= segment_manager_alignment > AllocationAlgorithm::Alignment
? segment_manager_alignment : AllocationAlgorithm::Alignment;
typedef ipcdetail::managed_open_or_create_impl
< xsi_shared_memory_file_wrapper
, final_segment_manager_alignment
, false
, true> type;
};
} //namespace ipcdetail {
//!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the
@@ -63,18 +82,21 @@ template
class basic_managed_xsi_shared_memory
: public ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
,ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
, private ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type
,ipcdetail::xsishmem_open_or_create<CharType, AllocationAlgorithm, IndexType>
::type::ManagedOpenOrCreateUserOffset>
, private ipcdetail::xsishmem_open_or_create
<CharType, AllocationAlgorithm, IndexType>::type
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
public:
typedef xsi_shared_memory_file_wrapper device_type;
public:
typedef typename ipcdetail::xsishmem_open_or_create<AllocationAlgorithm>::type base2_t;
typedef typename ipcdetail::xsishmem_open_or_create
<CharType, AllocationAlgorithm, IndexType>::type base2_t;
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
base2_t::ManagedOpenOrCreateUserOffset> base_t;
base2_t::ManagedOpenOrCreateUserOffset> base_t;
typedef ipcdetail::create_open_func<base_t> create_open_func_t;
@@ -100,7 +122,7 @@ class basic_managed_xsi_shared_memory
//!Default constructor. Does nothing.
//!Useful in combination with move semantics
basic_managed_xsi_shared_memory()
basic_managed_xsi_shared_memory() BOOST_NOEXCEPT
{}
//!Creates shared memory and creates and places the segment manager.
@@ -148,7 +170,7 @@ class basic_managed_xsi_shared_memory
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_xsi_shared_memory(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved)
basic_managed_xsi_shared_memory(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved) BOOST_NOEXCEPT
{
basic_managed_xsi_shared_memory tmp;
this->swap(moved);
@@ -157,7 +179,7 @@ class basic_managed_xsi_shared_memory
//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_xsi_shared_memory &operator=(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved)
basic_managed_xsi_shared_memory &operator=(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved) BOOST_NOEXCEPT
{
basic_managed_xsi_shared_memory tmp(boost::move(moved));
this->swap(tmp);
@@ -166,7 +188,7 @@ class basic_managed_xsi_shared_memory
//!Swaps the ownership of the managed shared memories managed by *this and other.
//!Never throws.
void swap(basic_managed_xsi_shared_memory &other)
void swap(basic_managed_xsi_shared_memory &other) BOOST_NOEXCEPT
{
base_t::swap(other);
base2_t::swap(other);
@@ -178,7 +200,7 @@ class basic_managed_xsi_shared_memory
static bool remove(int shmid)
{ return device_type::remove(shmid); }
int get_shmid() const
int get_shmid() const BOOST_NOEXCEPT
{ return base2_t::get_device().get_shmid(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

View File

@@ -47,7 +47,6 @@
#if defined (BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
# include <boost/interprocess/sync/windows/sync_utils.hpp>
#else
# ifdef BOOST_HAS_UNISTD_H
# include <fcntl.h>
@@ -136,11 +135,11 @@ class mapped_region
//!Default constructor. Address will be 0 (nullptr).
//!Size will be 0.
//!Does not throw
mapped_region();
mapped_region() BOOST_NOEXCEPT;
//!Move constructor. *this will be constructed taking ownership of "other"'s
//!region and "other" will be left in default constructor state.
mapped_region(BOOST_RV_REF(mapped_region) other)
mapped_region(BOOST_RV_REF(mapped_region) other) BOOST_NOEXCEPT
#if defined (BOOST_INTERPROCESS_WINDOWS)
: m_base(0), m_size(0)
, m_page_offset(0)
@@ -157,7 +156,7 @@ class mapped_region
//!Move assignment. If *this owns a memory mapped region, it will be
//!destroyed and it will take ownership of "other"'s memory mapped region.
mapped_region &operator=(BOOST_RV_REF(mapped_region) other)
mapped_region &operator=(BOOST_RV_REF(mapped_region) other) BOOST_NOEXCEPT
{
mapped_region tmp(boost::move(other));
this->swap(tmp);
@@ -166,18 +165,18 @@ class mapped_region
//!Swaps the mapped_region with another
//!mapped region
void swap(mapped_region &other);
void swap(mapped_region &other) BOOST_NOEXCEPT;
//!Returns the size of the mapping. Never throws.
std::size_t get_size() const;
std::size_t get_size() const BOOST_NOEXCEPT;
//!Returns the base address of the mapping.
//!Never throws.
void* get_address() const;
void* get_address() const BOOST_NOEXCEPT;
//!Returns the mode of the mapping used to construct the mapped region.
//!Never throws.
mode_t get_mode() const;
mode_t get_mode() const BOOST_NOEXCEPT;
//!Flushes to the disk a byte range within the mapped memory.
//!If 'async' is true, the function will return before flushing operation is completed
@@ -190,7 +189,7 @@ class mapped_region
//!mapped memory page, accessing that page can trigger a segmentation fault.
//!Depending on the OS, this operation might fail (XSI shared memory), it can decommit storage
//!and free a portion of the virtual address space (e.g.POSIX) or this
//!function can release some physical memory wihout freeing any virtual address space(Windows).
//!function can release some physical memory without freeing any virtual address space(Windows).
//!Returns true on success. Never throws.
bool shrink_by(std::size_t bytes, bool from_back = true);
@@ -225,7 +224,7 @@ class mapped_region
//!Returns the size of the page. This size is the minimum memory that
//!will be used by the system when mapping a memory mappable source and
//!will restrict the address and the offset to map.
static std::size_t get_page_size();
static std::size_t get_page_size() BOOST_NOEXCEPT;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -269,19 +268,19 @@ class mapped_region
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void swap(mapped_region &x, mapped_region &y)
inline void swap(mapped_region &x, mapped_region &y) BOOST_NOEXCEPT
{ x.swap(y); }
inline mapped_region::~mapped_region()
{ this->priv_close(); }
inline std::size_t mapped_region::get_size() const
inline std::size_t mapped_region::get_size() const BOOST_NOEXCEPT
{ return m_size; }
inline mode_t mapped_region::get_mode() const
inline mode_t mapped_region::get_mode() const BOOST_NOEXCEPT
{ return m_mode; }
inline void* mapped_region::get_address() const
inline void* mapped_region::get_address() const BOOST_NOEXCEPT
{ return m_base; }
inline void* mapped_region::priv_map_address() const
@@ -297,7 +296,7 @@ inline bool mapped_region::priv_flush_param_check
if(m_base == 0)
return false;
if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){
if(mapping_offset >= m_size || numbytes > (m_size - size_t(mapping_offset))){
return false;
}
@@ -346,14 +345,14 @@ inline void mapped_region::priv_size_from_mapping_size
(offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size)
{
//Check if mapping size fits in the user address space
//as offset_t is the maximum file size and its signed.
//as offset_t is the maximum file size and it's signed.
if(mapping_size < offset ||
boost::uintmax_t(mapping_size - (offset - page_offset)) >
boost::uintmax_t(std::size_t(-1))){
error_info err(size_error);
throw interprocess_exception(err);
}
size = static_cast<std::size_t>(mapping_size - (offset - page_offset));
size = static_cast<std::size_t>(mapping_size - offset);
}
inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, const void *&address)
@@ -365,17 +364,17 @@ inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, cons
//We calculate the difference between demanded and valid offset
//(always less than a page in std::size_t, thus, representable by std::size_t)
const std::size_t page_offset =
static_cast<std::size_t>(offset - (offset / page_size) * page_size);
static_cast<std::size_t>(offset - (offset / offset_t(page_size)) * offset_t(page_size));
//Update the mapping address
if(address){
address = static_cast<const char*>(address) - page_offset;
}
return page_offset;
return offset_t(page_offset);
}
#if defined (BOOST_INTERPROCESS_WINDOWS)
inline mapped_region::mapped_region()
inline mapped_region::mapped_region() BOOST_NOEXCEPT
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only)
, m_file_or_mapping_hnd(ipcdetail::invalid_file())
{}
@@ -383,7 +382,7 @@ inline mapped_region::mapped_region()
template<int dummy>
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
{
winapi::system_info info;
winapi::interprocess_system_info info;
winapi::get_system_info(&info);
return std::size_t(info.dwAllocationGranularity);
}
@@ -442,11 +441,11 @@ inline mapped_region::mapped_region
//Create mapping handle
native_mapping_handle = winapi::create_file_mapping
( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle())
, protection, 0, 0, 0);
, protection, 0, (char*)0, 0);
//Check if all is correct
if(!native_mapping_handle){
error_info err = winapi::get_last_error();
error_info err ((int)winapi::get_last_error());
throw interprocess_exception(err);
}
handle_to_close = native_mapping_handle;
@@ -466,7 +465,7 @@ inline mapped_region::mapped_region
if(size == 0){
offset_t mapping_size;
if(!winapi::get_file_mapping_size(native_mapping_handle, mapping_size)){
error_info err = winapi::get_last_error();
error_info err((int)winapi::get_last_error());
throw interprocess_exception(err);
}
//This can throw
@@ -477,18 +476,18 @@ inline mapped_region::mapped_region
void *base = winapi::map_view_of_file_ex
(native_mapping_handle,
map_access,
offset - page_offset,
::boost::ulong_long_type(offset - page_offset),
static_cast<std::size_t>(page_offset + size),
const_cast<void*>(address));
//Check error
if(!base){
error_info err = winapi::get_last_error();
error_info err((int)winapi::get_last_error());
throw interprocess_exception(err);
}
//Calculate new base for the user
m_base = static_cast<char*>(base) + page_offset;
m_page_offset = page_offset;
m_page_offset = static_cast<std::size_t>(page_offset);
m_size = size;
}
//Windows shared memory needs the duplication of the handle if we want to
@@ -496,7 +495,7 @@ inline mapped_region::mapped_region
//
//For mapped files, we duplicate the file handle to be able to FlushFileBuffers
if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_or_mapping_hnd)){
error_info err = winapi::get_last_error();
error_info err((int)winapi::get_last_error());
this->priv_close();
throw interprocess_exception(err);
}
@@ -573,7 +572,7 @@ inline void mapped_region::dont_close_on_destruction()
#else //#if defined (BOOST_INTERPROCESS_WINDOWS)
inline mapped_region::mapped_region()
inline mapped_region::mapped_region() BOOST_NOEXCEPT
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
{}
@@ -696,7 +695,7 @@ inline mapped_region::mapped_region
//Map it to the address space
void* base = mmap ( const_cast<void*>(address)
, static_cast<std::size_t>(page_offset + size)
, static_cast<std::size_t>(page_offset) + size
, prot
, flags
, mapping.get_mapping_handle().handle
@@ -710,7 +709,7 @@ inline mapped_region::mapped_region
//Calculate new base for the user
m_base = static_cast<char*>(base) + page_offset;
m_page_offset = page_offset;
m_page_offset = static_cast<std::size_t>(page_offset);
m_size = size;
//Check for fixed mapping error
@@ -852,7 +851,7 @@ template<int dummy>
const std::size_t mapped_region::page_size_holder<dummy>::PageSize
= mapped_region::page_size_holder<dummy>::get_page_size();
inline std::size_t mapped_region::get_page_size()
inline std::size_t mapped_region::get_page_size() BOOST_NOEXCEPT
{
if(!page_size_holder<0>::PageSize)
return page_size_holder<0>::get_page_size();
@@ -860,7 +859,7 @@ inline std::size_t mapped_region::get_page_size()
return page_size_holder<0>::PageSize;
}
inline void mapped_region::swap(mapped_region &other)
inline void mapped_region::swap(mapped_region &other) BOOST_NOEXCEPT
{
::boost::adl_move_swap(this->m_base, other.m_base);
::boost::adl_move_swap(this->m_size, other.m_size);

View File

@@ -35,6 +35,8 @@
#include <boost/container/detail/placement_new.hpp>
// move
#include <boost/move/utility_core.hpp>
// move/detail
#include <boost/move/detail/force_ptr.hpp>
// other boost
#include <boost/static_assert.hpp>
#include <boost/assert.hpp>
@@ -289,10 +291,10 @@ class memory_algorithm_common
max_value(ceil_units(nbytes) + AllocatedCtrlUnits, size_type(MinBlockUnits));
//We can create a new block in the end of the segment
if(old_size >= (first_min_units + MinBlockUnits)){
block_ctrl *second = reinterpret_cast<block_ctrl *>
block_ctrl *second = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(first) + Alignment*first_min_units);
first->m_size = first_min_units;
second->m_size = old_size - first->m_size;
first->m_size = first_min_units & block_ctrl::size_mask;
second->m_size = (old_size - first->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(second->m_size >= MinBlockUnits);
memory_algo->priv_mark_new_allocated_block(first);
memory_algo->priv_mark_new_allocated_block(second);
@@ -326,7 +328,8 @@ class memory_algorithm_common
(reinterpret_cast<char*>(first) + first->m_size*Alignment));
//Set the new size of the first block
size_type old_size = first->m_size;
first->m_size = (size_type)(reinterpret_cast<char*>(second) - reinterpret_cast<char*>(first))/Alignment;
first->m_size = size_type(size_type(reinterpret_cast<char*>(second) - reinterpret_cast<char*>(first))/Alignment
& block_ctrl::size_mask);
memory_algo->priv_mark_new_allocated_block(first);
//Now check if we can create a new buffer in the end
@@ -346,15 +349,15 @@ class memory_algorithm_common
if((old_size - first->m_size) >= (second_min_units + MinBlockUnits)){
//Now obtain the address of the end block
block_ctrl *third = new (reinterpret_cast<char*>(second) + Alignment*second_min_units)block_ctrl;
second->m_size = second_min_units;
third->m_size = old_size - first->m_size - second->m_size;
second->m_size = second_min_units & block_ctrl::size_mask;
third->m_size = (old_size - first->m_size - second->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(third->m_size >= MinBlockUnits);
memory_algo->priv_mark_new_allocated_block(second);
memory_algo->priv_mark_new_allocated_block(third);
memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(third));
}
else{
second->m_size = old_size - first->m_size;
second->m_size = (old_size - first->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(second->m_size >= MinBlockUnits);
memory_algo->priv_mark_new_allocated_block(second);
}
@@ -437,15 +440,15 @@ class memory_algorithm_common
return true;
//Now we can just rewrite the size of the old buffer
block->m_size = (received_size-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits;
block->m_size = ((received_size-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits) & block_ctrl::size_mask;
BOOST_ASSERT(block->m_size >= BlockCtrlUnits);
//We create the new block
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(block) + block->m_size*Alignment);
//Write control data to simulate this new block was previously allocated
//and deallocate it
new_block->m_size = old_block_units - block->m_size;
new_block->m_size = (old_block_units - block->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits);
memory_algo->priv_mark_new_allocated_block(block);
memory_algo->priv_mark_new_allocated_block(new_block);
@@ -520,7 +523,7 @@ class memory_algorithm_common
break;
total_request_units -= elem_units;
//This is the position where the new block must be created
block_ctrl *new_block = reinterpret_cast<block_ctrl *>(block_address);
block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>(block_address);
assert_alignment(new_block);
//The last block should take all the remaining space
@@ -531,7 +534,7 @@ class memory_algorithm_common
: max_value(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units))
> received_units)){
//By default, the new block will use the rest of the buffer
new_block->m_size = received_units - total_used_units;
new_block->m_size = (received_units - total_used_units) & block_ctrl::size_mask;
memory_algo->priv_mark_new_allocated_block(new_block);
//If the remaining units are bigger than needed and we can
@@ -557,7 +560,7 @@ class memory_algorithm_common
}
}
else{
new_block->m_size = elem_units;
new_block->m_size = elem_units & block_ctrl::size_mask;
memory_algo->priv_mark_new_allocated_block(new_block);
}

View File

@@ -37,6 +37,7 @@
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
#include <boost/move/detail/type_traits.hpp> //make_unsigned, alignment_of
#include <boost/move/detail/force_ptr.hpp>
#include <boost/intrusive/detail/minimal_pair_header.hpp>
#include <cstring>
#include <boost/assert.hpp>
@@ -91,6 +92,7 @@ class simple_seq_fit_impl
class block_ctrl
{
public:
static const size_type size_mask = size_type(-1);
//!Offset pointer to the next block.
block_ctrl_ptr m_next;
//!This block's memory size (including block_ctrl
@@ -329,7 +331,7 @@ inline simple_seq_fit_impl<MutexFamily, VoidPointer>::
//Initialize pointers
size_type block1_off = priv_first_block_offset(this, extra_hdr_bytes);
m_header.m_root.m_next = reinterpret_cast<block_ctrl*>
m_header.m_root.m_next = move_detail::force_ptr<block_ctrl*>
((reinterpret_cast<char*>(this) + block1_off));
algo_impl_t::assert_alignment(ipcdetail::to_raw_pointer(m_header.m_root.m_next));
m_header.m_root.m_next->m_size = (segment_size - block1_off)/Alignment;
@@ -360,7 +362,7 @@ inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::grow(size_type extra_
//We'll create a new free block with extra_size bytes
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(this) + old_end);
algo_impl_t::assert_alignment(new_block);
@@ -438,7 +440,7 @@ inline
typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *
simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_get_block(const void *ptr)
{
return const_cast<block_ctrl*>(reinterpret_cast<const block_ctrl*>
return const_cast<block_ctrl*>(move_detail::force_ptr<const block_ctrl*>
(reinterpret_cast<const char*>(ptr) - AllocatedCtrlBytes));
}
@@ -707,7 +709,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
//We need a minimum size to split the previous one
if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(reuse) - needs_backwards - BlockCtrlBytes);
new_block->m_next = 0;
@@ -850,7 +852,7 @@ inline typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *
(typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *ptr)
{
//Take the address where the next block should go
block_ctrl *next_block = reinterpret_cast<block_ctrl*>
block_ctrl *next_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(ptr) + ptr->m_size*Alignment);
//Check if the adjacent block is in the managed segment
@@ -912,7 +914,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
{
size_type preferred_size = received_size;
//Obtain the real size of the block
block_ctrl *block = reinterpret_cast<block_ctrl*>(priv_get_block(ptr));
block_ctrl *block = move_detail::force_ptr<block_ctrl*>(priv_get_block(ptr));
size_type old_block_size = block->m_size;
//All used blocks' next is marked with 0 so check it
@@ -995,7 +997,7 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_check_and_allocate
size_type total_size = block->m_size;
block->m_size = nunits;
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(block) + Alignment*nunits);
new_block->m_size = total_size - nunits;
new_block->m_next = block->m_next;
@@ -1044,7 +1046,7 @@ void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_deallocate(void* addr)
//(lower address) block
block_ctrl * prev = &m_header.m_root;
block_ctrl * pos = ipcdetail::to_raw_pointer(m_header.m_root.m_next);
block_ctrl * block = reinterpret_cast<block_ctrl*>(priv_get_block(addr));
block_ctrl * block = move_detail::force_ptr<block_ctrl*>(priv_get_block(addr));
//All used blocks' next is marked with 0 so check it
BOOST_ASSERT(block->m_next == 0);

View File

@@ -40,6 +40,7 @@
#include <boost/container/detail/placement_new.hpp>
// move/detail
#include <boost/move/detail/type_traits.hpp> //make_unsigned, alignment_of
#include <boost/move/detail/force_ptr.hpp> //make_unsigned, alignment_of
// intrusive
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
@@ -107,6 +108,7 @@ class rbtree_best_fit
struct SizeHolder
{
static const size_type size_mask = size_type(-1) >> 2;
//!This block's memory size (including block_ctrl
//!header) in Alignment units
size_type m_prev_size;
@@ -384,28 +386,28 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
BOOST_ASSERT(segment_size >= (BlockCtrlBytes + EndCtrlBlockBytes));
//Initialize the first big block and the "end" node
block_ctrl *first_big_block = ::new(addr, boost_container_new_t())block_ctrl;
first_big_block->m_size = segment_size/Alignment - EndCtrlBlockUnits;
block_ctrl *first_big_block = ::new(addr, boost_container_new_t()) block_ctrl;
first_big_block->m_size = (segment_size/Alignment - EndCtrlBlockUnits) & block_ctrl::size_mask;
BOOST_ASSERT(first_big_block->m_size >= BlockCtrlUnits);
//The "end" node is just a node of size 0 with the "end" bit set
block_ctrl *end_block = static_cast<block_ctrl*>
(new (reinterpret_cast<char*>(addr) + first_big_block->m_size*Alignment)SizeHolder);
SizeHolder *end_block =
::new(reinterpret_cast<char*>(addr) + first_big_block->m_size*Alignment, boost_container_new_t()) SizeHolder;
//This will overwrite the prev part of the "end" node
priv_mark_as_free_block (first_big_block);
#ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP
first_big_block->m_prev_size = end_block->m_size =
(reinterpret_cast<char*>(first_big_block) - reinterpret_cast<char*>(end_block))/Alignment;
size_type(reinterpret_cast<char*>(first_big_block) - reinterpret_cast<char*>(end_block))/Alignmen) & block_ctrl::size_mask;
#else
first_big_block->m_prev_size = end_block->m_size =
(reinterpret_cast<char*>(end_block) - reinterpret_cast<char*>(first_big_block))/Alignment;
size_type(reinterpret_cast<char*>(end_block) - reinterpret_cast<char*>(first_big_block))/Alignment & block_ctrl::size_mask;
#endif
end_block->m_allocated = 1;
first_big_block->m_prev_allocated = 1;
BOOST_ASSERT(priv_next_block(first_big_block) == end_block);
BOOST_ASSERT(priv_prev_block(end_block) == first_big_block);
BOOST_ASSERT(priv_prev_block((block_ctrl*)end_block) == first_big_block);
BOOST_ASSERT(priv_first_block() == first_big_block);
BOOST_ASSERT(priv_end_block() == end_block);
@@ -424,8 +426,8 @@ inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_c
rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>
::priv_first_block()
{
size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes);
return reinterpret_cast<block_ctrl *>(reinterpret_cast<char*>(this) + block1_off);
const size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes);
return move_detail::force_ptr<block_ctrl*>(reinterpret_cast<char*>(this) + block1_off);
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
@@ -433,10 +435,10 @@ inline typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_c
rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>
::priv_end_block()
{
size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes);
const size_type original_first_block_size = m_header.m_size/Alignment*Alignment - block1_off/Alignment*Alignment - EndCtrlBlockBytes;
block_ctrl *end_block = reinterpret_cast<block_ctrl*>
(reinterpret_cast<char*>(this) + block1_off + original_first_block_size);
const size_type block1_off = priv_first_block_offset_from_this(this, m_header.m_extra_hdr_bytes);
const size_type original_first_block_size = (m_header.m_size - block1_off)/Alignment - EndCtrlBlockUnits;
block_ctrl *end_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(this) + block1_off + original_first_block_size*Alignment);
return end_block;
}
@@ -483,7 +485,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::grow(size_type ext
//Now create a new block between the old end and the new end
size_type align_offset = (m_header.m_size - old_border_offset)/Alignment;
block_ctrl *new_end_block = reinterpret_cast<block_ctrl*>
block_ctrl *new_end_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(old_end_block) + align_offset*Alignment);
//the last and first block are special:
@@ -491,11 +493,11 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::grow(size_type ext
//between them
new_end_block->m_allocated = 1;
#ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP
new_end_block->m_size = (reinterpret_cast<char*>(first_block) -
reinterpret_cast<char*>(new_end_block))/Alignment;
new_end_block->m_size = size_type(reinterpret_cast<char*>(first_block) -
reinterpret_cast<char*>(new_end_block))/Alignment & block_ctrl::size_mask;
#else
new_end_block->m_size = (reinterpret_cast<char*>(new_end_block) -
reinterpret_cast<char*>(first_block))/Alignment;
new_end_block->m_size = size_type(reinterpret_cast<char*>(new_end_block) -
reinterpret_cast<char*>(first_block))/Alignment & block_ctrl::size_mask;
#endif
first_block->m_prev_size = new_end_block->m_size;
first_block->m_prev_allocated = 1;
@@ -503,8 +505,8 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::grow(size_type ext
//The old end block is the new block
block_ctrl *new_block = old_end_block;
new_block->m_size = (reinterpret_cast<char*>(new_end_block) -
reinterpret_cast<char*>(new_block))/Alignment;
new_block->m_size = size_type(reinterpret_cast<char*>(new_end_block) -
reinterpret_cast<char*>(new_block))/Alignment & block_ctrl::size_mask;
BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits);
priv_mark_as_allocated_block(new_block);
BOOST_ASSERT(priv_next_block(new_block) == new_end_block);
@@ -568,11 +570,13 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::shrink_to_fit()
//Write new end block attributes
#ifdef BOOST_INTERPROCESS_RBTREE_BEST_FIT_ABI_V1_HPP
new_end_block->m_size = first_block->m_prev_size =
(reinterpret_cast<char*>(first_block) - reinterpret_cast<char*>(new_end_block))/Alignment;
new_end_block->m_size =
size_type(reinterpret_cast<char*>(first_block) - reinterpret_cast<char*>(new_end_block))/Alignment & block_ctrl::size_mask;
first_block->m_prev_size = new_end_block->m_size;
#else
new_end_block->m_size = first_block->m_prev_size =
(reinterpret_cast<char*>(new_end_block) - reinterpret_cast<char*>(first_block))/Alignment;
new_end_block->m_size =
size_type(reinterpret_cast<char*>(new_end_block) - reinterpret_cast<char*>(first_block))/Alignment & block_ctrl::size_mask;
first_block->m_prev_size = new_end_block->m_size;
#endif
new_end_block->m_allocated = 1;
@@ -581,7 +585,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::shrink_to_fit()
BOOST_ASSERT(new_end_block->m_size == (old_end_block_size - last_block_size));
//Update managed buffer's size
m_header.m_size = shrunk_border_offset;
m_header.m_size = shrunk_border_offset & block_ctrl::size_mask;
BOOST_ASSERT(priv_end_block() == new_end_block);
if(unique_buffer)
priv_deallocate(unique_buffer);
@@ -641,7 +645,6 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
//Iterate through all blocks obtaining their size
for(; ib != ie; ++ib){
free_memory += (size_type)ib->m_size*Alignment;
algo_impl_t::assert_alignment(&*ib);
if(!algo_impl_t::check_alignment(&*ib))
return false;
}
@@ -849,17 +852,17 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
}
//We need a minimum size to split the previous one
if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){
block_ctrl *new_block = reinterpret_cast<block_ctrl *>
block_ctrl *new_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(reuse) - needs_backwards_aligned);
//Free old previous buffer
new_block->m_size =
AllocatedCtrlUnits + (needs_backwards_aligned + (prefer_in_recvd_out_size - UsableByPreviousChunk))/Alignment;
(AllocatedCtrlUnits + (needs_backwards_aligned + (prefer_in_recvd_out_size - UsableByPreviousChunk))/Alignment) & block_ctrl::size_mask;
BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits);
priv_mark_as_allocated_block(new_block);
prev_block->m_size = (reinterpret_cast<char*>(new_block) -
reinterpret_cast<char*>(prev_block))/Alignment;
prev_block->m_size = size_type(reinterpret_cast<char*>(new_block) -
reinterpret_cast<char*>(prev_block))/Alignment & block_ctrl::size_mask;
BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits);
priv_mark_as_free_block(prev_block);
@@ -886,7 +889,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
//first bytes, fill them with a pattern
void *p = priv_get_user_buffer(new_block);
void *user_ptr = reinterpret_cast<char*>(p);
BOOST_ASSERT((static_cast<char*>(reuse_ptr) - static_cast<char*>(user_ptr)) % backwards_multiple == 0);
BOOST_ASSERT(size_type(static_cast<char*>(reuse_ptr) - static_cast<char*>(user_ptr)) % backwards_multiple == 0);
algo_impl_t::assert_alignment(user_ptr);
return user_ptr;
}
@@ -903,14 +906,14 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
m_header.m_allocated += (size_type)prev_block->m_size*Alignment;
//Now update sizes
prev_block->m_size = prev_block->m_size + reuse->m_size;
prev_block->m_size = size_type(prev_block->m_size + reuse->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(prev_block->m_size >= BlockCtrlUnits);
priv_mark_as_allocated_block(prev_block);
//If the backwards expansion has remaining bytes in the
//first bytes, fill them with a pattern
void *user_ptr = priv_get_user_buffer(prev_block);
BOOST_ASSERT((static_cast<char*>(reuse_ptr) - static_cast<char*>(user_ptr)) % backwards_multiple == 0);
BOOST_ASSERT(size_type(static_cast<char*>(reuse_ptr) - static_cast<char*>(user_ptr)) % backwards_multiple == 0);
algo_impl_t::assert_alignment(user_ptr);
return user_ptr;
}
@@ -999,7 +1002,7 @@ typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *
rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_get_block(const void *ptr)
{
return const_cast<block_ctrl*>
(reinterpret_cast<const block_ctrl*>
(move_detail::force_ptr<const block_ctrl*>
(reinterpret_cast<const char*>(ptr) - AllocatedCtrlBytes));
}
@@ -1086,29 +1089,19 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
//overwrite the tree hook of the old next block. So we first erase the
//old if needed and we'll insert the new one after creating the new next
imultiset_iterator old_next_block_it(Imultiset::s_iterator_to(*next_block));
const bool size_invariants_broken =
(next_block->m_size - rem_units ) < BlockCtrlUnits ||
(old_next_block_it != m_header.m_imultiset.begin() &&
(--imultiset_iterator(old_next_block_it))->m_size > rem_units);
if(size_invariants_broken){
m_header.m_imultiset.erase(old_next_block_it);
}
m_header.m_imultiset.erase(old_next_block_it);
//This is the remaining block
block_ctrl *rem_block = ::new(reinterpret_cast<block_ctrl*>
(reinterpret_cast<char*>(block) + intended_units*Alignment), boost_container_new_t())block_ctrl;
rem_block->m_size = rem_units;
block_ctrl *rem_block =
::new(reinterpret_cast<char*>(block) + intended_units*Alignment, boost_container_new_t()) block_ctrl;
rem_block->m_size = rem_units & block_ctrl::size_mask;
algo_impl_t::assert_alignment(rem_block);
BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits);
priv_mark_as_free_block(rem_block);
//Now the second part of the fixup
if(size_invariants_broken)
m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *rem_block);
else
m_header.m_imultiset.replace_node(old_next_block_it, *rem_block);
m_header.m_imultiset.insert(*rem_block);
//Write the new length
block->m_size = intended_user_units + AllocatedCtrlUnits;
block->m_size = (intended_user_units + AllocatedCtrlUnits) & block_ctrl::size_mask;
BOOST_ASSERT(block->m_size >= BlockCtrlUnits);
m_header.m_allocated += (intended_units - old_block_units)*Alignment;
}
@@ -1118,7 +1111,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
m_header.m_imultiset.erase(Imultiset::s_iterator_to(*next_block));
//Write the new length
block->m_size = merged_units;
block->m_size = merged_units & block_ctrl::size_mask;
BOOST_ASSERT(block->m_size >= BlockCtrlUnits);
m_header.m_allocated += (merged_units - old_block_units)*Alignment;
}
@@ -1133,7 +1126,7 @@ typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *
(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *ptr)
{
BOOST_ASSERT(!ptr->m_prev_allocated);
return reinterpret_cast<block_ctrl *>
return move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(ptr) - ptr->m_prev_size*Alignment);
}
@@ -1147,7 +1140,7 @@ typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *
//The first block's logic is different from the rest of blocks: stores in m_prev_size the absolute
//distance with the end block
BOOST_ASSERT(first_segment_block->m_prev_allocated);
block_ctrl *end_block = reinterpret_cast<block_ctrl *>
block_ctrl *end_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(first_segment_block) + first_segment_block->m_prev_size*Alignment);
(void)end_block;
BOOST_ASSERT(end_block->m_allocated == 1);
@@ -1164,7 +1157,7 @@ typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *
//The first block's logic is different from the rest of blocks: stores in m_prev_size the absolute
//distance with the end block
BOOST_ASSERT(end_segment_block->m_allocated);
block_ctrl *first_block = reinterpret_cast<block_ctrl *>
block_ctrl *first_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(end_segment_block) - end_segment_block->m_size*Alignment);
(void)first_block;
BOOST_ASSERT(first_block->m_prev_allocated == 1);
@@ -1179,7 +1172,7 @@ typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *
rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_next_block
(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *ptr)
{
return reinterpret_cast<block_ctrl *>
return move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(ptr) + ptr->m_size*Alignment);
}
@@ -1190,7 +1183,7 @@ bool rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_is_allocated_
bool allocated = block->m_allocated != 0;
#ifndef NDEBUG
if(block != priv_end_block()){
block_ctrl *next_block = reinterpret_cast<block_ctrl *>
block_ctrl *next_block = move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(block) + block->m_size*Alignment);
bool next_block_prev_allocated = next_block->m_prev_allocated != 0;
(void)next_block_prev_allocated;
@@ -1225,7 +1218,7 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_mark_as_alloc
(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *block)
{
block->m_allocated = 1;
reinterpret_cast<block_ctrl *>
move_detail::force_ptr<block_ctrl*>
(reinterpret_cast<char*>(block)+ block->m_size*Alignment)->m_prev_allocated = 1;
}
@@ -1254,34 +1247,20 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al
//two blocks, the first's size will be "units" and
//the second's size "block->m_size-units"
size_type block_old_size = block->m_size;
block->m_size = nunits;
block->m_size = nunits & block_ctrl::size_mask;
BOOST_ASSERT(block->m_size >= BlockCtrlUnits);
//This is the remaining block
block_ctrl *rem_block = ::new(reinterpret_cast<block_ctrl*>
(reinterpret_cast<char*>(block) + Alignment*nunits), boost_container_new_t())block_ctrl;
block_ctrl *rem_block =
::new(reinterpret_cast<char*>(block) + Alignment*nunits, boost_container_new_t()) block_ctrl;
algo_impl_t::assert_alignment(rem_block);
rem_block->m_size = block_old_size - nunits;
rem_block->m_size = (block_old_size - nunits) & block_ctrl::size_mask;
BOOST_ASSERT(rem_block->m_size >= BlockCtrlUnits);
priv_mark_as_free_block(rem_block);
imultiset_iterator it_hint;
if(it_old == m_header.m_imultiset.begin()
|| (--imultiset_iterator(it_old))->m_size <= rem_block->m_size){
//option a: slow but secure
//m_header.m_imultiset.insert(m_header.m_imultiset.erase(it_old), *rem_block);
//option b: Construct an empty node and swap
//Imultiset::init_node(*rem_block);
//block->swap_nodes(*rem_block);
//option c: replace the node directly
m_header.m_imultiset.replace_node(Imultiset::s_iterator_to(*it_old), *rem_block);
}
else{
//Now we have to update the data in the tree
m_header.m_imultiset.erase(it_old);
m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *rem_block);
}
//Now we have to update the data in the tree.
//Use the position of the erased one as a hint
m_header.m_imultiset.insert(m_header.m_imultiset.erase(it_old), *rem_block);
}
else if (block->m_size >= nunits){
m_header.m_imultiset.erase(it_old);
@@ -1302,7 +1281,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_check_and_al
//cleared with zero_free_memory
TreeHook *t = static_cast<TreeHook*>(block);
//Just clear the memory part reserved for the user
std::size_t tree_hook_offset_in_block = (char*)t - (char*)block;
std::size_t tree_hook_offset_in_block = std::size_t((char*)t - (char*)block);
//volatile char *ptr =
char *ptr = reinterpret_cast<char*>(block)+tree_hook_offset_in_block;
const std::size_t s = BlockCtrlBytes - tree_hook_offset_in_block;
@@ -1354,40 +1333,20 @@ void rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_deallocate(vo
if(merge_with_prev){
//Get the previous block
block_to_insert = priv_prev_block(block);
block_to_insert->m_size += block->m_size;
block_to_insert->m_size = size_type(block_to_insert->m_size + block->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits);
m_header.m_imultiset.erase(Imultiset::s_iterator_to(*block_to_insert));
}
//Merge if the next is free
if(merge_with_next){
block_to_insert->m_size += next_block->m_size;
block_to_insert->m_size = size_type(block_to_insert->m_size + next_block->m_size) & block_ctrl::size_mask;
BOOST_ASSERT(block_to_insert->m_size >= BlockCtrlUnits);
const imultiset_iterator next_it = Imultiset::s_iterator_to(*next_block);
if(merge_with_prev){
m_header.m_imultiset.erase(next_it);
}
else{
m_header.m_imultiset.replace_node(next_it, *block_to_insert);
}
m_header.m_imultiset.erase(next_it);
}
//Now try to shortcut erasure + insertion (O(log(N))) with
//a O(1) operation if merging does not alter tree positions
const imultiset_iterator block_to_check_it = Imultiset::s_iterator_to(*block_to_insert);
imultiset_const_iterator next_to_check_it(block_to_check_it), end_it(m_header.m_imultiset.end());
if(++next_to_check_it != end_it && block_to_insert->m_size > next_to_check_it->m_size){
//Block is bigger than next, so move it
m_header.m_imultiset.erase(block_to_check_it);
m_header.m_imultiset.insert(end_it, *block_to_insert);
}
else{
//Block size increment didn't violate tree invariants so there is nothing to fix
}
}
else{
m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *block_to_insert);
}
priv_mark_as_free_block(block_to_insert);
m_header.m_imultiset.insert(*block_to_insert);
}
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED

View File

@@ -33,8 +33,15 @@
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp> //alignment_of, aligned_storage
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <iosfwd>
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
//!\file
//!Describes a smart pointer that stores the offset between this pointer and
//!target pointee, called offset_ptr.
@@ -400,17 +407,17 @@ class offset_ptr
//!offset_ptr += difference_type.
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator+= (difference_type offset) BOOST_NOEXCEPT
{ this->inc_offset(offset * sizeof (PointedType)); return *this; }
{ this->inc_offset(offset * difference_type(sizeof(PointedType))); return *this; }
//!offset_ptr -= difference_type.
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator-= (difference_type offset) BOOST_NOEXCEPT
{ this->dec_offset(offset * sizeof (PointedType)); return *this; }
{ this->dec_offset(offset * difference_type(sizeof(PointedType))); return *this; }
//!++offset_ptr.
//!Never throws.
BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator++ (void) BOOST_NOEXCEPT
{ this->inc_offset(sizeof (PointedType)); return *this; }
{ this->inc_offset(difference_type(sizeof(PointedType))); return *this; }
//!offset_ptr++.
//!Never throws.
@@ -573,10 +580,10 @@ class offset_ptr
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
BOOST_INTERPROCESS_FORCEINLINE void inc_offset(DifferenceType bytes) BOOST_NOEXCEPT
{ internal.m_offset += bytes; }
{ internal.m_offset += OffsetType(bytes); }
BOOST_INTERPROCESS_FORCEINLINE void dec_offset(DifferenceType bytes) BOOST_NOEXCEPT
{ internal.m_offset -= bytes; }
{ internal.m_offset -= OffsetType(bytes); }
ipcdetail::offset_ptr_internal<OffsetType, OffsetAlignment> internal;
@@ -762,4 +769,8 @@ struct pointer_to_other
#include <boost/interprocess/detail/config_end.hpp>
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
#pragma GCC diagnostic pop
#endif
#endif //#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP

View File

@@ -29,6 +29,10 @@
#include <boost/interprocess/detail/win32_api.hpp>
#else
#include <sys/stat.h>
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -70,7 +74,7 @@ class permissions
#if defined(BOOST_INTERPROCESS_WINDOWS)
typedef void* os_permissions_type;
#else
typedef int os_permissions_type;
typedef ::mode_t os_permissions_type;
#endif
os_permissions_type m_perm;
@@ -79,20 +83,20 @@ class permissions
public:
//!Constructs a permissions object from a user provided os-dependent
//!permissions.
permissions(os_permissions_type type)
permissions(os_permissions_type type) BOOST_NOEXCEPT
: m_perm(type)
{}
//!Constructs a default permissions object:
//!A null security attributes pointer for windows or 0644
//!for UNIX.
permissions()
permissions() BOOST_NOEXCEPT
{ set_default(); }
//!Sets permissions to default values:
//!A null security attributes pointer for windows or 0644
//!for UNIX.
void set_default()
void set_default() BOOST_NOEXCEPT
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
m_perm = 0;
@@ -103,7 +107,7 @@ class permissions
//!Sets permissions to unrestricted access:
//!A null DACL for windows or 0666 for UNIX.
void set_unrestricted()
void set_unrestricted() BOOST_NOEXCEPT
{
#if defined (BOOST_INTERPROCESS_WINDOWS)
m_perm = &ipcdetail::unrestricted_permissions_holder<0>::unrestricted;
@@ -114,12 +118,12 @@ class permissions
//!Sets permissions from a user provided os-dependent
//!permissions.
void set_permissions(os_permissions_type perm)
void set_permissions(os_permissions_type perm) BOOST_NOEXCEPT
{ m_perm = perm; }
//!Returns stored os-dependent
//!permissions
os_permissions_type get_permissions() const
os_permissions_type get_permissions() const BOOST_NOEXCEPT
{ return m_perm; }
};

View File

@@ -127,6 +127,20 @@ class segment_manager_base
void * allocate (size_type nbytes, const std::nothrow_t &)
{ return MemoryAlgorithm::allocate(nbytes); }
//!Returns a reference to the internal memory algorithm.
//!This function is useful for custom memory algorithms that
//!need additional configuration options after construction. Never throws.
//!This function should be only used by advanced users.
MemoryAlgorithm &get_memory_algorithm()
{ return static_cast<MemoryAlgorithm&>(*this); }
//!Returns a const reference to the internal memory algorithm.
//!This function is useful for custom memory algorithms that
//!need additional configuration options after construction. Never throws.
//!This function should be only used by advanced users.
const MemoryAlgorithm &get_memory_algorithm() const
{ return static_cast<const MemoryAlgorithm&>(*this); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//Experimental. Dont' use.
@@ -424,6 +438,8 @@ class segment_manager
const void *const segm_addr = static_cast<segment_manager_base_t*>(this);
(void)this_addr; (void)segm_addr;
BOOST_ASSERT( this_addr == segm_addr);
const std::size_t void_ptr_alignment = boost::move_detail::alignment_of<void_pointer>::value; (void)void_ptr_alignment;
BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of<segment_manager>::value));
}
//!Tries to find a previous named/unique allocation. Returns the address
@@ -837,8 +853,8 @@ class segment_manager
size_type &length, ipcdetail::true_ is_intrusive, bool use_lock)
{
(void)is_intrusive;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
typedef typename index_type::iterator index_it;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::iterator index_it;
//-------------------------------
scoped_lock<rmutex> guard(priv_get_lock(use_lock));
@@ -874,9 +890,9 @@ class segment_manager
size_type &length, ipcdetail::false_ is_intrusive, bool use_lock)
{
(void)is_intrusive;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
typedef typename index_type::key_type key_type;
typedef typename index_type::iterator index_it;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
typedef typename char_aware_index_type::key_type key_type;
typedef typename char_aware_index_type::iterator index_it;
//-------------------------------
scoped_lock<rmutex> guard(priv_get_lock(use_lock));
@@ -934,9 +950,9 @@ class segment_manager
ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index)
{
(void)is_intrusive_index;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
typedef typename index_type::iterator index_it;
typedef typename index_type::value_type intrusive_value_type;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::iterator index_it;
typedef typename index_type_t::value_type intrusive_value_type;
//-------------------------------
scoped_lock<rmutex> guard(m_header);
@@ -984,9 +1000,9 @@ class segment_manager
ipcdetail::false_ is_intrusive_index)
{
(void)is_intrusive_index;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
typedef typename index_type::iterator index_it;
typedef typename index_type::key_type key_type;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
typedef typename char_aware_index_type::iterator index_it;
typedef typename char_aware_index_type::key_type key_type;
//-------------------------------
scoped_lock<rmutex> guard(m_header);
@@ -1010,8 +1026,8 @@ class segment_manager
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table)
{
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
typedef typename index_type::iterator index_it;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
typedef typename char_aware_index_type::iterator index_it;
//Get allocation parameters
block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
@@ -1068,8 +1084,8 @@ class segment_manager
, sizeof(CharT)
, namelen);
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
typedef typename index_type::iterator index_it;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::iterator index_it;
typedef std::pair<index_it, bool> index_ib;
//-------------------------------
@@ -1088,8 +1104,8 @@ class segment_manager
//the key (which is a smart pointer) to an equivalent one
index_ib insert_ret;
typename index_type::insert_commit_data commit_data;
typedef typename index_type::value_type intrusive_value_type;
typename index_type_t::insert_commit_data commit_data;
typedef typename index_type_t::value_type intrusive_value_type;
BOOST_TRY{
ipcdetail::intrusive_compare_key<CharT> key(name, namelen);
@@ -1165,7 +1181,7 @@ class segment_manager
//if something goes wrong. This will be executed *before*
//the memory allocation as the intrusive value is built in that
//memory
value_eraser<index_type> v_eraser(index, it);
value_eraser<index_type_t> v_eraser(index, it);
//Construct array, this can throw
ipcdetail::array_construct(ptr, num, table);
@@ -1193,11 +1209,11 @@ class segment_manager
, sizeof(CharT)
, namelen);
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
typedef typename index_type::key_type key_type;
typedef typename index_type::mapped_type mapped_type;
typedef typename index_type::value_type value_type;
typedef typename index_type::iterator index_it;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::key_type key_type;
typedef typename index_type_t::mapped_type mapped_type;
typedef typename index_type_t::value_type value_type;
typedef typename index_type_t::iterator index_it;
typedef std::pair<index_it, bool> index_ib;
//-------------------------------
@@ -1240,7 +1256,7 @@ class segment_manager
}
//Initialize the node value_eraser to erase inserted node
//if something goes wrong
value_eraser<index_type> v_eraser(index, it);
value_eraser<index_type_t> v_eraser(index, it);
//Allocates buffer for name + data, this can throw (it hurts)
void *buffer_ptr;

View File

@@ -28,13 +28,14 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/shared_dir_helpers.hpp>
#include <boost/interprocess/detail/char_wchar_holder.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <cstddef>
#include <string>
#if defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
# include <fcntl.h> //O_CREAT, O_*...
# include <string>
# include <fcntl.h> //posix_fallocate, O_CREAT, O_*...
# include <sys/mman.h> //shm_xxx
# include <unistd.h> //ftruncate, close
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
@@ -64,7 +65,7 @@ class shared_memory_object
public:
//!Default constructor. Represents an empty shared_memory_object.
shared_memory_object();
shared_memory_object() BOOST_NOEXCEPT;
//!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode"
//!If the file previously exists, throws an error.*/
@@ -82,10 +83,39 @@ class shared_memory_object
shared_memory_object(open_only_t, const char *name, mode_t mode)
{ this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode"
//!If the file previously exists, throws an error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
shared_memory_object(create_only_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions())
{ this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); }
//!Tries to create a shared memory object with name "name" and mode "mode", with the
//!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
//!Otherwise throws an error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
shared_memory_object(open_or_create_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions())
{ this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); }
//!Tries to open a shared memory object with name "name", with the access mode "mode".
//!If the file does not previously exist, it throws an error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
shared_memory_object(open_only_t, const wchar_t*name, mode_t mode)
{ this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Moves the ownership of "moved"'s shared memory object to *this.
//!After the call, "moved" does not represent any shared memory object.
//!Does not throw
shared_memory_object(BOOST_RV_REF(shared_memory_object) moved)
shared_memory_object(BOOST_RV_REF(shared_memory_object) moved) BOOST_NOEXCEPT
: m_handle(file_handle_t(ipcdetail::invalid_file()))
, m_mode(read_only)
{ this->swap(moved); }
@@ -93,7 +123,7 @@ class shared_memory_object
//!Moves the ownership of "moved"'s shared memory to *this.
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved)
shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved) BOOST_NOEXCEPT
{
shared_memory_object tmp(boost::move(moved));
this->swap(tmp);
@@ -101,12 +131,23 @@ class shared_memory_object
}
//!Swaps the shared_memory_objects. Does not throw
void swap(shared_memory_object &moved);
void swap(shared_memory_object &moved) BOOST_NOEXCEPT;
//!Erases a shared memory object from the system.
//!Returns false on error. Never throws
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a shared memory object from the system.
//!Returns false on error. Never throws
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Sets the size of the shared memory mapping
void truncate(offset_t length);
@@ -120,17 +161,17 @@ class shared_memory_object
~shared_memory_object();
//!Returns the name of the shared memory object.
const char *get_name() const;
const char *get_name() const BOOST_NOEXCEPT;
//!Returns true if the size of the shared memory object
//!can be obtained and writes the size in the passed reference
bool get_size(offset_t &size) const;
bool get_size(offset_t &size) const BOOST_NOEXCEPT;
//!Returns access mode
mode_t get_mode() const;
mode_t get_mode() const BOOST_NOEXCEPT;
//!Returns mapping handle. Never throws.
mapping_handle_t get_mapping_handle() const;
mapping_handle_t get_mapping_handle() const BOOST_NOEXCEPT;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -139,17 +180,18 @@ class shared_memory_object
void priv_close();
//!Opens or creates a shared memory object.
bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm);
template<class CharT>
bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm);
file_handle_t m_handle;
mode_t m_mode;
std::string m_filename;
file_handle_t m_handle;
mode_t m_mode;
char_wchar_holder m_filename;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline shared_memory_object::shared_memory_object()
inline shared_memory_object::shared_memory_object() BOOST_NOEXCEPT
: m_handle(file_handle_t(ipcdetail::invalid_file()))
, m_mode(read_only)
{}
@@ -158,34 +200,35 @@ inline shared_memory_object::~shared_memory_object()
{ this->priv_close(); }
inline const char *shared_memory_object::get_name() const
{ return m_filename.c_str(); }
inline const char *shared_memory_object::get_name() const BOOST_NOEXCEPT
{ return m_filename.getn(); }
inline bool shared_memory_object::get_size(offset_t &size) const
inline bool shared_memory_object::get_size(offset_t &size) const BOOST_NOEXCEPT
{ return ipcdetail::get_file_size((file_handle_t)m_handle, size); }
inline void shared_memory_object::swap(shared_memory_object &other)
inline void shared_memory_object::swap(shared_memory_object &other) BOOST_NOEXCEPT
{
boost::adl_move_swap(m_handle, other.m_handle);
boost::adl_move_swap(m_mode, other.m_mode);
m_filename.swap(other.m_filename);
}
inline mapping_handle_t shared_memory_object::get_mapping_handle() const
inline mapping_handle_t shared_memory_object::get_mapping_handle() const BOOST_NOEXCEPT
{
return ipcdetail::mapping_handle_from_file_handle(m_handle);
}
inline mode_t shared_memory_object::get_mode() const
inline mode_t shared_memory_object::get_mode() const BOOST_NOEXCEPT
{ return m_mode; }
#if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
template<class CharT>
inline bool shared_memory_object::priv_open_or_create
(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm)
(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm)
{
m_filename = filename;
std::string shmfile;
std::basic_string<CharT> shmfile;
ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, shmfile);
//Set accesses
@@ -222,22 +265,39 @@ inline bool shared_memory_object::priv_open_or_create
return true;
}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES)
inline bool shared_memory_object::remove(const wchar_t *filename)
{
BOOST_TRY{
//Make sure a temporary path is created for shared memory
std::wstring shmfile;
ipcdetail::shared_filepath(filename, shmfile);
return ipcdetail::delete_file(shmfile.c_str());
}
BOOST_CATCH(...){
return false;
} BOOST_CATCH_END
}
#endif
inline bool shared_memory_object::remove(const char *filename)
{
try{
BOOST_TRY{
//Make sure a temporary path is created for shared memory
std::string shmfile;
ipcdetail::shared_filepath(filename, shmfile);
return ipcdetail::delete_file(shmfile.c_str());
}
catch(...){
BOOST_CATCH(...){
return false;
}
} BOOST_CATCH_END
}
inline void shared_memory_object::truncate(offset_t length)
{
if(!ipcdetail::truncate_file(m_handle, length)){
if(!ipcdetail::truncate_file(m_handle, (std::size_t)length)){
error_info err = system_error_code();
throw interprocess_exception(err);
}
@@ -275,9 +335,10 @@ inline bool use_filesystem_based_posix()
} //shared_memory_object_detail
template<class CharT>
inline bool shared_memory_object::priv_open_or_create
(ipcdetail::create_enum_t type,
const char *filename,
const CharT *filename,
mode_t mode, const permissions &perm)
{
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
@@ -287,11 +348,12 @@ inline bool shared_memory_object::priv_open_or_create
#else
const bool add_leading_slash = true;
#endif
std::basic_string<CharT> fname;
if(add_leading_slash){
ipcdetail::add_leading_slash(filename, m_filename);
ipcdetail::add_leading_slash(filename, fname);
}
else{
ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, m_filename);
ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, fname);
}
//Create new mapping
@@ -306,19 +368,19 @@ inline bool shared_memory_object::priv_open_or_create
error_info err(mode_error);
throw interprocess_exception(err);
}
int unix_perm = perm.get_permissions();
::mode_t unix_perm = perm.get_permissions();
switch(type){
case ipcdetail::DoOpen:
{
//No oflag addition
m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
m_handle = shm_open(fname.c_str(), oflag, unix_perm);
}
break;
case ipcdetail::DoCreate:
{
oflag |= (O_CREAT | O_EXCL);
m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
m_handle = shm_open(fname.c_str(), oflag, unix_perm);
if(m_handle >= 0){
::fchmod(m_handle, unix_perm);
}
@@ -328,16 +390,16 @@ inline bool shared_memory_object::priv_open_or_create
{
//We need a create/open loop to change permissions correctly using fchmod, since
//with "O_CREAT" only we don't know if we've created or opened the shm.
while(1){
while(true){
//Try to create shared memory
m_handle = shm_open(m_filename.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
m_handle = shm_open(fname.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm);
//If successful change real permissions
if(m_handle >= 0){
::fchmod(m_handle, unix_perm);
}
//If already exists, try to open
else if(errno == EEXIST){
m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
m_handle = shm_open(fname.c_str(), oflag, unix_perm);
//If open fails and errno tells the file does not exist
//(shm was removed between creation and opening tries), just retry
if(m_handle < 0 && errno == ENOENT){
@@ -370,7 +432,7 @@ inline bool shared_memory_object::priv_open_or_create
inline bool shared_memory_object::remove(const char *filename)
{
try{
BOOST_TRY{
std::string filepath;
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
const bool add_leading_slash = false;
@@ -387,14 +449,30 @@ inline bool shared_memory_object::remove(const char *filename)
}
return 0 == shm_unlink(filepath.c_str());
}
catch(...){
BOOST_CATCH(...){
return false;
}
} BOOST_CATCH_END
}
inline void shared_memory_object::truncate(offset_t length)
{
if(0 != ftruncate(m_handle, length)){
#ifdef BOOST_INTERPROCESS_POSIX_FALLOCATE
int ret = EINTR;
while (EINTR == ret) {
ret = posix_fallocate(m_handle, 0, length);
}
if (ret && ret != EOPNOTSUPP && ret != ENODEV){
error_info err(ret);
throw interprocess_exception(err);
}
//ftruncate fallback
#endif //BOOST_INTERPROCESS_POSIX_FALLOCATE
handle_eintr:
if (0 != ftruncate(m_handle, length)){
if (errno == EINTR)
goto handle_eintr;
error_info err(system_error_code());
throw interprocess_exception(err);
}

View File

@@ -52,7 +52,7 @@ class deleter
segment_manager_pointer mp_mngr;
public:
deleter(segment_manager_pointer pmngr)
deleter(segment_manager_pointer pmngr) BOOST_NOEXCEPT
: mp_mngr(pmngr)
{}

View File

@@ -36,7 +36,7 @@ class bad_weak_ptr
{
public:
virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW
virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{ return "boost::interprocess::bad_weak_ptr"; }
};

View File

@@ -25,7 +25,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/checked_delete.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
#include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
@@ -47,18 +46,21 @@ template<class T, class VoidAllocator, class Deleter>
class shared_count
{
public:
typedef typename boost::container::
allocator_traits<VoidAllocator>::pointer void_ptr;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
rebind_pointer<T>::type pointer;
pointer_traits<void_ptr>::template
rebind_pointer<T>::type pointer;
private:
typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<counted_impl>::type counted_impl_ptr;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<sp_counted_base>::type counted_base_ptr;
typedef boost::container::allocator_traits<VoidAllocator> vallocator_traits;
@@ -67,11 +69,11 @@ class shared_count
portable_rebind_alloc<counted_impl>::type counted_impl_allocator;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<const Deleter>::type const_deleter_pointer;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
pointer m_px;
@@ -229,8 +231,10 @@ template<class T, class VoidAllocator, class Deleter>
class weak_count
{
public:
typedef typename boost::container::
allocator_traits<VoidAllocator>::pointer void_ptr;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<T>::type pointer;
private:
@@ -238,10 +242,10 @@ class weak_count
typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<counted_impl>::type counted_impl_ptr;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<sp_counted_base>::type counted_base_ptr;
pointer m_px;

View File

@@ -43,17 +43,19 @@ namespace ipcdetail {
template <class Allocator>
struct scoped_ptr_dealloc_functor
{
typedef typename Allocator::pointer pointer;
typedef typename boost::container::
allocator_traits<Allocator>::pointer pointer;
typedef ipcdetail::integral_constant<unsigned,
boost::interprocess::version<Allocator>::value> alloc_version;
typedef ipcdetail::integral_constant<unsigned, 1> allocator_v1;
typedef ipcdetail::integral_constant<unsigned, 2> allocator_v2;
private:
void priv_deallocate(const typename Allocator::pointer &p, allocator_v1)
void priv_deallocate(const pointer &p, allocator_v1)
{ m_alloc.deallocate(p, 1); }
void priv_deallocate(const typename Allocator::pointer &p, allocator_v2)
void priv_deallocate(const pointer &p, allocator_v2)
{ m_alloc.deallocate_one(p); }
public:
@@ -85,7 +87,11 @@ class sp_counted_impl_pd
allocator_traits<A>::template
portable_rebind_alloc
< const this_type >::type const_this_allocator;
typedef typename this_allocator::pointer this_pointer;
typedef typename boost::container::
allocator_traits<this_allocator>
::pointer this_pointer;
typedef typename boost::container::
allocator_traits<A>::pointer a_pointer;
typedef typename boost::intrusive::
pointer_traits<this_pointer> this_pointer_traits;
@@ -93,10 +99,10 @@ class sp_counted_impl_pd
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
typedef typename boost::intrusive::
pointer_traits<typename A::pointer>::template
pointer_traits<a_pointer>::template
rebind_pointer<const D>::type const_deleter_pointer;
typedef typename boost::intrusive::
pointer_traits<typename A::pointer>::template
pointer_traits<a_pointer>::template
rebind_pointer<const A>::type const_allocator_pointer;
typedef typename D::pointer pointer;
@@ -127,8 +133,7 @@ class sp_counted_impl_pd
//Do it now!
scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> >
deleter_ptr(this_ptr, a_copy);
typedef typename this_allocator::value_type value_type;
ipcdetail::to_raw_pointer(this_ptr)->~value_type();
ipcdetail::to_raw_pointer(this_ptr)->~this_type();
}
void release() // nothrow

View File

@@ -91,49 +91,49 @@ class scoped_ptr
//!Assigns internal pointer as 0 and returns previous pointer. This will
//!avoid deletion on destructor
pointer release()
pointer release() BOOST_NOEXCEPT
{ pointer tmp(m_ptr); m_ptr = 0; return tmp; }
//!Returns a reference to the object pointed to by the stored pointer.
//!Never throws.
reference operator*() const
reference operator*() const BOOST_NOEXCEPT
{ BOOST_ASSERT(m_ptr != 0); return *m_ptr; }
//!Returns the internal stored pointer.
//!Never throws.
pointer &operator->()
pointer &operator->() BOOST_NOEXCEPT
{ BOOST_ASSERT(m_ptr != 0); return m_ptr; }
//!Returns the internal stored pointer.
//!Never throws.
const pointer &operator->() const
const pointer &operator->() const BOOST_NOEXCEPT
{ BOOST_ASSERT(m_ptr != 0); return m_ptr; }
//!Returns the stored pointer.
//!Never throws.
pointer & get()
pointer & get() BOOST_NOEXCEPT
{ return m_ptr; }
//!Returns the stored pointer.
//!Never throws.
const pointer & get() const
const pointer & get() const BOOST_NOEXCEPT
{ return m_ptr; }
typedef pointer this_type::*unspecified_bool_type;
//!Conversion to bool
//!Never throws
operator unspecified_bool_type() const
operator unspecified_bool_type() const BOOST_NOEXCEPT
{ return m_ptr == 0? 0: &this_type::m_ptr; }
//!Returns true if the stored pointer is 0.
//!Never throws.
bool operator! () const // never throws
bool operator! () const BOOST_NOEXCEPT // never throws
{ return m_ptr == 0; }
//!Exchanges the internal pointer and deleter with other scoped_ptr
//!Never throws.
void swap(scoped_ptr & b) // never throws
void swap(scoped_ptr & b) BOOST_NOEXCEPT // never throws
{
::boost::adl_move_swap(static_cast<Deleter&>(*this), static_cast<Deleter&>(b));
::boost::adl_move_swap(m_ptr, b.m_ptr);
@@ -148,7 +148,7 @@ class scoped_ptr
//!Exchanges the internal pointer and deleter with other scoped_ptr
//!Never throws.
template<class T, class D> inline
void swap(scoped_ptr<T, D> & a, scoped_ptr<T, D> & b)
void swap(scoped_ptr<T, D> & a, scoped_ptr<T, D> & b) BOOST_NOEXCEPT
{ a.swap(b); }
//!Returns a copy of the stored pointer

View File

@@ -30,6 +30,7 @@
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/cast_tags.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/interprocess/smart_ptr/detail/shared_count.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/nothrow.hpp>
@@ -37,7 +38,6 @@
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/smart_ptr/deleter.hpp>
#include <boost/static_assert.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <iosfwd> // for std::basic_ostream
@@ -56,7 +56,7 @@ namespace ipcdetail{
template<class T, class VoidAllocator, class Deleter>
inline void sp_enable_shared_from_this
(shared_count<T, VoidAllocator, Deleter> const & pn
,enable_shared_from_this<T, VoidAllocator, Deleter> *pe
,enable_shared_from_this<T, VoidAllocator, Deleter> const*pe
,T *ptr)
{
@@ -103,18 +103,20 @@ class shared_ptr
typedef T element_type;
typedef T value_type;
typedef typename boost::container::
allocator_traits<VoidAllocator>::pointer void_ptr;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<T>::type pointer;
typedef typename ipcdetail::add_reference
<value_type>::type reference;
typedef typename ipcdetail::add_reference
<const value_type>::type const_reference;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<const Deleter>::type const_deleter_pointer;
typedef typename boost::intrusive::
pointer_traits<typename VoidAllocator::pointer>::template
pointer_traits<void_ptr>::template
rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
BOOST_COPYABLE_AND_MOVABLE(shared_ptr)
@@ -395,16 +397,16 @@ template<class T, class ManagedMemory>
inline typename managed_shared_ptr<T, ManagedMemory>::type
make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &)
{
try{
BOOST_TRY{
return typename managed_shared_ptr<T, ManagedMemory>::type
( constructed_object
, managed_memory.template get_allocator<void>()
, managed_memory.template get_deleter<T>()
);
}
catch(...){
BOOST_CATCH(...){
return typename managed_shared_ptr<T, ManagedMemory>::type();
}
} BOOST_CATCH_END
}

View File

@@ -63,8 +63,10 @@ class weak_ptr
private:
// Borland 5.5.1 specific workarounds
typedef weak_ptr<T, A, D> this_type;
typedef typename boost::container::
allocator_traits<A>::pointer alloc_ptr;
typedef typename boost::intrusive::
pointer_traits<typename A::pointer>::template
pointer_traits<alloc_ptr>::template
rebind_pointer<T>::type pointer;
typedef typename ipcdetail::add_reference
<T>::type reference;

View File

@@ -88,7 +88,7 @@ class basic_bufferbuf
: basic_streambuf_t(), m_mode(mode), m_buffer(buf), m_length(length)
{ this->set_pointers(); }
virtual ~basic_bufferbuf(){}
virtual ~basic_bufferbuf() BOOST_OVERRIDE {}
public:
//!Returns the pointer and size of the internal buffer.
@@ -115,14 +115,14 @@ class basic_bufferbuf
}
protected:
virtual int_type underflow()
virtual int_type underflow() BOOST_OVERRIDE
{
// Precondition: gptr() >= egptr(). Returns a character, if available.
return this->gptr() != this->egptr() ?
CharTraits::to_int_type(*this->gptr()) : CharTraits::eof();
}
virtual int_type pbackfail(int_type c = CharTraits::eof())
virtual int_type pbackfail(int_type c = CharTraits::eof()) BOOST_OVERRIDE
{
if(this->gptr() != this->eback()) {
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
@@ -132,7 +132,7 @@ class basic_bufferbuf
}
else if(m_mode & std::ios_base::out) {
this->gbump(-1);
*this->gptr() = c;
*this->gptr() = CharTraits::to_char_type(c);
return c;
}
else
@@ -147,7 +147,7 @@ class basic_bufferbuf
return CharTraits::eof();
}
virtual int_type overflow(int_type c = CharTraits::eof())
virtual int_type overflow(int_type c = CharTraits::eof()) BOOST_OVERRIDE
{
if(m_mode & std::ios_base::out) {
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
@@ -181,7 +181,7 @@ class basic_bufferbuf
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir,
std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
= std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE
{
bool in = false;
bool out = false;
@@ -238,7 +238,7 @@ class basic_bufferbuf
return pos_type(off_type(-1));
else {
this->setp(this->pbase(), this->pbase() + n);
this->pbump(off);
this->pbump(static_cast<int>(off));
}
}
@@ -246,7 +246,7 @@ class basic_bufferbuf
}
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
= std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE
{ return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); }
private:

View File

@@ -115,7 +115,7 @@ class basic_vectorbuf
mp_high_water = base_t::pptr();
}
//This does not reallocate
m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0));
m_vect.resize(std::size_t(mp_high_water - (m_vect.size() ? &m_vect[0] : 0)));
}
//Now swap vector
m_vect.swap(vect);
@@ -138,7 +138,7 @@ class basic_vectorbuf
if(m_vect.size() > high_pos){
m_vect.resize(high_pos);
//But we must update end write pointer because vector size is now shorter
int old_pos = base_t::pptr() - base_t::pbase();
int old_pos = (int)(base_t::pptr() - base_t::pbase());
const_cast<basic_vectorbuf*>(this)->base_t::setp(old_ptr, old_ptr + high_pos);
const_cast<basic_vectorbuf*>(this)->base_t::pbump(old_pos);
}
@@ -214,7 +214,7 @@ class basic_vectorbuf
}
protected:
virtual int_type underflow()
virtual int_type underflow() BOOST_OVERRIDE
{
if (base_t::gptr() == 0)
return CharTraits::eof();
@@ -229,7 +229,7 @@ class basic_vectorbuf
return CharTraits::eof();
}
virtual int_type pbackfail(int_type c = CharTraits::eof())
virtual int_type pbackfail(int_type c = CharTraits::eof()) BOOST_OVERRIDE
{
if(this->gptr() != this->eback()) {
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
@@ -239,7 +239,7 @@ class basic_vectorbuf
}
else if(m_mode & std::ios_base::out) {
this->gbump(-1);
*this->gptr() = c;
*this->gptr() = CharTraits::to_char_type(c);
return c;
}
else
@@ -254,7 +254,7 @@ class basic_vectorbuf
return CharTraits::eof();
}
virtual int_type overflow(int_type c = CharTraits::eof())
virtual int_type overflow(int_type c = CharTraits::eof()) BOOST_OVERRIDE
{
if(m_mode & std::ios_base::out) {
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
@@ -289,7 +289,7 @@ class basic_vectorbuf
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir,
std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
= std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE
{
//Get seek mode
bool in(0 != (mode & std::ios_base::in)), out(0 != (mode & std::ios_base::out));
@@ -351,13 +351,13 @@ class basic_vectorbuf
base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr());
if (out){
base_t::setp(base_t::pbase(), base_t::epptr());
base_t::pbump(newoff);
base_t::pbump(static_cast<int>(newoff));
}
return pos_type(newoff);
}
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode
= std::ios_base::in | std::ios_base::out)
= std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE
{ return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); }
private:

View File

@@ -0,0 +1,29 @@
// cv_status.hpp
//
// Copyright (C) 2011 Vicente J. Botet Escriba
// Copyright (C) 2021 Ion Gaztanaga
//
// 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)
#ifndef BOOST_INTERPROCESS_CV_STATUS_HPP
#define BOOST_INTERPROCESS_CV_STATUS_HPP
#include <boost/core/scoped_enum.hpp>
namespace boost {
namespace interprocess {
// enum class cv_status;
BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status)
{
no_timeout,
timeout
}
BOOST_SCOPED_ENUM_DECLARE_END(cv_status)
} //namespace interprocess
} //namespace boost
#endif // header

View File

@@ -23,16 +23,17 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/spin/wait.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
namespace boost {
namespace interprocess {
namespace ipcdetail {
template<class MutexType>
bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time)
template<class MutexType, class TimePoint>
bool try_based_timed_lock(MutexType &m, const TimePoint &abs_time)
{
//Same as lock()
if(abs_time == boost::posix_time::pos_infin){
if(is_pos_infinity(abs_time)){
m.lock();
return true;
}
@@ -45,7 +46,7 @@ bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time
}
else{
spin_wait swait;
while(microsec_clock::universal_time() < abs_time){
while(microsec_clock<TimePoint>::universal_time() < abs_time){
if(m.try_lock()){
return true;
}
@@ -73,46 +74,19 @@ void try_based_lock(MutexType &m)
}
template<class MutexType>
void timed_based_lock(MutexType &m, unsigned const uCheckPeriodSec)
void timeout_when_locking_aware_lock(MutexType &m)
{
const boost::posix_time::time_duration dur(0, 0, uCheckPeriodSec);
boost::posix_time::ptime deadline(microsec_clock::universal_time()+dur);
if(!m.timed_lock(deadline)){
spin_wait swait;
do{
deadline = microsec_clock::universal_time()+dur;
if(m.timed_lock(deadline)){
break;
}
else{
swait.yield();
}
#ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
if (!m.timed_lock(microsec_clock<ustime>::universal_time()
+ usduration_milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS)))
{
throw interprocess_exception(timeout_when_locking_error
, "Interprocess mutex timeout when locking. Possible deadlock: "
"owner died without unlocking?");
}
while(1);
}
}
template<class MutexType>
void timed_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time, unsigned const uCheckPeriodSec)
{
const boost::posix_time::time_duration dur(0, 0, uCheckPeriodSec);
boost::posix_time::ptime deadline(microsec_clock::universal_time()+dur);
if(abs_time <= deadline){
m.timed_lock(abs_time);
}
else if(!m.timed_lock(deadline)){
spin_wait swait;
do{
deadline = microsec_clock::universal_time()+dur;
if(m.timed_lock(deadline)){
break;
}
else{
swait.yield();
}
}
while(1);
}
#else
m.lock();
#endif
}
} //namespace ipcdetail

View File

@@ -193,130 +193,124 @@ class condition_algorithm_8a
typedef typename ConditionMembers::integer_type integer_type;
public:
template<class Lock>
static bool wait ( ConditionMembers &data, Lock &lock
, bool timeout_enabled, const boost::posix_time::ptime &abs_time);
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;
template<bool TimeoutEnabled, class Lock, class TimePoint>
static bool wait ( ConditionMembers &data, Lock &lock, const TimePoint &abs_time)
{
scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
//Initialize to avoid warnings
integer_type nsignals_was_left = 0;
integer_type nwaiters_was_gone = 0;
if ( 0 != data.get_nwaiters_to_unblock() ) { // the gate is closed!!!
if ( 0 == data.get_nwaiters_blocked() ) { // NO-OP
data.get_sem_block_lock().wait();
++data.get_nwaiters_blocked();
data.get_sem_block_lock().post();
//Unlock external lock and program for relock
lock_inverter<Lock> inverted_lock(lock);
scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
bool bTimedOut = !do_sem_timed_wait(data.get_sem_block_queue(), abs_time, bool_<TimeoutEnabled>());
{
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
}
//lock.lock(); called from unlocker destructor
return ( bTimedOut ) ? false : true;
}
static void 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;
}
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 Lock>
inline bool condition_algorithm_8a<ConditionMembers>::wait
( ConditionMembers &data
, Lock &lock
, bool tout_enabled
, const boost::posix_time::ptime &abs_time
)
{
//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();
//Unlock external lock and program for relock
lock_inverter<Lock> inverted_lock(lock);
scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
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()
data.get_sem_block_queue().post(nsignals_to_issue);
}
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
}
//lock.lock(); called from unlocker destructor
return ( bTimedOut ) ? false : true;
}
private:
template<class TimePoint>
static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &abs_time, bool_<true>)
{ return sem.timed_wait(abs_time); }
template<class TimePoint>
static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &, bool_<false>)
{ sem.wait(); return true; }
};
template<class ConditionMembers>
class condition_8a_wrapper
@@ -326,7 +320,7 @@ class condition_8a_wrapper
condition_8a_wrapper &operator=(const condition_8a_wrapper &);
ConditionMembers m_data;
typedef ipcdetail::condition_algorithm_8a<ConditionMembers> algo_type;
typedef condition_algorithm_8a<ConditionMembers> algo_type;
public:
@@ -352,7 +346,7 @@ class condition_8a_wrapper
{
if (!lock)
throw lock_exception();
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
algo_type::template wait<false>(m_data, lock, 0);
}
template <typename L, typename Pr>
@@ -362,24 +356,24 @@ class condition_8a_wrapper
throw lock_exception();
while (!pred())
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
algo_type::template wait<false>(m_data, lock, 0);
}
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
template <typename L, class TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{
if (!lock)
throw lock_exception();
return algo_type::wait(m_data, lock, true, abs_time);
return algo_type::template wait<true>(m_data, lock, abs_time);
}
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
template <typename L, class TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
while (!pred()){
if (!algo_type::wait(m_data, lock, true, abs_time))
if (!algo_type::template wait<true>(m_data, lock, abs_time))
return pred();
}
return true;

View File

@@ -68,85 +68,52 @@ class condition_any_algorithm
typedef typename ConditionAnyMembers::mutex_type mutex_type;
typedef typename ConditionAnyMembers::condvar_type condvar_type;
template <class Lock>
static void do_wait(ConditionAnyMembers &data, Lock& lock);
template <class Lock>
static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time);
public:
template<class Lock>
static bool wait ( ConditionAnyMembers &data, Lock &mut
, bool timeout_enabled, const boost::posix_time::ptime &abs_time);
static void signal( ConditionAnyMembers &data, bool broadcast);
template <class Lock>
static void wait(ConditionAnyMembers& data, Lock& lock)
{
//lock internal before unlocking external to avoid race with a notifier
scoped_lock<mutex_type> internal_lock(data.get_mutex());
{
lock_inverter<Lock> inverted_lock(lock);
scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
{ //unlock internal first to avoid deadlock with near simultaneous waits
scoped_lock<mutex_type> internal_unlock;
internal_lock.swap(internal_unlock);
data.get_condvar().wait(internal_unlock);
}
}
}
template <class Lock, class TimePoint>
static bool timed_wait(ConditionAnyMembers &data, Lock& lock, const TimePoint &abs_time)
{
//lock internal before unlocking external to avoid race with a notifier
scoped_lock<mutex_type> internal_lock(data.get_mutex());
{
//Unlock external lock and program for relock
lock_inverter<Lock> inverted_lock(lock);
scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
{ //unlock internal first to avoid deadlock with near simultaneous waits
scoped_lock<mutex_type> internal_unlock;
internal_lock.swap(internal_unlock);
return data.get_condvar().timed_wait(internal_unlock, abs_time);
}
}
}
static void signal(ConditionAnyMembers& data, bool broadcast)
{
scoped_lock<mutex_type> internal_lock(data.get_mutex());
if(broadcast){
data.get_condvar().notify_all();
}
else{
data.get_condvar().notify_one();
}
}
};
template<class ConditionAnyMembers>
void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast)
{
scoped_lock<mutex_type> internal_lock(data.get_mutex());
if(broadcast){
data.get_condvar().notify_all();
}
else{
data.get_condvar().notify_one();
}
}
template<class ConditionAnyMembers>
template<class Lock>
bool condition_any_algorithm<ConditionAnyMembers>::wait
( ConditionAnyMembers &data
, Lock &lock
, bool tout_enabled
, const boost::posix_time::ptime &abs_time)
{
if(tout_enabled){
return condition_any_algorithm::do_timed_wait(data, lock, abs_time);
}
else{
condition_any_algorithm::do_wait(data, lock);
return true;
}
}
template<class ConditionAnyMembers>
template <class Lock>
void condition_any_algorithm<ConditionAnyMembers>::do_wait
(ConditionAnyMembers &data, Lock& lock)
{
//lock internal before unlocking external to avoid race with a notifier
scoped_lock<mutex_type> internal_lock(data.get_mutex());
{
lock_inverter<Lock> inverted_lock(lock);
scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
{ //unlock internal first to avoid deadlock with near simultaneous waits
scoped_lock<mutex_type> internal_unlock;
internal_lock.swap(internal_unlock);
data.get_condvar().wait(internal_unlock);
}
}
}
template<class ConditionAnyMembers>
template <class Lock>
bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait
(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time)
{
//lock internal before unlocking external to avoid race with a notifier
scoped_lock<mutex_type> internal_lock(data.get_mutex());
{
//Unlock external lock and program for relock
lock_inverter<Lock> inverted_lock(lock);
scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
{ //unlock internal first to avoid deadlock with near simultaneous waits
scoped_lock<mutex_type> internal_unlock;
internal_lock.swap(internal_unlock);
return data.get_condvar().timed_wait(internal_unlock, abs_time);
}
}
}
template<class ConditionAnyMembers>
class condition_any_wrapper
@@ -176,12 +143,12 @@ class condition_any_wrapper
void notify_all()
{ algo_type::signal(m_data, true); }
template <typename L>
void wait(L& lock)
template <typename Lock>
void wait(Lock& lock)
{
if (!lock)
throw lock_exception();
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
algo_type::wait(m_data, lock);
}
template <typename L, typename Pr>
@@ -191,24 +158,24 @@ class condition_any_wrapper
throw lock_exception();
while (!pred())
algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
algo_type::wait(m_data, lock);
}
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
template <typename L, typename TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{
if (!lock)
throw lock_exception();
return algo_type::wait(m_data, lock, true, abs_time);
return algo_type::timed_wait(m_data, lock, abs_time);
}
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
template <typename L, typename TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
while (!pred()){
if (!algo_type::wait(m_data, lock, true, abs_time))
if (!algo_type::timed_wait(m_data, lock, abs_time))
return pred();
}
return true;

View File

@@ -35,18 +35,18 @@ class internal_mutex_lock
typedef typename Lock::mutex_type::internal_mutex_type mutex_type;
internal_mutex_lock(Lock &l)
BOOST_INTERPROCESS_FORCEINLINE internal_mutex_lock(Lock &l)
: l_(l)
{}
mutex_type* mutex() const
BOOST_INTERPROCESS_FORCEINLINE mutex_type* mutex() const
{ return l_ ? &l_.mutex()->internal_mutex() : 0; }
void lock() { l_.lock(); }
BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.lock(); }
void unlock() { l_.unlock(); }
BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.unlock(); }
operator unspecified_bool_type() const
BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const
{ return l_ ? &internal_mutex_lock::lock : 0; }
private:
@@ -58,11 +58,13 @@ class lock_inverter
{
Lock &l_;
public:
lock_inverter(Lock &l)
BOOST_INTERPROCESS_FORCEINLINE lock_inverter(Lock &l)
: l_(l)
{}
void lock() { l_.unlock(); }
void unlock() { l_.lock(); }
BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.unlock(); }
BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.lock(); }
};
template <class Lock>
@@ -71,12 +73,15 @@ class lock_to_sharable
Lock &l_;
public:
explicit lock_to_sharable(Lock &l)
BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_sharable(Lock &l)
: l_(l)
{}
void lock() { l_.lock_sharable(); }
bool try_lock(){ return l_.try_lock_sharable(); }
void unlock() { l_.unlock_sharable(); }
BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.lock_sharable(); }
BOOST_INTERPROCESS_FORCEINLINE bool try_lock(){ return l_.try_lock_sharable(); }
BOOST_INTERPROCESS_FORCEINLINE void unlock() { l_.unlock_sharable(); }
};
template <class Lock>
@@ -85,11 +90,16 @@ class lock_to_wait
Lock &l_;
public:
explicit lock_to_wait(Lock &l)
BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_wait(Lock &l)
: l_(l)
{}
void lock() { l_.wait(); }
bool try_lock(){ return l_.try_wait(); }
BOOST_INTERPROCESS_FORCEINLINE void lock() { l_.wait(); }
BOOST_INTERPROCESS_FORCEINLINE bool try_lock() { return l_.try_wait(); }
template<class TimePoint>
BOOST_INTERPROCESS_FORCEINLINE bool timed_lock(const TimePoint &abs_time)
{ return l_.timed_wait(abs_time); }
};
} //namespace ipcdetail

View File

@@ -24,7 +24,6 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/move/utility_core.hpp>
@@ -51,7 +50,7 @@ class file_lock
public:
//!Constructs an empty file mapping.
//!Does not throw
file_lock()
file_lock() BOOST_NOEXCEPT
: m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
{}
@@ -59,17 +58,26 @@ class file_lock
//!exist or there are no operating system resources.
file_lock(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Opens a file lock. Throws interprocess_exception if the file does not
//!exist or there are no operating system resources.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
file_lock(const wchar_t *name);
#endif
//!Moves the ownership of "moved"'s file mapping object to *this.
//!After the call, "moved" does not represent any file mapping object.
//!Does not throw
file_lock(BOOST_RV_REF(file_lock) moved)
file_lock(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT
: m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
{ this->swap(moved); }
//!Moves the ownership of "moved"'s file mapping to *this.
//!After the call, "moved" does not represent any file mapping.
//!Does not throw
file_lock &operator=(BOOST_RV_REF(file_lock) moved)
file_lock &operator=(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT
{
file_lock tmp(boost::move(moved));
this->swap(tmp);
@@ -81,7 +89,7 @@ class file_lock
//!Swaps two file_locks.
//!Does not throw.
void swap(file_lock &other)
void swap(file_lock &other) BOOST_NOEXCEPT
{
file_handle_t tmp = m_file_hnd;
m_file_hnd = other.m_file_hnd;
@@ -90,26 +98,55 @@ class file_lock
//Exclusive locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
//! and if another thread has exclusive, or sharable ownership of
//! the mutex, it waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! without waiting. If no other thread has exclusive, or sharable
//! ownership of the mutex this succeeds.
//!Returns: If it can acquire exclusive ownership immediately returns true.
//! If it has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! waiting if necessary until no other thread has exclusive, or sharable
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
@@ -118,12 +155,23 @@ class file_lock
//Sharable locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
//! and if another thread has exclusive ownership of the mutex, waits until
//! it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that owns a mutex object calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! without waiting. If no other thread has exclusive ownership of the
//! mutex this succeeds.
@@ -132,17 +180,39 @@ class file_lock
//!Throws: interprocess_exception on error.
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! waiting if necessary until no other thread has exclusive ownership of
//! the mutex or abs_time is reached.
//!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
file_handle_t m_file_hnd;
@@ -160,6 +230,20 @@ inline file_lock::file_lock(const char *name)
}
}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline file_lock::file_lock(const wchar_t *name)
{
m_file_hnd = ipcdetail::open_existing_file(name, read_write);
if(m_file_hnd == ipcdetail::invalid_file()){
error_info err(system_error_code());
throw interprocess_exception(err);
}
}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline file_lock::~file_lock()
{
if(m_file_hnd != ipcdetail::invalid_file()){
@@ -186,7 +270,8 @@ inline bool file_lock::try_lock()
return result;
}
inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool file_lock::timed_lock(const TimePoint &abs_time)
{ return ipcdetail::try_based_timed_lock(*this, abs_time); }
inline void file_lock::unlock()
@@ -215,7 +300,8 @@ inline bool file_lock::try_lock_sharable()
return result;
}
inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool file_lock::timed_lock_sharable(const TimePoint &abs_time)
{
ipcdetail::lock_to_sharable<file_lock> lsh(*this);
return ipcdetail::try_based_timed_lock(lsh, abs_time);

View File

@@ -24,23 +24,23 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
#include <boost/interprocess/sync/posix/condition.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
#define BOOST_INTERPROCESS_CONDITION_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_DOXYGEN_INVOKED)
#define BOOST_INTERPROCESS_CONDITION_USE_WINAPI
#else
//spin_condition is used
#include <boost/interprocess/sync/spin/condition.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -49,14 +49,6 @@
//!Describes process-shared variables interprocess_condition class
namespace boost {
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace posix_time
{ class ptime; }
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace interprocess {
class named_condition;
@@ -121,8 +113,8 @@ class interprocess_condition
//!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)
template <typename L, class TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return m_condition.timed_wait(internal_lock, abs_time);
@@ -131,28 +123,48 @@ class interprocess_condition
//!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)
template <typename L, class TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return m_condition.timed_wait(internal_lock, abs_time, pred);
}
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
ipcdetail::spin_condition m_condition;
#elif defined(BOOST_INTERPROCESS_USE_POSIX)
#undef BOOST_INTERPROCESS_USE_POSIX
#if defined(BOOST_INTERPROCESS_CONDITION_USE_POSIX)
ipcdetail::posix_condition m_condition;
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
#undef BOOST_INTERPROCESS_USE_WINDOWS
ipcdetail::windows_condition m_condition;
#elif defined(BOOST_INTERPROCESS_CONDITION_USE_WINAPI)
ipcdetail::winapi_condition m_condition;
#else
#error "Unknown platform for interprocess_mutex"
ipcdetail::spin_condition m_condition;
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};

View File

@@ -24,7 +24,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -36,14 +36,6 @@
//!Describes process-shared variables interprocess_condition_any class
namespace boost {
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace posix_time
{ class ptime; }
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace interprocess {
//!This class is a condition variable that can be placed in shared memory or
@@ -117,16 +109,40 @@ class interprocess_condition_any
//!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)
template <typename L, class TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{ return m_cond.timed_wait(lock, 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)
template <typename L, class TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{ return m_cond.timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
};
} //namespace interprocess

View File

@@ -28,30 +28,28 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/assert.hpp>
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
#include <boost/interprocess/sync/posix/mutex.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
#define BOOST_INTERPROCESS_MUTEX_USE_POSIX
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
//Experimental...
#define BOOST_INTERPROCESS_MUTEX_USE_WINAPI
#include <boost/interprocess/sync/windows/mutex.hpp>
#define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#else
//spin_mutex is used
#include <boost/interprocess/sync/spin/mutex.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
namespace boost {
namespace interprocess {
namespace ipcdetail{
namespace robust_emulation_helpers {
namespace boost {
namespace interprocess {
namespace ipcdetail{
namespace robust_emulation_helpers {
template<class T>
class mutex_traits;
}}}}
template<class T>
class mutex_traits;
}}}}
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -76,21 +74,16 @@ class interprocess_mutex
friend class interprocess_condition;
public:
#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#if defined(BOOST_INTERPROCESS_MUTEX_USE_POSIX)
typedef ipcdetail::posix_mutex internal_mutex_type;
#elif defined(BOOST_INTERPROCESS_MUTEX_USE_WINAPI)
typedef ipcdetail::winapi_mutex internal_mutex_type;
#else
typedef ipcdetail::spin_mutex internal_mutex_type;
private:
friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
void take_ownership(){ m_mutex.take_ownership(); }
public:
#elif defined(BOOST_INTERPROCESS_USE_POSIX)
#undef BOOST_INTERPROCESS_USE_POSIX
typedef ipcdetail::posix_mutex internal_mutex_type;
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
#undef BOOST_INTERPROCESS_USE_WINDOWS
typedef ipcdetail::windows_mutex internal_mutex_type;
#else
#error "Unknown platform for interprocess_mutex"
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -104,20 +97,34 @@ class interprocess_mutex
//!the result is undefined. Does not throw.
~interprocess_mutex();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain ownership of the mutex, and
//! if another thread has ownership of the mutex, it waits until it can
//! obtain the ownership. If a thread takes ownership of the mutex the
//! mutex must be unlocked by the same mutex.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain ownership of the mutex, and
//! if another thread has ownership of the mutex returns immediately.
//!Returns: If the thread acquires ownership of the mutex, returns true, if
//! the another thread has ownership of the mutex, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread will try to obtain exclusive ownership of the
//! mutex if it can do so in until the specified time is reached. If the
//! mutex supports recursive locking, the mutex must be unlocked the same
@@ -125,7 +132,22 @@ class interprocess_mutex
//!Returns: If the thread acquires ownership of the mutex, returns true, if
//! the timeout expires returns false.
//!Throws: interprocess_exception on error.
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: interprocess_exception on error.
@@ -155,26 +177,13 @@ inline interprocess_mutex::interprocess_mutex(){}
inline interprocess_mutex::~interprocess_mutex(){}
inline void interprocess_mutex::lock()
{
#ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
boost::posix_time::ptime wait_time
= microsec_clock::universal_time()
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
if (!m_mutex.timed_lock(wait_time))
{
throw interprocess_exception(timeout_when_locking_error
, "Interprocess mutex timeout when locking. Possible deadlock: "
"owner died without unlocking?");
}
#else
m_mutex.lock();
#endif
}
{ ipcdetail::timeout_when_locking_aware_lock(m_mutex); }
inline bool interprocess_mutex::try_lock()
{ return m_mutex.try_lock(); }
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template <class TimePoint>
inline bool interprocess_mutex::timed_lock(const TimePoint &abs_time)
{ return m_mutex.timed_lock(abs_time); }
inline void interprocess_mutex::unlock()

View File

@@ -39,33 +39,30 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
#include <boost/assert.hpp>
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
(defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES))
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \
defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES)
#include <boost/interprocess/sync/posix/recursive_mutex.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
//Experimental...
#include <boost/interprocess/sync/windows/recursive_mutex.hpp>
#define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI
#else
//spin_recursive_mutex is used
#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#endif
namespace boost {
namespace interprocess {
namespace ipcdetail{
namespace robust_emulation_helpers {
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
namespace boost {
namespace interprocess {
namespace ipcdetail{
namespace robust_emulation_helpers {
template<class T>
class mutex_traits;
}}}}
template<class T>
class mutex_traits;
}}}}
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -101,19 +98,39 @@ class interprocess_recursive_mutex
//! mutex must be unlocked by the same mutex. The mutex must be unlocked
//! the same number of times it is locked.
//!Throws: interprocess_exception on error.
//!
//!Note: A program shall not deadlock if the thread that has ownership calls
//! this function.
void lock();
//!Tries to lock the interprocess_mutex, returns false when interprocess_mutex
//!is already locked, returns true when success. The mutex must be unlocked
//!the same number of times it is locked.
//!Throws: interprocess_exception if a severe error is found
//!
//!Note: A program shall not deadlock if the thread that has ownership calls
//! this function.
bool try_lock();
//!Tries to lock the interprocess_mutex, if interprocess_mutex can't be locked before
//!abs_time time, returns false. The mutex must be unlocked
//! the same number of times it is locked.
//!Throws: interprocess_exception if a severe error is found
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program shall not deadlock if the thread that has ownership calls
//! this function.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//! If the mutex supports recursive locking, the mutex must be unlocked the
@@ -123,19 +140,14 @@ class interprocess_recursive_mutex
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#if defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX)
ipcdetail::posix_recursive_mutex mutex;
#elif defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI)
ipcdetail::winapi_recursive_mutex mutex;
#else
void take_ownership(){ mutex.take_ownership(); }
friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_recursive_mutex>;
ipcdetail::spin_recursive_mutex mutex;
#elif defined(BOOST_INTERPROCESS_USE_POSIX)
#undef BOOST_INTERPROCESS_USE_POSIX
ipcdetail::posix_recursive_mutex mutex;
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
#undef BOOST_INTERPROCESS_USE_WINDOWS
ipcdetail::windows_recursive_mutex mutex;
#else
#error "Unknown platform for interprocess_mutex"
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
@@ -151,23 +163,13 @@ inline interprocess_recursive_mutex::interprocess_recursive_mutex(){}
inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){}
inline void interprocess_recursive_mutex::lock()
{
#ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
boost::posix_time::ptime wait_time
= microsec_clock::universal_time()
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
if (!mutex.timed_lock(wait_time)){
throw interprocess_exception(timeout_when_locking_error, "Interprocess mutex timeout when locking. Possible deadlock: owner died without unlocking?");
}
#else
mutex.lock();
#endif
}
{ ipcdetail::timeout_when_locking_aware_lock(mutex); }
inline bool interprocess_recursive_mutex::try_lock()
{ return mutex.try_lock(); }
inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool interprocess_recursive_mutex::timed_lock(const TimePoint &abs_time)
{ return mutex.timed_lock(abs_time); }
inline void interprocess_recursive_mutex::unlock()

View File

@@ -26,19 +26,21 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/interprocess/sync/detail/common_algorithms.hpp>
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
(defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES))
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \
defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES)
#include <boost/interprocess/sync/posix/semaphore.hpp>
#define BOOST_INTERPROCESS_USE_POSIX
//Experimental...
#define BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
//Experimental...
#include <boost/interprocess/sync/windows/semaphore.hpp>
#define BOOST_INTERPROCESS_USE_WINDOWS
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#define BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI
#else
//spin_semaphore is used
#include <boost/interprocess/sync/spin/semaphore.hpp>
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
@@ -87,22 +89,21 @@ class interprocess_semaphore
//!to the posted or the timeout expires. If the timeout expires, the
//!function returns false. If the interprocess_semaphore is posted the function
//!returns true. If there is an error throws sem_exception
bool timed_wait(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_wait(const TimePoint &abs_time);
//!Returns the interprocess_semaphore count
// int get_count() const;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
ipcdetail::spin_semaphore m_sem;
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
#undef BOOST_INTERPROCESS_USE_WINDOWS
ipcdetail::windows_semaphore m_sem;
#if defined(BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX)
typedef ipcdetail::posix_semaphore internal_sem_t;
#elif defined(BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI)
typedef ipcdetail::winapi_semaphore internal_sem_t;
#else
#undef BOOST_INTERPROCESS_USE_POSIX
ipcdetail::posix_semaphore m_sem;
#endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
typedef ipcdetail::spin_semaphore internal_sem_t;
#endif //#if defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
internal_sem_t m_sem;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
@@ -120,22 +121,15 @@ inline interprocess_semaphore::~interprocess_semaphore(){}
inline void interprocess_semaphore::wait()
{
#ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
boost::posix_time::ptime wait_time
= microsec_clock::universal_time()
+ boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
if (!m_sem.timed_wait(wait_time))
{
throw interprocess_exception(timeout_when_waiting_error, "Interprocess semaphore timeout when waiting. Possible deadlock: owner died without posting?");
}
#else
m_sem.wait();
#endif
ipcdetail::lock_to_wait<internal_sem_t> ltw(m_sem);
timeout_when_locking_aware_lock(ltw);
}
inline bool interprocess_semaphore::try_wait()
{ return m_sem.try_wait(); }
inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool interprocess_semaphore::timed_wait(const TimePoint &abs_time)
{ return m_sem.timed_wait(abs_time); }
inline void interprocess_semaphore::post()

View File

@@ -26,7 +26,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <climits>
@@ -59,26 +58,55 @@ class interprocess_sharable_mutex
//Exclusive locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
//! and if another thread has exclusive or sharable ownership of
//! the mutex, it waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! without waiting. If no other thread has exclusive or sharable
//! ownership of the mutex this succeeds.
//!Returns: If it can acquire exclusive ownership immediately returns true.
//! If it has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! waiting if necessary until no other thread has exclusive or sharable
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
@@ -87,32 +115,76 @@ class interprocess_sharable_mutex
//Sharable locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
//! and if another thread has exclusive ownership of the mutex,
//! waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! without waiting. If no other thread has exclusive ownership
//! of the mutex this succeeds.
//!Returns: If it can acquire sharable ownership immediately returns true. If it
//! has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! waiting if necessary until no other thread has exclusive
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef scoped_lock<interprocess_mutex> scoped_lock_t;
@@ -214,8 +286,9 @@ inline bool interprocess_sharable_mutex::try_lock()
return true;
}
template<class TimePoint>
inline bool interprocess_sharable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
(const TimePoint &abs_time)
{
scoped_lock_t lck(m_mut, abs_time);
if(!lck.owns()) return false;
@@ -297,8 +370,9 @@ inline bool interprocess_sharable_mutex::try_lock_sharable()
return true;
}
template<class TimePoint>
inline bool interprocess_sharable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
(const TimePoint &abs_time)
{
scoped_lock_t lck(m_mut, abs_time);
if(!lck.owns()) return false;

View File

@@ -24,7 +24,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <climits>
@@ -57,26 +56,56 @@ class interprocess_upgradable_mutex
//Exclusive locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
//! and if another thread has exclusive, sharable or upgradable ownership of
//! the mutex, it waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! without waiting. If no other thread has exclusive, sharable or upgradable
//! ownership of the mutex this succeeds.
//!Returns: If it can acquire exclusive ownership immediately returns true.
//! If it has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! waiting if necessary until no other thread has exclusive, sharable or
//! upgradable ownership of the mutex or abs_time is reached.
//!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
@@ -85,54 +114,117 @@ class interprocess_upgradable_mutex
//Sharable locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
//! and if another thread has exclusive ownership of the mutex,
//! waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! without waiting. If no other thread has exclusive ownership
//! of the mutex this succeeds.
//!Returns: If it can acquire sharable ownership immediately returns true. If it
//! has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! waiting if necessary until no other thread has exclusive
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//Upgradable locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
//! and if another thread has exclusive or upgradable ownership of the mutex,
//! waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock_upgradable();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire upgradable ownership of the mutex
//! without waiting. If no other thread has exclusive or upgradable ownership
//! of the mutex this succeeds.
//!Returns: If it can acquire upgradable ownership immediately returns true.
//! If it has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock_upgradable();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire upgradable ownership of the mutex
//! waiting if necessary until no other thread has exclusive or upgradable
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock_upgradable(const TimePoint &abs_time);
//!Precondition: The thread must have upgradable ownership of the mutex.
//!Effects: The calling thread releases the upgradable ownership of the mutex.
@@ -183,7 +275,8 @@ class interprocess_upgradable_mutex
//! will maintain upgradable ownership.
//!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
//!Throws: An exception derived from interprocess_exception on error. */
bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time);
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The thread atomically releases sharable ownership and tries to acquire
@@ -326,8 +419,8 @@ inline bool interprocess_upgradable_mutex::try_lock()
return true;
}
inline bool interprocess_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
bool interprocess_upgradable_mutex::timed_lock(const TimePoint &abs_time)
{
//Mutexes and condvars handle just fine infinite abs_times
//so avoid checking it here
@@ -412,8 +505,8 @@ inline bool interprocess_upgradable_mutex::try_lock_upgradable()
return true;
}
inline bool interprocess_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
bool interprocess_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time)
{
//Mutexes and condvars handle just fine infinite abs_times
//so avoid checking it here
@@ -489,8 +582,8 @@ inline bool interprocess_upgradable_mutex::try_lock_sharable()
return true;
}
inline bool interprocess_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool interprocess_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time)
{
//Mutexes and condvars handle just fine infinite abs_times
//so avoid checking it here
@@ -602,8 +695,8 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock()
return true;
}
inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time)
{
//Mutexes and condvars handle just fine infinite abs_times
//so avoid checking it here

View File

@@ -26,14 +26,6 @@
//!Describes the lock options with associated with interprocess_mutex lock constructors.
namespace boost {
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace posix_time
{ class ptime; }
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace interprocess {
//!Type to indicate to a mutex lock constructor that must not lock the mutex.

View File

@@ -21,15 +21,16 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#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/detail/locks.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
#define BOOST_INTERPROCESS_NAMED_CONDITION_USE_WINAPI
#else
#include <boost/interprocess/sync/shm/named_condition.hpp>
#endif
@@ -56,9 +57,10 @@ class named_condition
named_condition &operator=(const named_condition &);
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions());
named_condition(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global condition with a name.
//!If the condition is created, this call is equivalent to
@@ -66,12 +68,45 @@ class named_condition
//!If the condition is already created, this call is equivalent
//!named_condition(open_only_t, ... )
//!Does not throw
named_condition(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
named_condition(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global condition with a name if that condition is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
named_condition(open_only_t open_only, const char *name);
named_condition(open_only_t, const char *name);
//!Opens a global condition with a name if that condition is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_condition(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global condition with a name.
//!If the condition is created, this call is equivalent to
//!named_condition(create_only_t, ... )
//!If the condition is already created, this call is equivalent
//!named_condition(open_only_t, ... )
//!Does not throw
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_condition(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global condition with a name if that condition is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_condition(open_only_t, const wchar_t *name);
#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -105,23 +140,58 @@ class named_condition
//!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);
template <typename L, class TimePoint>
bool timed_wait(L& lock, const TimePoint &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);
template <typename L, class TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred);
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined(BOOST_INTERPROCESS_USE_WINDOWS)
typedef ipcdetail::windows_named_condition condition_type;
#if defined(BOOST_INTERPROCESS_NAMED_CONDITION_USE_WINAPI)
typedef ipcdetail::winapi_named_condition condition_type;
#else
typedef ipcdetail::shm_named_condition condition_type;
#endif
@@ -150,6 +220,23 @@ inline named_condition::named_condition(open_only_t, const char *name)
: m_cond(open_only_t(), name)
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_condition::named_condition(create_only_t, const wchar_t *name, const permissions &perm)
: m_cond(create_only_t(), name, perm)
{}
inline named_condition::named_condition(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_cond(open_or_create_t(), name, perm)
{}
inline named_condition::named_condition(open_only_t, const wchar_t *name)
: m_cond(open_only_t(), name)
{}
#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void named_condition::notify_one()
{ m_cond.notify_one(); }
@@ -170,17 +257,17 @@ inline void named_condition::wait(L& lock, Pr pred)
m_cond.wait(internal_lock, pred);
}
template <typename L>
template <typename L, typename TimePoint>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
(L& lock, const TimePoint &abs_time)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return m_cond.timed_wait(internal_lock, abs_time);
}
template <typename L, typename Pr>
template <typename L, typename TimePoint, typename Pr>
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
(L& lock, const TimePoint &abs_time, Pr pred)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return m_cond.timed_wait(internal_lock, abs_time, pred);
@@ -191,6 +278,16 @@ inline bool named_condition::remove(const char *name)
return condition_type::remove(name);
}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool named_condition::remove(const wchar_t *name)
{
return condition_type::remove(name);
}
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess

View File

@@ -21,15 +21,16 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#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/detail/locks.hpp>
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
#include <boost/interprocess/sync/windows/named_condition_any.hpp>
#define BOOST_INTERPROCESS_USE_WINDOWS
#define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_USE_WINAPI
#else
#include <boost/interprocess/sync/shm/named_condition_any.hpp>
#endif
@@ -55,6 +56,7 @@ class named_condition_any
named_condition_any(const named_condition_any &);
named_condition_any &operator=(const named_condition_any &);
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
@@ -79,6 +81,42 @@ class named_condition_any
: m_cond(open_only_t(), name)
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_condition_any(create_only_t, const wchar_t *name, const permissions &perm = permissions())
: m_cond(create_only_t(), name, perm)
{}
//!Opens or creates a global condition with a name.
//!If the condition is created, this call is equivalent to
//!named_condition_any(create_only_t, ... )
//!If the condition is already created, this call is equivalent
//!named_condition_any(open_only_t, ... )
//!Does not throw
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_condition_any(open_or_create_t, const wchar_t *name, const permissions &perm = permissions())
: m_cond(open_or_create_t(), name, perm)
{}
//!Opens a global condition with a name if that condition is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_condition_any(open_only_t, const wchar_t *name)
: m_cond(open_only_t(), name)
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
//!any system resources allocated by the system for use by this process for
@@ -116,26 +154,62 @@ class named_condition_any
//!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)
template <typename L, typename TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{ return m_cond.timed_wait(lock, 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)
template <typename L, typename TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{ return m_cond.timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name)
{ return condition_any_type::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name)
{ return condition_any_type::remove(name); }
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
#if defined(BOOST_INTERPROCESS_USE_WINDOWS)
typedef ipcdetail::windows_named_condition_any condition_any_type;
#if defined(BOOST_INTERPROCESS_NAMED_CONDITION_ANY_USE_WINAPI)
typedef ipcdetail::winapi_named_condition_any condition_any_type;
#else
typedef ipcdetail::shm_named_condition_any condition_any_type;
#endif

View File

@@ -24,17 +24,16 @@
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/interprocess_tester.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/permissions.hpp>
#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES)
#include <boost/interprocess/sync/posix/named_mutex.hpp>
#define BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES
#define BOOST_INTERPROCESS_NAMED_MUTEX_USE_POSIX
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
#include <boost/interprocess/sync/windows/named_mutex.hpp>
#define BOOST_INTERPROCESS_USE_WINDOWS
#define BOOST_INTERPROCESS_NAMED_MUTEX_USE_WINAPI
#else
#include <boost/interprocess/sync/shm/named_mutex.hpp>
#include <boost/interprocess/sync/shm/named_mutex.hpp>
#endif
//!\file
@@ -62,7 +61,7 @@ class named_mutex
public:
//!Creates a global mutex with a name.
//!Throws interprocess_exception on error.
named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
named_mutex(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global mutex with a name.
//!If the mutex is created, this call is equivalent to
@@ -70,12 +69,42 @@ class named_mutex
//!If the mutex is already created, this call is equivalent
//!named_mutex(open_only_t, ... )
//!Does not throw
named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global mutex with a name if that mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
named_mutex(open_only_t open_only, const char *name);
named_mutex(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global mutex with a name.
//!Throws interprocess_exception on error.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global mutex with a name.
//!If the mutex is created, this call is equivalent to
//!named_mutex(create_only_t, ... )
//!If the mutex is already created, this call is equivalent
//!named_mutex(open_only_t, ... )
//!Does not throw
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global mutex with a name if that mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_mutex(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -89,36 +118,74 @@ class named_mutex
//!mutex.
void unlock();
//!Requires: The calling thread does not own the mutex.
//!
//!Locks the mutex, sleeps when the mutex is already locked.
//!Throws interprocess_exception if a severe error is found
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Tries to lock the mutex, returns false when the mutex
//!is already locked, returns true when success.
//!Throws interprocess_exception if a severe error is found
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Tries to lock the the mutex until time abs_time,
//!Returns false when timeout expires, returns true when locks.
//!Throws interprocess_exception if a severe error is found
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Erases a named mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named mutex from the system.
//!Returns false on error. Never throws.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
public:
#if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES)
#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USE_POSIX)
typedef ipcdetail::posix_named_mutex internal_mutex_type;
#undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES
#elif defined(BOOST_INTERPROCESS_USE_WINDOWS)
typedef ipcdetail::windows_named_mutex internal_mutex_type;
#undef BOOST_INTERPROCESS_USE_WINDOWS
#elif defined(BOOST_INTERPROCESS_NAMED_MUTEX_USE_WINAPI)
typedef ipcdetail::winapi_named_mutex internal_mutex_type;
#else
typedef ipcdetail::shm_named_mutex internal_mutex_type;
#endif
@@ -144,6 +211,22 @@ inline named_mutex::named_mutex(open_only_t, const char *name)
: m_mut(open_only_t(), name)
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_mutex::named_mutex(create_only_t, const wchar_t *name, const permissions &perm)
: m_mut(create_only_t(), name, perm)
{}
inline named_mutex::named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_mut(open_or_create_t(), name, perm)
{}
inline named_mutex::named_mutex(open_only_t, const wchar_t *name)
: m_mut(open_only_t(), name)
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void named_mutex::dont_close_on_destruction()
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); }
@@ -159,12 +242,20 @@ inline void named_mutex::unlock()
inline bool named_mutex::try_lock()
{ return m_mut.try_lock(); }
inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool named_mutex::timed_lock(const TimePoint &abs_time)
{ return m_mut.timed_lock(abs_time); }
inline bool named_mutex::remove(const char *name)
{ return internal_mutex_type::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool named_mutex::remove(const wchar_t *name)
{ return internal_mutex_type::remove(name); }
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {

View File

@@ -22,11 +22,11 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/permissions.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
#define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_USE_WINAPI
#else
#include <boost/interprocess/sync/shm/named_recursive_mutex.hpp>
#endif
@@ -56,7 +56,7 @@ class named_recursive_mutex
//!Creates a global recursive_mutex with a name.
//!If the recursive_mutex can't be created throws interprocess_exception
named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global recursive_mutex with a name.
//!If the recursive_mutex is created, this call is equivalent to
@@ -64,12 +64,42 @@ class named_recursive_mutex
//!If the recursive_mutex is already created, this call is equivalent
//!named_recursive_mutex(open_only_t, ... )
//!Does not throw
named_recursive_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global recursive_mutex with a name if that recursive_mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
named_recursive_mutex(open_only_t open_only, const char *name);
named_recursive_mutex(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global recursive_mutex with a name.
//!If the recursive_mutex can't be created throws interprocess_exception
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global recursive_mutex with a name.
//!If the recursive_mutex is created, this call is equivalent to
//!named_recursive_mutex(create_only_t, ... )
//!If the recursive_mutex is already created, this call is equivalent
//!named_recursive_mutex(open_only_t, ... )
//!Does not throw
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global recursive_mutex with a name if that recursive_mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_recursive_mutex(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -85,30 +115,58 @@ class named_recursive_mutex
//!Locks named_recursive_mutex, sleeps when named_recursive_mutex is already locked.
//!Throws interprocess_exception if a severe error is found.
//!
//!Note: A program shall not deadlock if the thread that has ownership calls
//! this function.
void lock();
//!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex
//!is already locked, returns true when success.
//!Throws interprocess_exception if a severe error is found.
//!
//!Note: A program shall not deadlock if the thread that has ownership calls
//! this function.
bool try_lock();
//!Tries to lock the named_recursive_mutex until time abs_time,
//!Returns false when timeout expires, returns true when locks.
//!Throws interprocess_exception if a severe error is found
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program shall not deadlock if the thread that has ownership calls
//! this function.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Erases a named recursive mutex
//!from the system
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named recursive mutex
//!from the system
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
void dont_close_on_destruction();
#if defined(BOOST_INTERPROCESS_USE_WINDOWS)
typedef ipcdetail::windows_named_recursive_mutex impl_t;
#undef BOOST_INTERPROCESS_USE_WINDOWS
#if defined(BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_USE_WINAPI)
typedef ipcdetail::winapi_named_recursive_mutex impl_t;
#else
typedef ipcdetail::shm_named_recursive_mutex impl_t;
#endif
@@ -137,6 +195,22 @@ inline named_recursive_mutex::named_recursive_mutex(open_only_t, const char *nam
: m_mut (open_only, name)
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_recursive_mutex::named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm)
: m_mut (create_only, name, perm)
{}
inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_mut (open_or_create, name, perm)
{}
inline named_recursive_mutex::named_recursive_mutex(open_only_t, const wchar_t *name)
: m_mut (open_only, name)
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void named_recursive_mutex::lock()
{ m_mut.lock(); }
@@ -146,12 +220,20 @@ inline void named_recursive_mutex::unlock()
inline bool named_recursive_mutex::try_lock()
{ return m_mut.try_lock(); }
inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool named_recursive_mutex::timed_lock(const TimePoint &abs_time)
{ return m_mut.timed_lock(abs_time); }
inline bool named_recursive_mutex::remove(const char *name)
{ return impl_t::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool named_recursive_mutex::remove(const wchar_t *name)
{ return impl_t::remove(name); }
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {

View File

@@ -25,16 +25,15 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/interprocess_tester.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#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
#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USE_WINAPI
#else
#include <boost/interprocess/sync/shm/named_semaphore.hpp>
#include <boost/interprocess/sync/shm/named_semaphore.hpp>
#endif
//!\file
@@ -74,6 +73,36 @@ class named_semaphore
//!interprocess_exception.
named_semaphore(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global semaphore with a name, and an initial count.
//!If the semaphore can't be created throws interprocess_exception
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions());
//!Opens or creates a global semaphore with a name, and an initial count.
//!If the semaphore is created, this call is equivalent to
//!named_semaphore(create_only_t, ...)
//!If the semaphore is already created, this call is equivalent to
//!named_semaphore(open_only_t, ... )
//!and initialCount is ignored.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions());
//!Opens a global semaphore with a name if that semaphore is previously.
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_semaphore(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
//!any system resources allocated by the system for use by this process for
@@ -102,12 +131,24 @@ class named_semaphore
//!to the posted or the timeout expires. If the timeout expires, the
//!function returns false. If the semaphore is posted the function
//!returns true. If there is an error throws sem_exception
bool timed_wait(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_wait(const TimePoint &abs_time);
//!Erases a named semaphore from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named semaphore from the system.
//!Returns false on error. Never throws.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
@@ -115,9 +156,8 @@ class named_semaphore
#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES)
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;
#elif defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USE_WINAPI)
typedef ipcdetail::winapi_named_semaphore impl_t;
#else
typedef ipcdetail::shm_named_semaphore impl_t;
#endif
@@ -141,6 +181,24 @@ inline named_semaphore::named_semaphore(open_only_t, const char *name)
: m_sem(open_only, name)
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_semaphore::named_semaphore
(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm)
: m_sem(create_only, name, initialCount, perm)
{}
inline named_semaphore::named_semaphore
(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm)
: m_sem(open_or_create, name, initialCount, perm)
{}
inline named_semaphore::named_semaphore(open_only_t, const wchar_t *name)
: m_sem(open_only, name)
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_semaphore::~named_semaphore()
{}
@@ -156,12 +214,20 @@ inline void named_semaphore::post()
inline bool named_semaphore::try_wait()
{ return m_sem.try_wait(); }
inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool named_semaphore::timed_wait(const TimePoint &abs_time)
{ return m_sem.timed_wait(abs_time); }
inline bool named_semaphore::remove(const char *name)
{ return impl_t::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool named_semaphore::remove(const wchar_t *name)
{ return impl_t::remove(name); }
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {

View File

@@ -26,7 +26,6 @@
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/sync/interprocess_sharable_mutex.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
#include <boost/interprocess/permissions.hpp>
@@ -57,20 +56,50 @@ class named_sharable_mutex
//!Creates a global sharable mutex with a name.
//!If the sharable mutex can't be created throws interprocess_exception
named_sharable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
named_sharable_mutex(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global sharable mutex with a name.
//!If the sharable mutex is created, this call is equivalent to
//!named_sharable_mutex(create_only_t, ...)
//!If the sharable mutex is already created, this call is equivalent to
//!named_sharable_mutex(open_only_t, ... ).
named_sharable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
named_sharable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global sharable mutex with a name if that sharable mutex
//!is previously.
//!created. If it is not previously created this function throws
//!interprocess_exception.
named_sharable_mutex(open_only_t open_only, const char *name);
named_sharable_mutex(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global sharable mutex with a name.
//!If the sharable mutex can't be created throws interprocess_exception
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_sharable_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global sharable mutex with a name.
//!If the sharable mutex is created, this call is equivalent to
//!named_sharable_mutex(create_only_t, ...)
//!If the sharable mutex is already created, this call is equivalent to
//!named_sharable_mutex(open_only_t, ... ).
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_sharable_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global sharable mutex with a name if that sharable mutex
//!is previously.
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_sharable_mutex(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -82,26 +111,55 @@ class named_sharable_mutex
//Exclusive locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
//! and if another thread has exclusive or sharable ownership of
//! the mutex, it waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
void lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! without waiting. If no other thread has exclusive or sharable
//! ownership of the mutex this succeeds.
//!Returns: If it can acquire exclusive ownership immediately returns true.
//! If it has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
bool try_lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! waiting if necessary until no other thread has exclusive, or sharable
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown.
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
@@ -110,36 +168,88 @@ class named_sharable_mutex
//Sharable locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
//! and if another thread has exclusive ownership of the mutex,
//! waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! without waiting. If no other thread has exclusive ownership
//! of the mutex this succeeds.
//!Returns: If it can acquire sharable ownership immediately returns true. If it
//! has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! waiting if necessary until no other thread has exclusive
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//!Erases a named sharable mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named sharable mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const wchar_t *name);
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
@@ -192,6 +302,43 @@ inline named_sharable_mutex::named_sharable_mutex
,construct_func_t(ipcdetail::DoOpen))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_sharable_mutex::named_sharable_mutex
(create_only_t, const wchar_t *name, const permissions &perm)
: m_shmem (create_only
,name
,sizeof(interprocess_sharable_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoCreate)
,perm)
{}
inline named_sharable_mutex::named_sharable_mutex
(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_shmem (open_or_create
,name
,sizeof(interprocess_sharable_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoOpenOrCreate)
,perm)
{}
inline named_sharable_mutex::named_sharable_mutex
(open_only_t, const wchar_t *name)
: m_shmem (open_only
,name
,read_write
,0
,construct_func_t(ipcdetail::DoOpen))
{}
#endif
inline void named_sharable_mutex::dont_close_on_destruction()
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
@@ -204,8 +351,9 @@ inline void named_sharable_mutex::unlock()
inline bool named_sharable_mutex::try_lock()
{ return this->mutex()->try_lock(); }
template<class TimePoint>
inline bool named_sharable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
(const TimePoint &abs_time)
{ return this->mutex()->timed_lock(abs_time); }
inline void named_sharable_mutex::lock_sharable()
@@ -217,13 +365,21 @@ inline void named_sharable_mutex::unlock_sharable()
inline bool named_sharable_mutex::try_lock_sharable()
{ return this->mutex()->try_lock_sharable(); }
template<class TimePoint>
inline bool named_sharable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
(const TimePoint &abs_time)
{ return this->mutex()->timed_lock_sharable(abs_time); }
inline bool named_sharable_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool named_sharable_mutex::remove(const wchar_t *name)
{ return shared_memory_object::remove(name); }
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {

View File

@@ -26,7 +26,6 @@
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
#include <boost/interprocess/permissions.hpp>
@@ -58,20 +57,50 @@ class named_upgradable_mutex
//!Creates a global upgradable mutex with a name.
//!If the upgradable mutex can't be created throws interprocess_exception
named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
named_upgradable_mutex(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global upgradable mutex with a name.
//!If the upgradable mutex is created, this call is equivalent to
//!named_upgradable_mutex(create_only_t, ...)
//!If the upgradable mutex is already created, this call is equivalent to
//!named_upgradable_mutex(open_only_t, ... ).
named_upgradable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
named_upgradable_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global upgradable mutex with a name if that upgradable mutex
//!is previously.
//!created. If it is not previously created this function throws
//!interprocess_exception.
named_upgradable_mutex(open_only_t open_only, const char *name);
named_upgradable_mutex(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global upgradable mutex with a name.
//!If the upgradable mutex can't be created throws interprocess_exception
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_upgradable_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global upgradable mutex with a name.
//!If the upgradable mutex is created, this call is equivalent to
//!named_upgradable_mutex(create_only_t, ...)
//!If the upgradable mutex is already created, this call is equivalent to
//!named_upgradable_mutex(open_only_t, ... ).
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_upgradable_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global upgradable mutex with a name if that upgradable mutex
//!is previously.
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
named_upgradable_mutex(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -83,26 +112,55 @@ class named_upgradable_mutex
//Exclusive locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
//! and if another thread has exclusive, sharable or upgradable ownership of
//! the mutex, it waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
void lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! without waiting. If no other thread has exclusive, sharable or upgradable
//! ownership of the mutex this succeeds.
//!Returns: If it can acquire exclusive ownership immediately returns true.
//! If it has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
bool try_lock();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire exclusive ownership of the mutex
//! waiting if necessary until no other thread has exclusive, sharable or
//! upgradable ownership of the mutex or abs_time is reached.
//!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
@@ -111,54 +169,117 @@ class named_upgradable_mutex
//Sharable locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain sharable ownership of the mutex,
//! and if another thread has exclusive ownership of the mutex,
//! waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! without waiting. If no other thread has exclusive ownership
//! of the mutex this succeeds.
//!Returns: If it can acquire sharable ownership immediately returns true. If it
//! has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! waiting if necessary until no other thread has exclusive
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//Upgradable locking
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
//! and if another thread has exclusive or upgradable ownership of the mutex,
//! waits until it can obtain the ownership.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
void lock_upgradable();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire upgradable ownership of the mutex
//! without waiting. If no other thread has exclusive or upgradable ownership
//! of the mutex this succeeds.
//!Returns: If it can acquire upgradable ownership immediately returns true.
//! If it has to wait, returns false.
//!Throws: interprocess_exception on error.
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
bool try_lock_upgradable();
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire upgradable ownership of the mutex
//! waiting if necessary until no other thread has exclusive or upgradable
//! ownership of the mutex or abs_time is reached.
//!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
//!Throws: interprocess_exception on error.
bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
//!
//!Note: A program may deadlock if the thread that has ownership calls
//! this function. If the implementation can detect the deadlock,
//! an exception could be thrown
template<class TimePoint>
bool timed_lock_upgradable(const TimePoint &abs_time);
//!Precondition: The thread must have upgradable ownership of the mutex.
//!Effects: The calling thread releases the upgradable ownership of the mutex.
@@ -209,7 +330,8 @@ class named_upgradable_mutex
//! will maintain upgradable ownership.
//!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
//!Throws: An exception derived from interprocess_exception on error.
bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time);
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The thread atomically releases sharable ownership and tries to acquire
@@ -231,6 +353,15 @@ class named_upgradable_mutex
//!Returns false on error. Never throws.
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named upgradable mutex from the system.
//!Returns false on error. Never throws.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class ipcdetail::interprocess_tester;
@@ -283,6 +414,43 @@ inline named_upgradable_mutex::named_upgradable_mutex
,construct_func_t(ipcdetail::DoOpen))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline named_upgradable_mutex::named_upgradable_mutex
(create_only_t, const wchar_t *name, const permissions &perm)
: m_shmem (create_only
,name
,sizeof(interprocess_upgradable_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoCreate)
,perm)
{}
inline named_upgradable_mutex::named_upgradable_mutex
(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_shmem (open_or_create
,name
,sizeof(interprocess_upgradable_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoOpenOrCreate)
,perm)
{}
inline named_upgradable_mutex::named_upgradable_mutex
(open_only_t, const wchar_t *name)
: m_shmem (open_only
,name
,read_write
,0
,construct_func_t(ipcdetail::DoOpen))
{}
#endif
inline void named_upgradable_mutex::dont_close_on_destruction()
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); }
@@ -295,8 +463,8 @@ inline void named_upgradable_mutex::unlock()
inline bool named_upgradable_mutex::try_lock()
{ return this->mutex()->try_lock(); }
inline bool named_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool named_upgradable_mutex::timed_lock(const TimePoint &abs_time)
{ return this->mutex()->timed_lock(abs_time); }
inline void named_upgradable_mutex::lock_upgradable()
@@ -308,8 +476,8 @@ inline void named_upgradable_mutex::unlock_upgradable()
inline bool named_upgradable_mutex::try_lock_upgradable()
{ return this->mutex()->try_lock_upgradable(); }
inline bool named_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool named_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time)
{ return this->mutex()->timed_lock_upgradable(abs_time); }
inline void named_upgradable_mutex::lock_sharable()
@@ -321,8 +489,8 @@ inline void named_upgradable_mutex::unlock_sharable()
inline bool named_upgradable_mutex::try_lock_sharable()
{ return this->mutex()->try_lock_sharable(); }
inline bool named_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool named_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time)
{ return this->mutex()->timed_lock_sharable(abs_time); }
inline void named_upgradable_mutex::unlock_and_lock_upgradable()
@@ -340,8 +508,8 @@ inline void named_upgradable_mutex::unlock_upgradable_and_lock()
inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock()
{ return this->mutex()->try_unlock_upgradable_and_lock(); }
inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock
(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time)
{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); }
inline bool named_upgradable_mutex::try_unlock_sharable_and_lock()
@@ -353,6 +521,14 @@ inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
inline bool named_upgradable_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool named_upgradable_mutex::remove(const wchar_t *name)
{ return shared_memory_object::remove(name); }
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace interprocess {

View File

@@ -27,14 +27,6 @@
//!Describes null_mutex classes
namespace boost {
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace posix_time
{ class ptime; }
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace interprocess {
//!Implements a mutex that simulates a mutex without doing any operation and
@@ -49,7 +41,7 @@ class null_mutex
//!Constructor.
//!Empty.
null_mutex(){}
null_mutex() BOOST_NOEXCEPT {}
//!Destructor.
//!Empty.
@@ -65,9 +57,22 @@ class null_mutex
//!Simulates a mutex timed_lock() operation.
//!Equivalent to "return true;"
bool timed_lock(const boost::posix_time::ptime &)
template<class TimePoint>
bool timed_lock(const TimePoint &)
{ return true; }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint>
bool try_lock_until(const TimePoint &)
{ return true; }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration>
bool try_lock_for(const Duration &)
{ return true; }
//!Simulates a mutex unlock() operation.
//!Empty function.
void unlock(){}
@@ -76,20 +81,36 @@ class null_mutex
//!Empty function.
void lock_sharable(){}
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Simulates a mutex try_lock_sharable() operation.
//!Equivalent to "return true;"
bool try_lock_sharable()
{ return true; }
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Simulates a mutex timed_lock_sharable() operation.
//!Equivalent to "return true;"
bool timed_lock_sharable(const boost::posix_time::ptime &)
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &)
{ return true; }
//!Simulates a mutex unlock_sharable() operation.
//!Empty function.
void unlock_sharable(){}
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//!Simulates a mutex lock_upgradable() operation.
//!Empty function.
void lock_upgradable(){}
@@ -101,7 +122,8 @@ class null_mutex
//!Simulates a mutex timed_lock_upgradable() operation.
//!Equivalent to "return true;"
bool timed_lock_upgradable(const boost::posix_time::ptime &)
template<class TimePoint>
bool timed_lock_upgradable(const TimePoint &)
{ return true; }
//!Simulates a mutex unlock_upgradable() operation.
@@ -133,7 +155,8 @@ class null_mutex
//!Simulates timed_unlock_upgradable_and_lock().
//!Equivalent to "return true;"
bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &)
template<class TimePoint>
bool timed_unlock_upgradable_and_lock(const TimePoint &)
{ return true; }
//!Simulates try_unlock_sharable_and_lock().

View File

@@ -22,11 +22,12 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
#include <boost/interprocess/sync/posix/mutex.hpp>
#include <boost/assert.hpp>
@@ -84,13 +85,13 @@ class posix_condition
//!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)
template <typename L, typename TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{
if (!lock)
throw lock_exception();
//Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
if(ipcdetail::is_pos_infinity(abs_time)){
this->wait(lock);
return true;
}
@@ -100,13 +101,13 @@ class posix_condition
//!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)
template <typename L, typename TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{
if (!lock)
throw lock_exception();
//Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
if(ipcdetail::is_pos_infinity(abs_time)){
this->wait(lock, pred);
return true;
}
@@ -117,10 +118,30 @@ class posix_condition
return true;
}
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, duration_to_ustime(dur)) ? cv_status::no_timeout : cv_status::timeout; }
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, duration_to_ustime(dur), pred); }
void do_wait(posix_mutex &mut);
bool do_timed_wait(const boost::posix_time::ptime &abs_time, posix_mutex &mut);
template<class TimePoint>
bool do_timed_wait(const TimePoint &abs_time, posix_mutex &mut);
private:
pthread_cond_t m_condition;
@@ -175,10 +196,11 @@ inline void posix_condition::do_wait(posix_mutex &mut)
BOOST_ASSERT(res == 0); (void)res;
}
template<class TimePoint>
inline bool posix_condition::do_timed_wait
(const boost::posix_time::ptime &abs_time, posix_mutex &mut)
(const TimePoint &abs_time, posix_mutex &mut)
{
timespec ts = ptime_to_timespec(abs_time);
timespec ts = timepoint_to_timespec(abs_time);
pthread_mutex_t* pmutex = &mut.m_mut;
int res = 0;
res = pthread_cond_timedwait(&m_condition, pmutex, &ts);

View File

@@ -41,10 +41,11 @@
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
# include <boost/interprocess/detail/os_thread_functions.hpp>
@@ -69,7 +70,14 @@ class posix_mutex
void lock();
bool try_lock();
bool timed_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
void unlock();
friend class posix_condition;
@@ -93,28 +101,66 @@ inline posix_mutex::~posix_mutex()
inline void posix_mutex::lock()
{
if (pthread_mutex_lock(&m_mut) != 0)
int res = pthread_mutex_lock(&m_mut);
#ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
if (res == EOWNERDEAD)
{
//We can't inform the application and data might
//corrupted, so be safe and mark the mutex as not recoverable
//so applications can act accordingly.
pthread_mutex_unlock(&m_mut);
throw lock_exception(not_recoverable);
}
else if (res == ENOTRECOVERABLE)
throw lock_exception(not_recoverable);
#endif
if (res != 0)
throw lock_exception();
}
inline bool posix_mutex::try_lock()
{
int res = pthread_mutex_trylock(&m_mut);
#ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
if (res == EOWNERDEAD)
{
//We can't inform the application and data might
//corrupted, so be safe and mark the mutex as not recoverable
//so applications can act accordingly.
pthread_mutex_unlock(&m_mut);
throw lock_exception(not_recoverable);
}
else if (res == ENOTRECOVERABLE)
throw lock_exception(not_recoverable);
#endif
if (!(res == 0 || res == EBUSY))
throw lock_exception();
return res == 0;
}
inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool posix_mutex::timed_lock(const TimePoint &abs_time)
{
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
//Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
if(ipcdetail::is_pos_infinity(abs_time)){
this->lock();
return true;
}
timespec ts = ptime_to_timespec(abs_time);
timespec ts = timepoint_to_timespec(abs_time);
int res = pthread_mutex_timedlock(&m_mut, &ts);
#ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
if (res == EOWNERDEAD)
{
//We can't inform the application and data might
//corrupted, so be safe and mark the mutex as not recoverable
//so applications can act accordingly.
pthread_mutex_unlock(&m_mut);
throw lock_exception(not_recoverable);
}
else if (res == ENOTRECOVERABLE)
throw lock_exception(not_recoverable);
#endif
if (res != 0 && res != ETIMEDOUT)
throw lock_exception();
return res == 0;
@@ -128,8 +174,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
inline void posix_mutex::unlock()
{
int res = 0;
res = pthread_mutex_unlock(&m_mut);
int res = pthread_mutex_unlock(&m_mut);
(void)res;
BOOST_ASSERT(res == 0);
}

View File

@@ -45,18 +45,29 @@ class posix_named_mutex
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
posix_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
posix_named_mutex(create_only_t, const char *name, const permissions &perm = permissions());
posix_named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
posix_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
posix_named_mutex(open_only_t open_only, const char *name);
posix_named_mutex(open_only_t, const char *name);
~posix_named_mutex();
void unlock();
void lock();
bool try_lock();
bool timed_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint>
bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration>
bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
static bool remove(const char *name);
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
@@ -97,7 +108,8 @@ inline void posix_named_mutex::unlock()
inline bool posix_named_mutex::try_lock()
{ return m_sem.try_wait(); }
inline bool posix_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool posix_named_mutex::timed_lock(const TimePoint &abs_time)
{ return m_sem.timed_wait(abs_time); }
inline bool posix_named_mutex::remove(const char *name)

View File

@@ -65,7 +65,8 @@ class posix_named_semaphore
bool try_wait()
{ return semaphore_try_wait(mp_sem); }
bool timed_wait(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
bool timed_wait(const TimePoint &abs_time)
{ return semaphore_timed_wait(mp_sem, abs_time); }
static bool remove(const char *name)

View File

@@ -41,8 +41,12 @@ namespace ipcdetail{
if(pthread_mutexattr_init(&m_attr)!=0 ||
pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0 ||
(recursive &&
pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE)!= 0 ))
throw interprocess_exception("pthread_mutexattr_xxxx failed");
pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE) != 0 )
#ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
|| pthread_mutexattr_setrobust(&m_attr, PTHREAD_MUTEX_ROBUST) != 0
#endif
)
throw interprocess_exception("pthread_mutexattr_xxxx failed");
}
//!Destructor
@@ -144,7 +148,7 @@ namespace ipcdetail{
//!Constructor. Takes barrier attributes to initialize the barrier
barrier_initializer(pthread_barrier_t &mut,
pthread_barrierattr_t &mut_attr,
int count)
unsigned int count)
: mp_barrier(&mut)
{
if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0)

View File

@@ -1,48 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-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_PTIME_TO_TIMESPEC_HPP
#define BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
namespace boost {
namespace interprocess {
namespace ipcdetail {
inline timespec ptime_to_timespec (const boost::posix_time::ptime &tm)
{
const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
//Avoid negative absolute times
boost::posix_time::time_duration duration = (tm <= epoch) ? boost::posix_time::time_duration(epoch - epoch)
: boost::posix_time::time_duration(tm - epoch);
timespec ts;
ts.tv_sec = duration.total_seconds();
ts.tv_nsec = duration.total_nanoseconds() % 1000000000;
return ts;
}
} //namespace ipcdetail {
} //namespace interprocess {
} //namespace boost {
#endif //ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP

View File

@@ -41,8 +41,8 @@
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
#include <boost/interprocess/exceptions.hpp>
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
# include <boost/interprocess/detail/os_thread_functions.hpp>
@@ -65,7 +65,7 @@ class posix_recursive_mutex
void lock();
bool try_lock();
bool timed_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
void unlock();
private:
@@ -87,29 +87,67 @@ inline posix_recursive_mutex::~posix_recursive_mutex()
inline void posix_recursive_mutex::lock()
{
if (pthread_mutex_lock(&m_mut) != 0)
int res = pthread_mutex_lock(&m_mut);
#ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
if (res == EOWNERDEAD)
{
//We can't inform the application and data might
//corrupted, so be safe and mark the mutex as not recoverable
//so applications can act accordingly.
pthread_mutex_unlock(&m_mut);
throw lock_exception(not_recoverable);
}
else if (res == ENOTRECOVERABLE)
throw lock_exception(not_recoverable);
#endif
if (res != 0)
throw lock_exception();
}
inline bool posix_recursive_mutex::try_lock()
{
int res = pthread_mutex_trylock(&m_mut);
#ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
if (res == EOWNERDEAD)
{
//We can't inform the application and data might
//corrupted, so be safe and mark the mutex as not recoverable
//so applications can act accordingly.
pthread_mutex_unlock(&m_mut);
throw lock_exception(not_recoverable);
}
else if (res == ENOTRECOVERABLE)
throw lock_exception(not_recoverable);
#endif
if (!(res == 0 || res == EBUSY))
throw lock_exception();
return res == 0;
return (res == 0);
}
inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool posix_recursive_mutex::timed_lock(const TimePoint &abs_time)
{
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
//Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
if(ipcdetail::is_pos_infinity(abs_time)){
this->lock();
return true;
}
timespec ts = ptime_to_timespec(abs_time);
timespec ts = timepoint_to_timespec(abs_time);
int res = pthread_mutex_timedlock(&m_mut, &ts);
#ifdef BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES
if (res == EOWNERDEAD)
{
//We can't inform the application and data might
//corrupted, so be safe and mark the mutex as not recoverable
//so applications can act accordingly.
pthread_mutex_unlock(&m_mut);
throw lock_exception(not_recoverable);
}
else if (res == ENOTRECOVERABLE)
throw lock_exception(not_recoverable);
#endif
if (res != 0 && res != ETIMEDOUT)
throw lock_exception();
return res == 0;

View File

@@ -22,7 +22,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/posix/semaphore_wrapper.hpp>
namespace boost {
@@ -51,7 +50,8 @@ class posix_semaphore
bool try_wait()
{ return semaphore_try_wait(&m_sem); }
bool timed_wait(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
bool timed_wait(const TimePoint &abs_time)
{ return semaphore_timed_wait(&m_sem, abs_time); }
private:

View File

@@ -19,11 +19,11 @@
# pragma once
#endif
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
#include <boost/interprocess/detail/shared_dir_helpers.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
#include <boost/interprocess/permissions.hpp>
#include <fcntl.h> //O_CREAT, O_*...
@@ -40,7 +40,7 @@
#endif
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
#include <boost/interprocess/sync/posix/timepoint_to_timespec.hpp>
#else
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <boost/interprocess/sync/detail/locks.hpp>
@@ -122,7 +122,7 @@ inline void semaphore_close(sem_t *handle)
inline bool semaphore_unlink(const char *semname)
{
try{
BOOST_TRY{
std::string sem_str;
#ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
add_leading_slash(semname, sem_str);
@@ -131,9 +131,9 @@ inline bool semaphore_unlink(const char *semname)
#endif
return 0 == sem_unlink(sem_str.c_str());
}
catch(...){
BOOST_CATCH(...){
return false;
}
} BOOST_CATCH_END
}
#endif //BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
@@ -212,16 +212,17 @@ struct semaphore_wrapper_try_wrapper
#endif
inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool semaphore_timed_wait(sem_t *handle, const TimePoint &abs_time)
{
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
//Posix does not support infinity absolute time so handle it here
if(abs_time == boost::posix_time::pos_infin){
if(ipcdetail::is_pos_infinity(abs_time)){
semaphore_wait(handle);
return true;
}
timespec tspec = ptime_to_timespec(abs_time);
timespec tspec = timepoint_to_timespec(abs_time);
for (;;){
int res = sem_timedwait(handle, &tspec);
if(res == 0)

View File

@@ -0,0 +1,87 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-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_TIMEPOINT_TO_TIMESPEC_HPP
#define BOOST_INTERPROCESS_DETAIL_TIMEPOINT_TO_TIMESPEC_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/timed_utils.hpp>
namespace boost {
namespace interprocess {
namespace ipcdetail {
template<class TimePoint>
inline timespec timepoint_to_timespec ( const TimePoint &tm
, typename enable_if_ptime<TimePoint>::type * = 0)
{
typedef typename TimePoint::date_type date_type;
typedef typename TimePoint::time_duration_type time_duration_type;
const TimePoint epoch(date_type(1970,1,1));
//Avoid negative absolute times
time_duration_type duration = (tm <= epoch) ? time_duration_type(epoch - epoch)
: time_duration_type(tm - epoch);
timespec ts;
ts.tv_sec = static_cast<time_t>(duration.total_seconds());
ts.tv_nsec = static_cast<long>(duration.total_nanoseconds() % 1000000000);
return ts;
}
inline timespec timepoint_to_timespec (const ustime &tm)
{
timespec ts;
ts.tv_sec = static_cast<time_t>(tm.get_microsecs()/1000000u);
ts.tv_nsec = static_cast<long>((tm.get_microsecs()%1000000u)*1000u);
return ts;
}
template<class TimePoint>
inline timespec timepoint_to_timespec ( const TimePoint &tm
, typename enable_if_time_point<TimePoint>::type * = 0)
{
typedef typename TimePoint::duration duration_t;
duration_t d(tm.time_since_epoch());
timespec ts;
BOOST_IF_CONSTEXPR(duration_t::period::num == 1 && duration_t::period::den == 1000000000)
{
ts.tv_sec = static_cast<time_t>(d.count()/duration_t::period::den);
ts.tv_nsec = static_cast<long>(d.count()%duration_t::period::den);
}
else
{
const double factor = double(duration_t::period::num)/double(duration_t::period::den);
const double res = d.count()*factor;
ts.tv_sec = static_cast<time_t>(res);
ts.tv_nsec = static_cast<long>(res - double(ts.tv_sec));
}
return ts;
}
} //namespace ipcdetail {
} //namespace interprocess {
} //namespace boost {
#endif //ifndef BOOST_INTERPROCESS_DETAIL_TIMEPOINT_TO_TIMESPEC_HPP

View File

@@ -32,7 +32,6 @@
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/detail/simple_swap.hpp>
//!\file
@@ -67,7 +66,7 @@ class scoped_lock
//!Effects: Default constructs a scoped_lock.
//!Postconditions: owns() == false and mutex() == 0.
scoped_lock()
scoped_lock() BOOST_NOEXCEPT
: mp_mutex(0), m_locked(false)
{}
@@ -114,7 +113,8 @@ class scoped_lock
//! handles recursive locking depends upon the mutex. If the mutex_type
//! does not support try_lock, this constructor will fail at compile
//! time if instantiated, but otherwise have no effect.
scoped_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
template<class TimePoint>
scoped_lock(mutex_type& m, const TimePoint& abs_time)
: mp_mutex(&m), m_locked(mp_mutex->timed_lock(abs_time))
{}
@@ -128,7 +128,7 @@ class scoped_lock
//! can be moved with the expression: "boost::move(lock);". This
//! constructor does not alter the state of the mutex, only potentially
//! who owns it.
scoped_lock(BOOST_RV_REF(scoped_lock) scop)
scoped_lock(BOOST_RV_REF(scoped_lock) scop) BOOST_NOEXCEPT
: mp_mutex(0), m_locked(scop.owns())
{ mp_mutex = scop.release(); }
@@ -202,8 +202,8 @@ class scoped_lock
//! "write lock". If the "read lock" isn't held in the first place, the mutex
//! merely changes type to an unlocked "write lock". If the "read lock" is held,
//! then mutex transfer occurs only if it can do so in a non-blocking manner.
template<class T>
scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, boost::posix_time::ptime &abs_time
template<class T, class TimePoint>
scoped_lock(BOOST_RV_REF(upgradable_lock<T>) upgr, const TimePoint &abs_time
, typename ipcdetail::enable_if< ipcdetail::is_same<T, Mutex> >::type * = 0)
: mp_mutex(0), m_locked(false)
{
@@ -253,8 +253,8 @@ class scoped_lock
//!Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
~scoped_lock()
{
try{ if(m_locked && mp_mutex) mp_mutex->unlock(); }
catch(...){}
BOOST_TRY{ if(m_locked && mp_mutex) mp_mutex->unlock(); }
BOOST_CATCH(...){} BOOST_CATCH_END
}
//!Effects: If owns() before the call, then unlock() is called on mutex().
@@ -307,7 +307,8 @@ class scoped_lock
//! owning the mutex, but only if it can obtain ownership by the specified
//! time. If the mutex_type does not support timed_lock (), this function
//! will fail at compile time if instantiated, but otherwise have no effect.*/
bool timed_lock(const boost::posix_time::ptime& abs_time)
template<class TimePoint>
bool timed_lock(const TimePoint& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
@@ -315,6 +316,38 @@ class scoped_lock
return m_locked;
}
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
//! exception. Calls try_lock_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
//!Notes: The scoped_lock changes from a state of not owning the mutex, to
//! owning the mutex, but only if it can obtain ownership by the specified
//! time. If the mutex_type does not support timed_lock (), this function
//! will fail at compile time if instantiated, but otherwise have no effect.*/
template<class TimePoint>
bool try_lock_until(const TimePoint& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_until(abs_time);
return m_locked;
}
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
//! exception. Calls try_lock_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
//!Notes: The scoped_lock changes from a state of not owning the mutex, to
//! owning the mutex, but only if it can obtain ownership by the specified
//! time. If the mutex_type does not support timed_lock (), this function
//! will fail at compile time if instantiated, but otherwise have no effect.*/
template<class Duration>
bool try_lock_for(const Duration& dur)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_for(dur);
return m_locked;
}
//!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
//! exception. Calls unlock() on the referenced mutex.
//!Postconditions: owns() == false.
@@ -330,23 +363,23 @@ class scoped_lock
//!Effects: Returns true if this scoped_lock has acquired
//!the referenced mutex.
bool owns() const
bool owns() const BOOST_NOEXCEPT
{ return m_locked && mp_mutex; }
//!Conversion to bool.
//!Returns owns().
operator unspecified_bool_type() const
operator unspecified_bool_type() const BOOST_NOEXCEPT
{ return m_locked? &this_type::m_locked : 0; }
//!Effects: Returns a pointer to the referenced mutex, or 0 if
//!there is no mutex to reference.
mutex_type* mutex() const
mutex_type* mutex() const BOOST_NOEXCEPT
{ return mp_mutex; }
//!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
//! mutex to reference.
//!Postconditions: mutex() == 0 and owns() == false.
mutex_type* release()
mutex_type* release() BOOST_NOEXCEPT
{
mutex_type *mut = mp_mutex;
mp_mutex = 0;
@@ -356,7 +389,7 @@ class scoped_lock
//!Effects: Swaps state with moved lock.
//!Throws: Nothing.
void swap( scoped_lock<mutex_type> &other)
void swap( scoped_lock<mutex_type> &other) BOOST_NOEXCEPT
{
(simple_swap)(mp_mutex, other.mp_mutex);
(simple_swap)(m_locked, other.m_locked);

View File

@@ -33,7 +33,6 @@
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/simple_swap.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
//!\file
//!Describes the upgradable_lock class that serves to acquire the upgradable
@@ -67,7 +66,7 @@ class sharable_lock
//!Effects: Default constructs a sharable_lock.
//!Postconditions: owns() == false and mutex() == 0.
sharable_lock()
sharable_lock() BOOST_NOEXCEPT
: mp_mutex(0), m_locked(false)
{}
@@ -117,7 +116,8 @@ class sharable_lock
//! handles recursive locking depends upon the mutex. If the mutex_type
//! does not support timed_lock_sharable, this constructor will fail at
//! compile time if instantiated, but otherwise have no effect.
sharable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time)
template<class TimePoint>
sharable_lock(mutex_type& m, const TimePoint& abs_time)
: mp_mutex(&m), m_locked(false)
{ m_locked = mp_mutex->timed_lock_sharable(abs_time); }
@@ -129,7 +129,7 @@ class sharable_lock
//! signature. An non-moved sharable_lock can be moved with the expression:
//! "boost::move(lock);". This constructor does not alter the state of the mutex,
//! only potentially who owns it.
sharable_lock(BOOST_RV_REF(sharable_lock<mutex_type>) upgr)
sharable_lock(BOOST_RV_REF(sharable_lock<mutex_type>) upgr) BOOST_NOEXCEPT
: mp_mutex(0), m_locked(upgr.owns())
{ mp_mutex = upgr.release(); }
@@ -182,10 +182,10 @@ class sharable_lock
//!Notes: The destructor behavior ensures that the mutex lock is not leaked.
~sharable_lock()
{
try{
BOOST_TRY{
if(m_locked && mp_mutex) mp_mutex->unlock_sharable();
}
catch(...){}
BOOST_CATCH(...){} BOOST_CATCH_END
}
//!Effects: If owns() before the call, then unlock_sharable() is called on mutex().
@@ -240,7 +240,8 @@ class sharable_lock
//! specified time interval. If the mutex_type does not support
//! timed_lock_sharable(), this function will fail at compile time if
//! instantiated, but otherwise have no effect.
bool timed_lock(const boost::posix_time::ptime& abs_time)
template<class TimePoint>
bool timed_lock(const TimePoint& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
@@ -248,6 +249,46 @@ class sharable_lock
return m_locked;
}
//!Effects: If mutex() == 0 or already locked, throws a lock_exception()
//! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from
//! mutex()->timed_lock_sharable(elps_time).
//!Notes: The sharable_lock changes from a state of not owning the mutex,
//! to owning the mutex, but only if it can obtain ownership within the
//! specified time interval. If the mutex_type does not support
//! timed_lock_sharable(), this function will fail at compile time if
//! instantiated, but otherwise have no effect.
//!
//!Note: Similar to timed_lock, but with a std-like interface
template<class TimePoint>
bool try_lock_until(const TimePoint& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_shared_until(abs_time);
return m_locked;
}
//!Effects: If mutex() == 0 or already locked, throws a lock_exception()
//! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from
//! mutex()->timed_lock_sharable(elps_time).
//!Notes: The sharable_lock changes from a state of not owning the mutex,
//! to owning the mutex, but only if it can obtain ownership within the
//! specified time interval. If the mutex_type does not support
//! timed_lock_sharable(), this function will fail at compile time if
//! instantiated, but otherwise have no effect.
//!
//!Note: Similar to timed_lock, but with a std-like interface
template<class Duration>
bool try_lock_for(const Duration& dur)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_shared_for(dur);
return m_locked;
}
//!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception.
//! Calls unlock_sharable() on the referenced mutex.
//!Postconditions: owns() == false.
@@ -263,23 +304,23 @@ class sharable_lock
//!Effects: Returns true if this scoped_lock has
//!acquired the referenced mutex.
bool owns() const
bool owns() const BOOST_NOEXCEPT
{ return m_locked && mp_mutex; }
//!Conversion to bool.
//!Returns owns().
operator unspecified_bool_type() const
operator unspecified_bool_type() const BOOST_NOEXCEPT
{ return m_locked? &this_type::m_locked : 0; }
//!Effects: Returns a pointer to the referenced mutex, or 0 if
//!there is no mutex to reference.
mutex_type* mutex() const
mutex_type* mutex() const BOOST_NOEXCEPT
{ return mp_mutex; }
//!Effects: Returns a pointer to the referenced mutex, or 0 if there is no
//! mutex to reference.
//!Postconditions: mutex() == 0 and owns() == false.
mutex_type* release()
mutex_type* release() BOOST_NOEXCEPT
{
mutex_type *mut = mp_mutex;
mp_mutex = 0;
@@ -289,7 +330,7 @@ class sharable_lock
//!Effects: Swaps state with moved lock.
//!Throws: Nothing.
void swap(sharable_lock<mutex_type> &other)
void swap(sharable_lock<mutex_type> &other) BOOST_NOEXCEPT
{
(simple_swap)(mp_mutex, other.mp_mutex);
(simple_swap)(m_locked, other.m_locked);

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/static_assert.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/creation_tags.hpp>
@@ -28,7 +30,6 @@
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/permissions.hpp>
@@ -66,7 +67,7 @@ class shm_named_condition
public:
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
shm_named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions());
shm_named_condition(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global condition with a name.
//!If the condition is created, this call is equivalent to
@@ -74,12 +75,42 @@ class shm_named_condition
//!If the condition is already created, this call is equivalent
//!shm_named_condition(open_only_t, ... )
//!Does not throw
shm_named_condition(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
shm_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global condition with a name if that condition is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
shm_named_condition(open_only_t open_only, const char *name);
shm_named_condition(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
shm_named_condition(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global condition with a name.
//!If the condition is created, this call is equivalent to
//!shm_named_condition(create_only_t, ... )
//!If the condition is already created, this call is equivalent
//!shm_named_condition(open_only_t, ... )
//!Does not throw
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
shm_named_condition(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global condition with a name if that condition is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
shm_named_condition(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -113,19 +144,54 @@ class shm_named_condition
//!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);
template <typename L, typename TimePoint>
bool timed_wait(L& lock, const TimePoint &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);
template <typename L, typename TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred);
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
//!
//!Note: This function is only available on operating systems with
//! native wchar_t APIs (e.g. Windows).
static bool remove(const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -198,6 +264,40 @@ inline shm_named_condition::shm_named_condition(open_only_t, const char *name)
,construct_func_t(DoOpen))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline shm_named_condition::shm_named_condition(create_only_t, const wchar_t *name, const permissions &perm)
: m_shmem (create_only
,name
,sizeof(internal_condition) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoCreate)
,perm)
{}
inline shm_named_condition::shm_named_condition(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_shmem (open_or_create
,name
,sizeof(internal_condition) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoOpenOrCreate)
,perm)
{}
inline shm_named_condition::shm_named_condition(open_only_t, const wchar_t *name)
: m_shmem (open_only
,name
,read_write
,0
,construct_func_t(DoOpen))
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void shm_named_condition::dont_close_on_destruction()
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
@@ -215,19 +315,27 @@ template <typename L, typename Pr>
inline void shm_named_condition::wait(L& lock, Pr pred)
{ this->internal_cond().wait(lock, pred); }
template <typename L>
template <typename L, typename TimePoint>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
(L& lock, const TimePoint &abs_time)
{ return this->internal_cond().timed_wait(lock, abs_time); }
template <typename L, typename Pr>
template <typename L, typename TimePoint, typename Pr>
inline bool shm_named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->internal_cond().timed_wait(lock, abs_time, pred); }
inline bool shm_named_condition::remove(const char *name)
{ return shared_memory_object::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool shm_named_condition::remove(const wchar_t *name)
{ return shared_memory_object::remove(name); }
#endif
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace ipcdetail

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/static_assert.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/creation_tags.hpp>
@@ -28,7 +30,6 @@
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/sync/shm/named_creation_functor.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/permissions.hpp>
@@ -61,8 +62,9 @@ class shm_named_condition_any
public:
//!Creates a global condition with a name.
//!If the condition can't be created throws interprocess_exception
shm_named_condition_any(create_only_t create_only, const char *name, const permissions &perm = permissions())
: m_shmem (create_only
template <class CharT>
shm_named_condition_any(create_only_t, const CharT *name, const permissions &perm = permissions())
: m_shmem (create_only_t()
,name
,sizeof(internal_condition) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
@@ -78,8 +80,9 @@ class shm_named_condition_any
//!If the condition is already created, this call is equivalent
//!shm_named_condition_any(open_only_t, ... )
//!Does not throw
shm_named_condition_any(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions())
: m_shmem (open_or_create
template <class CharT>
shm_named_condition_any(open_or_create_t, const CharT *name, const permissions &perm = permissions())
: m_shmem (open_or_create_t()
,name
,sizeof(internal_condition) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
@@ -92,8 +95,9 @@ class shm_named_condition_any
//!Opens a global condition with a name if that condition is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
shm_named_condition_any(open_only_t open_only, const char *name)
: m_shmem (open_only
template <class CharT>
shm_named_condition_any(open_only_t, const CharT *name)
: m_shmem (open_only_t()
,name
,read_write
,0
@@ -137,20 +141,45 @@ class shm_named_condition_any
//!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)
template <typename L, typename TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{ return this->internal_cond().timed_wait(lock, 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)
template <typename L, typename TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->internal_cond().timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name)
template <class CharT>
static bool remove(const CharT *name)
{ return shared_memory_object::remove(name); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

View File

@@ -25,7 +25,6 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/interprocess_tester.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
@@ -58,7 +57,7 @@ class shm_named_mutex
public:
//!Creates a global interprocess_mutex with a name.
//!Throws interprocess_exception on error.
shm_named_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
shm_named_mutex(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global mutex with a name.
//!If the mutex is created, this call is equivalent to
@@ -66,12 +65,33 @@ class shm_named_mutex
//!If the mutex is already created, this call is equivalent
//!shm_named_mutex(open_only_t, ... )
//!Does not throw
shm_named_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
shm_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global mutex with a name if that mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
shm_named_mutex(open_only_t open_only, const char *name);
shm_named_mutex(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global interprocess_mutex with a name.
//!Throws interprocess_exception on error.
shm_named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global mutex with a name.
//!If the mutex is created, this call is equivalent to
//!shm_named_mutex(create_only_t, ... )
//!If the mutex is already created, this call is equivalent
//!shm_named_mutex(open_only_t, ... )
//!Does not throw
shm_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global mutex with a name if that mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
shm_named_mutex(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -97,12 +117,27 @@ class shm_named_mutex
//!Tries to lock the interprocess_mutex until time abs_time,
//!Returns false when timeout expires, returns true when locks.
//!Throws interprocess_exception if a severe error is found
bool timed_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
//!Erases a named mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const wchar_t *name);
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef interprocess_mutex internal_mutex_type;
interprocess_mutex &internal_mutex()
@@ -126,7 +161,7 @@ inline shm_named_mutex::~shm_named_mutex()
{}
inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const permissions &perm)
: m_shmem (create_only
: m_shmem (create_only_t()
,name
,sizeof(interprocess_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
@@ -137,7 +172,7 @@ inline shm_named_mutex::shm_named_mutex(create_only_t, const char *name, const p
{}
inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, const permissions &perm)
: m_shmem (open_or_create
: m_shmem (open_or_create_t()
,name
,sizeof(interprocess_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
@@ -148,13 +183,47 @@ inline shm_named_mutex::shm_named_mutex(open_or_create_t, const char *name, cons
{}
inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name)
: m_shmem (open_only
: m_shmem (open_only_t()
,name
,read_write
,0
,construct_func_t(ipcdetail::DoOpen))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline shm_named_mutex::shm_named_mutex(create_only_t, const wchar_t *name, const permissions &perm)
: m_shmem (create_only_t()
,name
,sizeof(interprocess_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoCreate)
,perm)
{}
inline shm_named_mutex::shm_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_shmem (open_or_create_t()
,name
,sizeof(interprocess_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(ipcdetail::DoOpenOrCreate)
,perm)
{}
inline shm_named_mutex::shm_named_mutex(open_only_t, const wchar_t *name)
: m_shmem (open_only_t()
,name
,read_write
,0
,construct_func_t(ipcdetail::DoOpen))
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void shm_named_mutex::lock()
{ this->internal_mutex().lock(); }
@@ -164,12 +233,20 @@ inline void shm_named_mutex::unlock()
inline bool shm_named_mutex::try_lock()
{ return this->internal_mutex().try_lock(); }
inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool shm_named_mutex::timed_lock(const TimePoint &abs_time)
{ return this->internal_mutex().timed_lock(abs_time); }
inline bool shm_named_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool shm_named_mutex::remove(const wchar_t *name)
{ return shared_memory_object::remove(name); }
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
} //namespace ipcdetail {

View File

@@ -23,7 +23,6 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
@@ -53,7 +52,7 @@ class shm_named_recursive_mutex
//!Creates a global recursive_mutex with a name.
//!If the recursive_mutex can't be created throws interprocess_exception
shm_named_recursive_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions());
shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm = permissions());
//!Opens or creates a global recursive_mutex with a name.
//!If the recursive_mutex is created, this call is equivalent to
@@ -61,12 +60,33 @@ class shm_named_recursive_mutex
//!If the recursive_mutex is already created, this call is equivalent
//!shm_named_recursive_mutex(open_only_t, ... )
//!Does not throw
shm_named_recursive_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions());
shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
//!Opens a global recursive_mutex with a name if that recursive_mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
shm_named_recursive_mutex(open_only_t open_only, const char *name);
shm_named_recursive_mutex(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Creates a global recursive_mutex with a name.
//!If the recursive_mutex can't be created throws interprocess_exception
shm_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens or creates a global recursive_mutex with a name.
//!If the recursive_mutex is created, this call is equivalent to
//!shm_named_recursive_mutex(create_only_t, ... )
//!If the recursive_mutex is already created, this call is equivalent
//!shm_named_recursive_mutex(open_only_t, ... )
//!Does not throw
shm_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions());
//!Opens a global recursive_mutex with a name if that recursive_mutex is previously
//!created. If it is not previously created this function throws
//!interprocess_exception.
shm_named_recursive_mutex(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
@@ -92,12 +112,27 @@ class shm_named_recursive_mutex
//!Tries to lock the shm_named_recursive_mutex until time abs_time,
//!Returns false when timeout expires, returns true when locks.
//!Throws interprocess_exception if a severe error is found
bool timed_lock(const boost::posix_time::ptime &abs_time);
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
//!Erases a named recursive mutex
//!from the system
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
//!Erases a named recursive mutex
//!from the system
static bool remove(const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class interprocess_tester;
@@ -118,7 +153,7 @@ inline void shm_named_recursive_mutex::dont_close_on_destruction()
{ interprocess_tester::dont_close_on_destruction(m_shmem); }
inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const char *name, const permissions &perm)
: m_shmem (create_only
: m_shmem (create_only_t()
,name
,sizeof(interprocess_recursive_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
@@ -129,7 +164,7 @@ inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const
{}
inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const char *name, const permissions &perm)
: m_shmem (open_or_create
: m_shmem (open_or_create_t()
,name
,sizeof(interprocess_recursive_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
@@ -140,13 +175,47 @@ inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, co
{}
inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const char *name)
: m_shmem (open_only
: m_shmem (open_only_t()
,name
,read_write
,0
,construct_func_t(DoOpen))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm)
: m_shmem (create_only_t()
,name
,sizeof(interprocess_recursive_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoCreate)
,perm)
{}
inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm)
: m_shmem (open_or_create_t()
,name
,sizeof(interprocess_recursive_mutex) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoOpenOrCreate)
,perm)
{}
inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const wchar_t *name)
: m_shmem (open_only_t()
,name
,read_write
,0
,construct_func_t(DoOpen))
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void shm_named_recursive_mutex::lock()
{ this->mutex()->lock(); }
@@ -156,12 +225,20 @@ inline void shm_named_recursive_mutex::unlock()
inline bool shm_named_recursive_mutex::try_lock()
{ return this->mutex()->try_lock(); }
inline bool shm_named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool shm_named_recursive_mutex::timed_lock(const TimePoint &abs_time)
{ return this->mutex()->timed_lock(abs_time); }
inline bool shm_named_recursive_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool shm_named_recursive_mutex::remove(const wchar_t *name)
{ return shared_memory_object::remove(name); }
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
} //namespace ipcdetail {
} //namespace interprocess {
} //namespace boost {

View File

@@ -25,7 +25,6 @@
#include <boost/interprocess/exceptions.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/shared_memory_object.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
@@ -52,15 +51,31 @@ class shm_named_semaphore
shm_named_semaphore(open_only_t, const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
shm_named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions());
shm_named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions());
shm_named_semaphore(open_only_t, const wchar_t *name);
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
~shm_named_semaphore();
void post();
void wait();
bool try_wait();
bool timed_wait(const boost::posix_time::ptime &abs_time);
template<class TimePoint> bool timed_wait(const TimePoint &abs_time);
static bool remove(const char *name);
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
static bool remove(const wchar_t *name);
#endif
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
friend class interprocess_tester;
@@ -71,7 +86,7 @@ class shm_named_semaphore
typedef ipcdetail::managed_open_or_create_impl<shared_memory_object, 0, true, false> open_create_impl_t;
open_create_impl_t m_shmem;
typedef named_creation_functor<interprocess_semaphore, int> construct_func_t;
typedef named_creation_functor<interprocess_semaphore, unsigned> construct_func_t;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
@@ -114,6 +129,43 @@ inline shm_named_semaphore::shm_named_semaphore
,construct_func_t(DoOpen, 0))
{}
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline shm_named_semaphore::shm_named_semaphore
(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm)
: m_shmem (create_only
,name
,sizeof(interprocess_semaphore) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoCreate, initialCount)
,perm)
{}
inline shm_named_semaphore::shm_named_semaphore
(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm)
: m_shmem (open_or_create
,name
,sizeof(interprocess_semaphore) +
open_create_impl_t::ManagedOpenOrCreateUserOffset
,read_write
,0
,construct_func_t(DoOpenOrCreate, initialCount)
,perm)
{}
inline shm_named_semaphore::shm_named_semaphore
(open_only_t, const wchar_t *name)
: m_shmem (open_only
,name
,read_write
,0
,construct_func_t(DoOpen, 0))
{}
#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline void shm_named_semaphore::post()
{ semaphore()->post(); }
@@ -123,12 +175,20 @@ inline void shm_named_semaphore::wait()
inline bool shm_named_semaphore::try_wait()
{ return semaphore()->try_wait(); }
inline bool shm_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
template<class TimePoint>
inline bool shm_named_semaphore::timed_wait(const TimePoint &abs_time)
{ return semaphore()->timed_wait(abs_time); }
inline bool shm_named_semaphore::remove(const char *name)
{ return shared_memory_object::remove(name); }
#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
inline bool shm_named_semaphore::remove(const wchar_t *name)
{ return shared_memory_object::remove(name); }
#endif
} //namespace ipcdetail {
} //namespace interprocess {
} //namespace boost {

Some files were not shown because too many files have changed in this diff Show More