update boost
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
127
linx64/include/boost/interprocess/detail/char_wchar_holder.hpp
Normal file
127
linx64/include/boost/interprocess/detail/char_wchar_holder.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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))
|
||||
{}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ®ion, 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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){\
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
388
linx64/include/boost/interprocess/detail/timed_utils.hpp
Normal file
388
linx64/include/boost/interprocess/detail/timed_utils.hpp
Normal 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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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); }
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
|
||||
@@ -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"; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
29
linx64/include/boost/interprocess/sync/cv_status.hpp
Normal file
29
linx64/include/boost/interprocess/sync/cv_status.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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().
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user