Adding the Boost Atomic and Lockfree libraries
This commit is contained in:
parent
c391bdcc62
commit
1fce7ccec2
@ -19,7 +19,7 @@
|
||||
# the BCP tool:
|
||||
# http://www.boost.org/doc/libs/1_52_0/tools/bcp/doc/html/index.html
|
||||
#
|
||||
# bcp call: bcp boost/utility.hpp boost/python.hpp boost/bind.hpp boost/lambda/lambda.hpp boost/exception/all.hpp boost/tuple/tuple_io.hpp boost/tuple/tuple_comparison.hpp boost/regex.hpp boost/foreach.hpp boost/smart_ptr.hpp boost/algorithm/string_regex.hpp boost/thread.hpp boost/unordered_map.hpp boost/unordered_set.hpp boost/format.hpp boost/ptr_container/ptr_container.hpp boost/filesystem.hpp boost/filesystem/fstream.hpp boost/utility.hpp boost/algorithm/cxx11/any_of.hpp ../BoostParts
|
||||
# bcp call: bcp boost/utility.hpp boost/python.hpp boost/bind.hpp boost/lambda/lambda.hpp boost/exception/all.hpp boost/tuple/tuple_io.hpp boost/tuple/tuple_comparison.hpp boost/regex.hpp boost/foreach.hpp boost/smart_ptr.hpp boost/algorithm/string_regex.hpp boost/thread.hpp boost/unordered_map.hpp boost/unordered_set.hpp boost/format.hpp boost/ptr_container/ptr_container.hpp boost/filesystem.hpp boost/filesystem/fstream.hpp boost/utility.hpp boost/algorithm/cxx11/any_of.hpp atomic lockfree ../BoostParts
|
||||
|
||||
cmake_minimum_required( VERSION 2.8 )
|
||||
|
||||
|
18
cpp/BoostParts/boost/atomic.hpp
Normal file
18
cpp/BoostParts/boost/atomic.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef BOOST_ATOMIC_HPP
|
||||
#define BOOST_ATOMIC_HPP
|
||||
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
// This header includes all Boost.Atomic public headers
|
||||
|
||||
#include <boost/atomic/atomic.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#endif
|
205
cpp/BoostParts/boost/atomic/atomic.hpp
Normal file
205
cpp/BoostParts/boost/atomic/atomic.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
#ifndef BOOST_ATOMIC_ATOMIC_HPP
|
||||
#define BOOST_ATOMIC_ATOMIC_HPP
|
||||
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
#include <boost/memory_order.hpp>
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/platform.hpp>
|
||||
#include <boost/atomic/detail/type-classification.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#ifndef BOOST_ATOMIC_CHAR_LOCK_FREE
|
||||
#define BOOST_ATOMIC_CHAR_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_CHAR16_T_LOCK_FREE
|
||||
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_CHAR32_T_LOCK_FREE
|
||||
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_WCHAR_T_LOCK_FREE
|
||||
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_SHORT_LOCK_FREE
|
||||
#define BOOST_ATOMIC_SHORT_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_INT_LOCK_FREE
|
||||
#define BOOST_ATOMIC_INT_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_LONG_LOCK_FREE
|
||||
#define BOOST_ATOMIC_LONG_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_LLONG_LOCK_FREE
|
||||
#define BOOST_ATOMIC_LLONG_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_POINTER_LOCK_FREE
|
||||
#define BOOST_ATOMIC_POINTER_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#define BOOST_ATOMIC_ADDRESS_LOCK_FREE BOOST_ATOMIC_POINTER_LOCK_FREE
|
||||
|
||||
#ifndef BOOST_ATOMIC_BOOL_LOCK_FREE
|
||||
#define BOOST_ATOMIC_BOOL_LOCK_FREE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_THREAD_FENCE
|
||||
#define BOOST_ATOMIC_THREAD_FENCE 0
|
||||
inline void atomic_thread_fence(memory_order)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_SIGNAL_FENCE
|
||||
#define BOOST_ATOMIC_SIGNAL_FENCE 0
|
||||
inline void atomic_signal_fence(memory_order order)
|
||||
{
|
||||
atomic_thread_fence(order);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
class atomic :
|
||||
public atomics::detail::base_atomic<T, typename atomics::detail::classify<T>::type, atomics::detail::storage_size_of<T>::value, boost::is_signed<T>::value >
|
||||
{
|
||||
private:
|
||||
typedef T value_type;
|
||||
typedef atomics::detail::base_atomic<T, typename atomics::detail::classify<T>::type, atomics::detail::storage_size_of<T>::value, boost::is_signed<T>::value > super;
|
||||
public:
|
||||
atomic(void) : super() {}
|
||||
explicit atomic(const value_type & v) : super(v) {}
|
||||
|
||||
atomic & operator=(value_type v) volatile
|
||||
{
|
||||
super::operator=(v);
|
||||
return *const_cast<atomic *>(this);
|
||||
}
|
||||
private:
|
||||
atomic(const atomic &) /* =delete */ ;
|
||||
atomic & operator=(const atomic &) /* =delete */ ;
|
||||
};
|
||||
|
||||
typedef atomic<char> atomic_char;
|
||||
typedef atomic<unsigned char> atomic_uchar;
|
||||
typedef atomic<signed char> atomic_schar;
|
||||
typedef atomic<uint8_t> atomic_uint8_t;
|
||||
typedef atomic<int8_t> atomic_int8_t;
|
||||
typedef atomic<unsigned short> atomic_ushort;
|
||||
typedef atomic<short> atomic_short;
|
||||
typedef atomic<uint16_t> atomic_uint16_t;
|
||||
typedef atomic<int16_t> atomic_int16_t;
|
||||
typedef atomic<unsigned int> atomic_uint;
|
||||
typedef atomic<int> atomic_int;
|
||||
typedef atomic<uint32_t> atomic_uint32_t;
|
||||
typedef atomic<int32_t> atomic_int32_t;
|
||||
typedef atomic<unsigned long> atomic_ulong;
|
||||
typedef atomic<long> atomic_long;
|
||||
typedef atomic<uint64_t> atomic_uint64_t;
|
||||
typedef atomic<int64_t> atomic_int64_t;
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
typedef atomic<boost::ulong_long_type> atomic_ullong;
|
||||
typedef atomic<boost::long_long_type> atomic_llong;
|
||||
#endif
|
||||
typedef atomic<void*> atomic_address;
|
||||
typedef atomic<bool> atomic_bool;
|
||||
typedef atomic<wchar_t> atomic_wchar_t;
|
||||
#if !defined(BOOST_NO_CXX11_CHAR16_T)
|
||||
typedef atomic<char16_t> atomic_char16_t;
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_CHAR32_T)
|
||||
typedef atomic<char32_t> atomic_char32_t;
|
||||
#endif
|
||||
|
||||
typedef atomic<int_least8_t> atomic_int_least8_t;
|
||||
typedef atomic<uint_least8_t> atomic_uint_least8_t;
|
||||
typedef atomic<int_least16_t> atomic_int_least16_t;
|
||||
typedef atomic<uint_least16_t> atomic_uint_least16_t;
|
||||
typedef atomic<int_least32_t> atomic_int_least32_t;
|
||||
typedef atomic<uint_least32_t> atomic_uint_least32_t;
|
||||
typedef atomic<int_least64_t> atomic_int_least64_t;
|
||||
typedef atomic<uint_least64_t> atomic_uint_least64_t;
|
||||
typedef atomic<int_fast8_t> atomic_int_fast8_t;
|
||||
typedef atomic<uint_fast8_t> atomic_uint_fast8_t;
|
||||
typedef atomic<int_fast16_t> atomic_int_fast16_t;
|
||||
typedef atomic<uint_fast16_t> atomic_uint_fast16_t;
|
||||
typedef atomic<int_fast32_t> atomic_int_fast32_t;
|
||||
typedef atomic<uint_fast32_t> atomic_uint_fast32_t;
|
||||
typedef atomic<int_fast64_t> atomic_int_fast64_t;
|
||||
typedef atomic<uint_fast64_t> atomic_uint_fast64_t;
|
||||
typedef atomic<intmax_t> atomic_intmax_t;
|
||||
typedef atomic<uintmax_t> atomic_uintmax_t;
|
||||
|
||||
typedef atomic<std::size_t> atomic_size_t;
|
||||
typedef atomic<std::ptrdiff_t> atomic_ptrdiff_t;
|
||||
|
||||
// PGI seems to not support intptr_t/uintptr_t properly. BOOST_HAS_STDINT_H is not defined for this compiler by Boost.Config.
|
||||
#if !defined(__PGIC__)
|
||||
|
||||
#if (defined(BOOST_WINDOWS) && !defined(_WIN32_WCE)) \
|
||||
|| (defined(_XOPEN_UNIX) && (_XOPEN_UNIX+0 > 0)) \
|
||||
|| defined(__CYGWIN__) \
|
||||
|| defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
|
||||
|| defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
typedef atomic<intptr_t> atomic_intptr_t;
|
||||
typedef atomic<uintptr_t> atomic_uintptr_t;
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#if defined(__INTPTR_TYPE__)
|
||||
typedef atomic< __INTPTR_TYPE__ > atomic_intptr_t;
|
||||
#endif
|
||||
#if defined(__UINTPTR_TYPE__)
|
||||
typedef atomic< __UINTPTR_TYPE__ > atomic_uintptr_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ATOMIC_FLAG_LOCK_FREE
|
||||
#define BOOST_ATOMIC_FLAG_LOCK_FREE 0
|
||||
class atomic_flag
|
||||
{
|
||||
public:
|
||||
atomic_flag(void) : v_(false) {}
|
||||
|
||||
bool
|
||||
test_and_set(memory_order order = memory_order_seq_cst)
|
||||
{
|
||||
return v_.exchange(true, order);
|
||||
}
|
||||
|
||||
void
|
||||
clear(memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
v_.store(false, order);
|
||||
}
|
||||
private:
|
||||
atomic_flag(const atomic_flag &) /* = delete */ ;
|
||||
atomic_flag & operator=(const atomic_flag &) /* = delete */ ;
|
||||
atomic<bool> v_;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
519
cpp/BoostParts/boost/atomic/detail/base.hpp
Normal file
519
cpp/BoostParts/boost/atomic/detail/base.hpp
Normal file
@ -0,0 +1,519 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_BASE_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_BASE_HPP
|
||||
|
||||
// Copyright (c) 2009 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
// Base class definition and fallback implementation.
|
||||
// To be overridden (through partial specialization) by
|
||||
// platform implementations.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/lockpool.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#define BOOST_ATOMIC_DECLARE_BASE_OPERATORS \
|
||||
operator value_type(void) volatile const \
|
||||
{ \
|
||||
return load(memory_order_seq_cst); \
|
||||
} \
|
||||
\
|
||||
this_type & \
|
||||
operator=(value_type v) volatile \
|
||||
{ \
|
||||
store(v, memory_order_seq_cst); \
|
||||
return *const_cast<this_type *>(this); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
compare_exchange_strong( \
|
||||
value_type & expected, \
|
||||
value_type desired, \
|
||||
memory_order order = memory_order_seq_cst) volatile \
|
||||
{ \
|
||||
return compare_exchange_strong(expected, desired, order, calculate_failure_order(order)); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
compare_exchange_weak( \
|
||||
value_type & expected, \
|
||||
value_type desired, \
|
||||
memory_order order = memory_order_seq_cst) volatile \
|
||||
{ \
|
||||
return compare_exchange_weak(expected, desired, order, calculate_failure_order(order)); \
|
||||
} \
|
||||
\
|
||||
|
||||
#define BOOST_ATOMIC_DECLARE_ADDITIVE_OPERATORS \
|
||||
value_type \
|
||||
operator++(int) volatile \
|
||||
{ \
|
||||
return fetch_add(1); \
|
||||
} \
|
||||
\
|
||||
value_type \
|
||||
operator++(void) volatile \
|
||||
{ \
|
||||
return fetch_add(1) + 1; \
|
||||
} \
|
||||
\
|
||||
value_type \
|
||||
operator--(int) volatile \
|
||||
{ \
|
||||
return fetch_sub(1); \
|
||||
} \
|
||||
\
|
||||
value_type \
|
||||
operator--(void) volatile \
|
||||
{ \
|
||||
return fetch_sub(1) - 1; \
|
||||
} \
|
||||
\
|
||||
value_type \
|
||||
operator+=(difference_type v) volatile \
|
||||
{ \
|
||||
return fetch_add(v) + v; \
|
||||
} \
|
||||
\
|
||||
value_type \
|
||||
operator-=(difference_type v) volatile \
|
||||
{ \
|
||||
return fetch_sub(v) - v; \
|
||||
} \
|
||||
|
||||
#define BOOST_ATOMIC_DECLARE_BIT_OPERATORS \
|
||||
value_type \
|
||||
operator&=(difference_type v) volatile \
|
||||
{ \
|
||||
return fetch_and(v) & v; \
|
||||
} \
|
||||
\
|
||||
value_type \
|
||||
operator|=(difference_type v) volatile \
|
||||
{ \
|
||||
return fetch_or(v) | v; \
|
||||
} \
|
||||
\
|
||||
value_type \
|
||||
operator^=(difference_type v) volatile \
|
||||
{ \
|
||||
return fetch_xor(v) ^ v; \
|
||||
} \
|
||||
|
||||
#define BOOST_ATOMIC_DECLARE_POINTER_OPERATORS \
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS \
|
||||
BOOST_ATOMIC_DECLARE_ADDITIVE_OPERATORS \
|
||||
|
||||
#define BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS \
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS \
|
||||
BOOST_ATOMIC_DECLARE_ADDITIVE_OPERATORS \
|
||||
BOOST_ATOMIC_DECLARE_BIT_OPERATORS \
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
inline memory_order
|
||||
calculate_failure_order(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_acq_rel:
|
||||
return memory_order_acquire;
|
||||
case memory_order_release:
|
||||
return memory_order_relaxed;
|
||||
default:
|
||||
return order;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename C, unsigned int Size, bool Sign>
|
||||
class base_atomic {
|
||||
private:
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef lockpool::scoped_lock guard_type;
|
||||
public:
|
||||
base_atomic(void) {}
|
||||
|
||||
explicit base_atomic(const value_type & v)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
|
||||
void
|
||||
store(value_type const& v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<char *>(v_));
|
||||
|
||||
memcpy(const_cast<char *>(v_), &v, sizeof(value_type));
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order /*order*/ = memory_order_seq_cst) volatile const
|
||||
{
|
||||
guard_type guard(const_cast<const char *>(v_));
|
||||
|
||||
value_type v;
|
||||
memcpy(&v, const_cast<const char *>(v_), sizeof(value_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order /*success_order*/,
|
||||
memory_order /*failure_order*/) volatile
|
||||
{
|
||||
guard_type guard(const_cast<char *>(v_));
|
||||
|
||||
if (memcmp(const_cast<char *>(v_), &expected, sizeof(value_type)) == 0) {
|
||||
memcpy(const_cast<char *>(v_), &desired, sizeof(value_type));
|
||||
return true;
|
||||
} else {
|
||||
memcpy(&expected, const_cast<char *>(v_), sizeof(value_type));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order /*order*/=memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<char *>(v_));
|
||||
|
||||
value_type tmp;
|
||||
memcpy(&tmp, const_cast<char *>(v_), sizeof(value_type));
|
||||
|
||||
memcpy(const_cast<char *>(v_), &v, sizeof(value_type));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
|
||||
char v_[sizeof(value_type)];
|
||||
};
|
||||
|
||||
template<typename T, unsigned int Size, bool Sign>
|
||||
class base_atomic<T, int, Size, Sign> {
|
||||
private:
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
typedef lockpool::scoped_lock guard_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
v_ = v;
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order /*order*/ = memory_order_seq_cst) const volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ = v;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(value_type & expected, value_type desired,
|
||||
memory_order /*success_order*/,
|
||||
memory_order /*failure_order*/) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
if (v_ == expected) {
|
||||
v_ = desired;
|
||||
return true;
|
||||
} else {
|
||||
expected = v_;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(value_type & expected, value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(difference_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ += v;
|
||||
return old;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(difference_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ -= v;
|
||||
return old;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ &= v;
|
||||
return old;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ |= v;
|
||||
return old;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ ^= v;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
template<typename T, unsigned int Size, bool Sign>
|
||||
class base_atomic<T *, void *, Size, Sign> {
|
||||
private:
|
||||
typedef base_atomic this_type;
|
||||
typedef T * value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef lockpool::scoped_lock guard_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
v_ = v;
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order /*order*/ = memory_order_seq_cst) const volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ = v;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(value_type & expected, value_type desired,
|
||||
memory_order /*success_order*/,
|
||||
memory_order /*failure_order*/) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
if (v_ == expected) {
|
||||
v_ = desired;
|
||||
return true;
|
||||
} else {
|
||||
expected = v_;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(value_type & expected, value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
value_type fetch_add(difference_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ += v;
|
||||
return old;
|
||||
}
|
||||
|
||||
value_type fetch_sub(difference_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ -= v;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
template<unsigned int Size, bool Sign>
|
||||
class base_atomic<void *, void *, Size, Sign> {
|
||||
private:
|
||||
typedef base_atomic this_type;
|
||||
typedef void * value_type;
|
||||
typedef lockpool::scoped_lock guard_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
v_ = v;
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order /*order*/ = memory_order_seq_cst) const volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order /*order*/ = memory_order_seq_cst) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
value_type old = v_;
|
||||
v_ = v;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(value_type & expected, value_type desired,
|
||||
memory_order /*success_order*/,
|
||||
memory_order /*failure_order*/) volatile
|
||||
{
|
||||
guard_type guard(const_cast<value_type *>(&v_));
|
||||
|
||||
if (v_ == expected) {
|
||||
v_ = desired;
|
||||
return true;
|
||||
} else {
|
||||
expected = v_;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(value_type & expected, value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
872
cpp/BoostParts/boost/atomic/detail/cas32strong.hpp
Normal file
872
cpp/BoostParts/boost/atomic/detail/cas32strong.hpp
Normal file
@ -0,0 +1,872 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_CAS32STRONG_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_CAS32STRONG_HPP
|
||||
|
||||
// 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)
|
||||
//
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
|
||||
// Build 8-, 16- and 32-bit atomic operations from
|
||||
// a platform_cmpxchg32_strong primitive.
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
/* integral types */
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, int, 1, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
storage_type expected_s = (storage_type) expected;
|
||||
storage_type desired_s = (storage_type) desired;
|
||||
|
||||
bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
expected = (value_type) expected_s;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, int, 2, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
storage_type expected_s = (storage_type) expected;
|
||||
storage_type desired_s = (storage_type) desired;
|
||||
|
||||
bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
expected = (value_type) expected_s;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, int, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile value_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32_strong(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
/* pointer types */
|
||||
|
||||
template<bool Sign>
|
||||
class base_atomic<void *, void *, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef void * value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile value_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32_strong(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T *, void *, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T * value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile value_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32_strong(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
/* generic types */
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, void, 1, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type const& v)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
storage_type tmp = 0;
|
||||
memcpy(&tmp, &v, sizeof(value_type));
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = tmp;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
storage_type tmp = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
|
||||
value_type v;
|
||||
memcpy(&v, &tmp, sizeof(value_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
storage_type expected_s = 0, desired_s = 0;
|
||||
memcpy(&expected_s, &expected, sizeof(value_type));
|
||||
memcpy(&desired_s, &desired, sizeof(value_type));
|
||||
|
||||
platform_fence_before(success_order);
|
||||
bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
memcpy(&expected, &expected_s, sizeof(value_type));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, void, 2, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type const& v)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
storage_type tmp = 0;
|
||||
memcpy(&tmp, &v, sizeof(value_type));
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = tmp;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
storage_type tmp = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
|
||||
value_type v;
|
||||
memcpy(&v, &tmp, sizeof(value_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
|
||||
storage_type expected_s = 0, desired_s = 0;
|
||||
memcpy(&expected_s, &expected, sizeof(value_type));
|
||||
memcpy(&desired_s, &desired, sizeof(value_type));
|
||||
|
||||
platform_fence_before(success_order);
|
||||
bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
memcpy(&expected, &expected_s, sizeof(value_type));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, void, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type const& v) : v_(0)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
storage_type tmp = 0;
|
||||
memcpy(&tmp, &v, sizeof(value_type));
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = tmp;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
storage_type tmp = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
|
||||
value_type v;
|
||||
memcpy(&v, &tmp, sizeof(value_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
|
||||
storage_type expected_s = 0, desired_s = 0;
|
||||
memcpy(&expected_s, &expected, sizeof(value_type));
|
||||
memcpy(&desired_s, &desired, sizeof(value_type));
|
||||
|
||||
platform_fence_before(success_order);
|
||||
bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
memcpy(&expected, &expected_s, sizeof(value_type));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
916
cpp/BoostParts/boost/atomic/detail/cas32weak.hpp
Normal file
916
cpp/BoostParts/boost/atomic/detail/cas32weak.hpp
Normal file
@ -0,0 +1,916 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_CAS32WEAK_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_CAS32WEAK_HPP
|
||||
|
||||
// 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)
|
||||
//
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
/* integral types */
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, int, 1, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
storage_type expected_s = (storage_type) expected;
|
||||
storage_type desired_s = (storage_type) desired;
|
||||
|
||||
bool success = platform_cmpxchg32(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
expected = (value_type) expected_s;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, int, 2, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
storage_type expected_s = (storage_type) expected;
|
||||
storage_type desired_s = (storage_type) desired;
|
||||
|
||||
bool success = platform_cmpxchg32(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
expected = (value_type) expected_s;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, int, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile value_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
/* pointer types */
|
||||
|
||||
template<bool Sign>
|
||||
class base_atomic<void *, void *, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef void * value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile value_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T *, void *, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T * value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile value_type &>(v_) = v;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = const_cast<const volatile value_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
/* generic types */
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, void, 1, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type const& v) : v_(0)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
storage_type tmp = 0;
|
||||
memcpy(&tmp, &v, sizeof(value_type));
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = tmp;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
storage_type tmp = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
|
||||
value_type v;
|
||||
memcpy(&v, &tmp, sizeof(value_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
storage_type expected_s = 0, desired_s = 0;
|
||||
memcpy(&expected_s, &expected, sizeof(value_type));
|
||||
memcpy(&desired_s, &desired, sizeof(value_type));
|
||||
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
memcpy(&expected, &expected_s, sizeof(value_type));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, void, 2, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type const& v) : v_(0)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
storage_type tmp = 0;
|
||||
memcpy(&tmp, &v, sizeof(value_type));
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = tmp;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
storage_type tmp = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
|
||||
value_type v;
|
||||
memcpy(&v, &tmp, sizeof(value_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
storage_type expected_s = 0, desired_s = 0;
|
||||
memcpy(&expected_s, &expected, sizeof(value_type));
|
||||
memcpy(&desired_s, &desired, sizeof(value_type));
|
||||
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
memcpy(&expected, &expected_s, sizeof(value_type));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, void, 4, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef uint32_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type const& v) : v_(0)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
storage_type tmp = 0;
|
||||
memcpy(&tmp, &v, sizeof(value_type));
|
||||
platform_fence_before_store(order);
|
||||
const_cast<volatile storage_type &>(v_) = tmp;
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
storage_type tmp = const_cast<const volatile storage_type &>(v_);
|
||||
platform_fence_after_load(order);
|
||||
|
||||
value_type v;
|
||||
memcpy(&v, &tmp, sizeof(value_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
storage_type expected_s = 0, desired_s = 0;
|
||||
memcpy(&expected_s, &expected, sizeof(value_type));
|
||||
memcpy(&desired_s, &desired, sizeof(value_type));
|
||||
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg32(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
memcpy(&expected, &expected_s, sizeof(value_type));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
for(;;) {
|
||||
value_type tmp = expected;
|
||||
if (compare_exchange_weak(tmp, desired, success_order, failure_order))
|
||||
return true;
|
||||
if (tmp != expected) {
|
||||
expected = tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
438
cpp/BoostParts/boost/atomic/detail/cas64strong.hpp
Normal file
438
cpp/BoostParts/boost/atomic/detail/cas64strong.hpp
Normal file
@ -0,0 +1,438 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_CAS64STRONG_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_CAS64STRONG_HPP
|
||||
|
||||
// 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)
|
||||
//
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
|
||||
// Build 64-bit atomic operation from platform_cmpxchg64_strong
|
||||
// primitive. It is assumed that 64-bit loads/stores are not
|
||||
// atomic, so they are funnelled through cmpxchg as well.
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
/* integral types */
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, int, 8, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
platform_store64(v, &v_);
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = platform_load64(&v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg64_strong(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
/* pointer types */
|
||||
|
||||
template<bool Sign>
|
||||
class base_atomic<void *, void *, 8, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef void * value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
platform_store64(v, &v_);
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = platform_load64(&v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg64_strong(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T *, void *, 8, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T * value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
public:
|
||||
explicit base_atomic(value_type v) : v_(v) {}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
platform_fence_before_store(order);
|
||||
platform_store64(v, &v_);
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
value_type v = platform_load64(&v_);
|
||||
platform_fence_after_load(order);
|
||||
return v;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
platform_fence_before(success_order);
|
||||
|
||||
bool success = platform_cmpxchg64_strong(expected, desired, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
value_type
|
||||
fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
value_type v_;
|
||||
};
|
||||
|
||||
/* generic types */
|
||||
|
||||
template<typename T, bool Sign>
|
||||
class base_atomic<T, void, 8, Sign> {
|
||||
typedef base_atomic this_type;
|
||||
typedef T value_type;
|
||||
typedef uint64_t storage_type;
|
||||
public:
|
||||
explicit base_atomic(value_type const& v) : v_(0)
|
||||
{
|
||||
memcpy(&v_, &v, sizeof(value_type));
|
||||
}
|
||||
base_atomic(void) {}
|
||||
|
||||
void
|
||||
store(value_type const& value, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
storage_type value_s = 0;
|
||||
memcpy(&value_s, &value, sizeof(value_s));
|
||||
platform_fence_before_store(order);
|
||||
platform_store64(value_s, &v_);
|
||||
platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
value_type
|
||||
load(memory_order order = memory_order_seq_cst) const volatile
|
||||
{
|
||||
storage_type value_s = platform_load64(&v_);
|
||||
platform_fence_after_load(order);
|
||||
value_type value;
|
||||
memcpy(&value, &value_s, sizeof(value_s));
|
||||
return value;
|
||||
}
|
||||
|
||||
value_type
|
||||
exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
value_type original = load(memory_order_relaxed);
|
||||
do {
|
||||
} while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
|
||||
return original;
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(
|
||||
value_type & expected,
|
||||
value_type const& desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
storage_type expected_s = 0, desired_s = 0;
|
||||
memcpy(&expected_s, &expected, sizeof(value_type));
|
||||
memcpy(&desired_s, &desired, sizeof(value_type));
|
||||
|
||||
platform_fence_before(success_order);
|
||||
bool success = platform_cmpxchg64_strong(expected_s, desired_s, &v_);
|
||||
|
||||
if (success) {
|
||||
platform_fence_after(success_order);
|
||||
} else {
|
||||
platform_fence_after(failure_order);
|
||||
memcpy(&expected, &expected_s, sizeof(value_type));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
is_lock_free(void) const volatile
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_ATOMIC_DECLARE_BASE_OPERATORS
|
||||
private:
|
||||
base_atomic(const base_atomic &) /* = delete */ ;
|
||||
void operator=(const base_atomic &) /* = delete */ ;
|
||||
storage_type v_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
54
cpp/BoostParts/boost/atomic/detail/config.hpp
Normal file
54
cpp/BoostParts/boost/atomic/detail/config.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_CONFIG_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_CONFIG_HPP
|
||||
|
||||
// Copyright (c) 2012 Hartmut Kaiser
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1020)) || defined(__GNUC__) || defined(BOOST_CLANG) || defined(BOOST_INTEL) || defined(__COMO__) || defined(__DMC__)
|
||||
#define BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Set up dll import/export options
|
||||
#if (defined(BOOST_ATOMIC_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && \
|
||||
!defined(BOOST_ATOMIC_STATIC_LINK)
|
||||
|
||||
#if defined(BOOST_ATOMIC_SOURCE)
|
||||
#define BOOST_ATOMIC_DECL BOOST_SYMBOL_EXPORT
|
||||
#define BOOST_ATOMIC_BUILD_DLL
|
||||
#else
|
||||
#define BOOST_ATOMIC_DECL BOOST_SYMBOL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // building a shared library
|
||||
|
||||
#ifndef BOOST_ATOMIC_DECL
|
||||
#define BOOST_ATOMIC_DECL
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Auto library naming
|
||||
#if !defined(BOOST_ATOMIC_SOURCE) && !defined(BOOST_ALL_NO_LIB) && \
|
||||
!defined(BOOST_ATOMIC_NO_LIB)
|
||||
|
||||
#define BOOST_LIB_NAME boost_atomic
|
||||
|
||||
// tell the auto-link code to select a dll when required:
|
||||
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ATOMIC_DYN_LINK)
|
||||
#define BOOST_DYN_LINK
|
||||
#endif
|
||||
|
||||
#include <boost/config/auto_link.hpp>
|
||||
|
||||
#endif // auto-linking disabled
|
||||
|
||||
#endif
|
359
cpp/BoostParts/boost/atomic/detail/gcc-alpha.hpp
Normal file
359
cpp/BoostParts/boost/atomic/detail/gcc-alpha.hpp
Normal file
@ -0,0 +1,359 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_GCC_ALPHA_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_GCC_ALPHA_HPP
|
||||
|
||||
// Copyright (c) 2009 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
#include <boost/atomic/detail/builder.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*
|
||||
Refer to http://h71000.www7.hp.com/doc/82final/5601/5601pro_004.html
|
||||
(HP OpenVMS systems documentation) and the alpha reference manual.
|
||||
*/
|
||||
|
||||
/*
|
||||
NB: The most natural thing would be to write the increment/decrement
|
||||
operators along the following lines:
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0,%1 \n"
|
||||
"addl %0,1,%0 \n"
|
||||
"stl_c %0,%1 \n"
|
||||
"beq %0,1b\n"
|
||||
: "=&b" (tmp)
|
||||
: "m" (value)
|
||||
: "cc"
|
||||
);
|
||||
|
||||
However according to the comments on the HP website and matching
|
||||
comments in the Linux kernel sources this defies branch prediction,
|
||||
as the cpu assumes that backward branches are always taken; so
|
||||
instead copy the trick from the Linux kernel, introduce a forward
|
||||
branch and back again.
|
||||
|
||||
I have, however, had a hard time measuring the difference between
|
||||
the two versions in microbenchmarks -- I am leaving it in nevertheless
|
||||
as it apparently does not hurt either.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
inline void fence_before(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_consume:
|
||||
case memory_order_release:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
__asm__ __volatile__ ("mb" ::: "memory");
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
inline void fence_after(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_acquire:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
__asm__ __volatile__ ("mb" ::: "memory");
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void platform_atomic_thread_fence(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_acquire:
|
||||
case memory_order_consume:
|
||||
case memory_order_release:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
__asm__ __volatile__ ("mb" ::: "memory");
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class atomic_alpha_32 {
|
||||
public:
|
||||
typedef T integral_type;
|
||||
explicit atomic_alpha_32(T v) : i(v) {}
|
||||
atomic_alpha_32() {}
|
||||
T load(memory_order order=memory_order_seq_cst) const volatile
|
||||
{
|
||||
T v=*reinterpret_cast<volatile const int *>(&i);
|
||||
fence_after(order);
|
||||
return v;
|
||||
}
|
||||
void store(T v, memory_order order=memory_order_seq_cst) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
*reinterpret_cast<volatile int *>(&i)=(int)v;
|
||||
}
|
||||
bool compare_exchange_weak(
|
||||
T &expected,
|
||||
T desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
fence_before(success_order);
|
||||
int current, success;
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %2, %4\n"
|
||||
"cmpeq %2, %0, %3\n"
|
||||
"mov %2, %0\n"
|
||||
"beq %3, 3f\n"
|
||||
"stl_c %1, %4\n"
|
||||
"2:\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"3: mov %3, %1\n"
|
||||
"br 2b\n"
|
||||
".previous\n"
|
||||
|
||||
: "+&r" (expected), "+&r" (desired), "=&r"(current), "=&r"(success)
|
||||
: "m" (i)
|
||||
:
|
||||
);
|
||||
if (desired) fence_after(success_order);
|
||||
else fence_after(failure_order);
|
||||
return desired;
|
||||
}
|
||||
|
||||
bool is_lock_free(void) const volatile {return true;}
|
||||
protected:
|
||||
inline T fetch_add_var(T c, memory_order order) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
T original, modified;
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0, %2\n"
|
||||
"addl %0, %3, %1\n"
|
||||
"stl_c %1, %2\n"
|
||||
"beq %1, 2f\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous\n"
|
||||
|
||||
: "=&r" (original), "=&r" (modified)
|
||||
: "m" (i), "r" (c)
|
||||
:
|
||||
);
|
||||
fence_after(order);
|
||||
return original;
|
||||
}
|
||||
inline T fetch_inc(memory_order order) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
int original, modified;
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0, %2\n"
|
||||
"addl %0, 1, %1\n"
|
||||
"stl_c %1, %2\n"
|
||||
"beq %1, 2f\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous\n"
|
||||
|
||||
: "=&r" (original), "=&r" (modified)
|
||||
: "m" (i)
|
||||
:
|
||||
);
|
||||
fence_after(order);
|
||||
return original;
|
||||
}
|
||||
inline T fetch_dec(memory_order order) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
int original, modified;
|
||||
__asm__ __volatile__(
|
||||
"1: ldl_l %0, %2\n"
|
||||
"subl %0, 1, %1\n"
|
||||
"stl_c %1, %2\n"
|
||||
"beq %1, 2f\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous\n"
|
||||
|
||||
: "=&r" (original), "=&r" (modified)
|
||||
: "m" (i)
|
||||
:
|
||||
);
|
||||
fence_after(order);
|
||||
return original;
|
||||
}
|
||||
private:
|
||||
T i;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class atomic_alpha_64 {
|
||||
public:
|
||||
typedef T integral_type;
|
||||
explicit atomic_alpha_64(T v) : i(v) {}
|
||||
atomic_alpha_64() {}
|
||||
T load(memory_order order=memory_order_seq_cst) const volatile
|
||||
{
|
||||
T v=*reinterpret_cast<volatile const T *>(&i);
|
||||
fence_after(order);
|
||||
return v;
|
||||
}
|
||||
void store(T v, memory_order order=memory_order_seq_cst) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
*reinterpret_cast<volatile T *>(&i)=v;
|
||||
}
|
||||
bool compare_exchange_weak(
|
||||
T &expected,
|
||||
T desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
fence_before(success_order);
|
||||
int current, success;
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %2, %4\n"
|
||||
"cmpeq %2, %0, %3\n"
|
||||
"mov %2, %0\n"
|
||||
"beq %3, 3f\n"
|
||||
"stq_c %1, %4\n"
|
||||
"2:\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"3: mov %3, %1\n"
|
||||
"br 2b\n"
|
||||
".previous\n"
|
||||
|
||||
: "+&r" (expected), "+&r" (desired), "=&r"(current), "=&r"(success)
|
||||
: "m" (i)
|
||||
:
|
||||
);
|
||||
if (desired) fence_after(success_order);
|
||||
else fence_after(failure_order);
|
||||
return desired;
|
||||
}
|
||||
|
||||
bool is_lock_free(void) const volatile {return true;}
|
||||
protected:
|
||||
inline T fetch_add_var(T c, memory_order order) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
T original, modified;
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0, %2\n"
|
||||
"addq %0, %3, %1\n"
|
||||
"stq_c %1, %2\n"
|
||||
"beq %1, 2f\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous\n"
|
||||
|
||||
: "=&r" (original), "=&r" (modified)
|
||||
: "m" (i), "r" (c)
|
||||
:
|
||||
);
|
||||
fence_after(order);
|
||||
return original;
|
||||
}
|
||||
inline T fetch_inc(memory_order order) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
T original, modified;
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0, %2\n"
|
||||
"addq %0, 1, %1\n"
|
||||
"stq_c %1, %2\n"
|
||||
"beq %1, 2f\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous\n"
|
||||
|
||||
: "=&r" (original), "=&r" (modified)
|
||||
: "m" (i)
|
||||
:
|
||||
);
|
||||
fence_after(order);
|
||||
return original;
|
||||
}
|
||||
inline T fetch_dec(memory_order order) volatile
|
||||
{
|
||||
fence_before(order);
|
||||
T original, modified;
|
||||
__asm__ __volatile__(
|
||||
"1: ldq_l %0, %2\n"
|
||||
"subq %0, 1, %1\n"
|
||||
"stq_c %1, %2\n"
|
||||
"beq %1, 2f\n"
|
||||
|
||||
".subsection 2\n"
|
||||
"2: br 1b\n"
|
||||
".previous\n"
|
||||
|
||||
: "=&r" (original), "=&r" (modified)
|
||||
: "m" (i)
|
||||
:
|
||||
);
|
||||
fence_after(order);
|
||||
return original;
|
||||
}
|
||||
private:
|
||||
T i;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class platform_atomic_integral<T, 4> : public build_atomic_from_typical<build_exchange<atomic_alpha_32<T> > > {
|
||||
public:
|
||||
typedef build_atomic_from_typical<build_exchange<atomic_alpha_32<T> > > super;
|
||||
explicit platform_atomic_integral(T v) : super(v) {}
|
||||
platform_atomic_integral(void) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class platform_atomic_integral<T, 8> : public build_atomic_from_typical<build_exchange<atomic_alpha_64<T> > > {
|
||||
public:
|
||||
typedef build_atomic_from_typical<build_exchange<atomic_alpha_64<T> > > super;
|
||||
explicit platform_atomic_integral(T v) : super(v) {}
|
||||
platform_atomic_integral(void) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class platform_atomic_integral<T, 1>: public build_atomic_from_larger_type<atomic_alpha_32<uint32_t>, T> {
|
||||
public:
|
||||
typedef build_atomic_from_larger_type<atomic_alpha_32<uint32_t>, T> super;
|
||||
|
||||
explicit platform_atomic_integral(T v) : super(v) {}
|
||||
platform_atomic_integral(void) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class platform_atomic_integral<T, 2>: public build_atomic_from_larger_type<atomic_alpha_32<uint32_t>, T> {
|
||||
public:
|
||||
typedef build_atomic_from_larger_type<atomic_alpha_32<uint32_t>, T> super;
|
||||
|
||||
explicit platform_atomic_integral(T v) : super(v) {}
|
||||
platform_atomic_integral(void) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
250
cpp/BoostParts/boost/atomic/detail/gcc-armv6plus.hpp
Normal file
250
cpp/BoostParts/boost/atomic/detail/gcc-armv6plus.hpp
Normal file
@ -0,0 +1,250 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_GCC_ARMV6PLUS_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_GCC_ARMV6PLUS_HPP
|
||||
|
||||
// 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)
|
||||
//
|
||||
// Copyright (c) 2009 Helge Bahmann
|
||||
// Copyright (c) 2009 Phil Endecott
|
||||
// ARM Code by Phil Endecott, based on other architectures.
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// From the ARM Architecture Reference Manual for architecture v6:
|
||||
//
|
||||
// LDREX{<cond>} <Rd>, [<Rn>]
|
||||
// <Rd> Specifies the destination register for the memory word addressed by <Rd>
|
||||
// <Rn> Specifies the register containing the address.
|
||||
//
|
||||
// STREX{<cond>} <Rd>, <Rm>, [<Rn>]
|
||||
// <Rd> Specifies the destination register for the returned status value.
|
||||
// 0 if the operation updates memory
|
||||
// 1 if the operation fails to update memory
|
||||
// <Rm> Specifies the register containing the word to be stored to memory.
|
||||
// <Rn> Specifies the register containing the address.
|
||||
// Rd must not be the same register as Rm or Rn.
|
||||
//
|
||||
// ARM v7 is like ARM v6 plus:
|
||||
// There are half-word and byte versions of the LDREX and STREX instructions,
|
||||
// LDREXH, LDREXB, STREXH and STREXB.
|
||||
// There are also double-word versions, LDREXD and STREXD.
|
||||
// (Actually it looks like these are available from version 6k onwards.)
|
||||
// FIXME these are not yet used; should be mostly a matter of copy-and-paste.
|
||||
// I think you can supply an immediate offset to the address.
|
||||
//
|
||||
// A memory barrier is effected using a "co-processor 15" instruction,
|
||||
// though a separate assembler mnemonic is available for it in v7.
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
// "Thumb 1" is a subset of the ARM instruction set that uses a 16-bit encoding. It
|
||||
// doesn't include all instructions and in particular it doesn't include the co-processor
|
||||
// instruction used for the memory barrier or the load-locked/store-conditional
|
||||
// instructions. So, if we're compiling in "Thumb 1" mode, we need to wrap all of our
|
||||
// asm blocks with code to temporarily change to ARM mode.
|
||||
//
|
||||
// You can only change between ARM and Thumb modes when branching using the bx instruction.
|
||||
// bx takes an address specified in a register. The least significant bit of the address
|
||||
// indicates the mode, so 1 is added to indicate that the destination code is Thumb.
|
||||
// A temporary register is needed for the address and is passed as an argument to these
|
||||
// macros. It must be one of the "low" registers accessible to Thumb code, specified
|
||||
// using the "l" attribute in the asm statement.
|
||||
//
|
||||
// Architecture v7 introduces "Thumb 2", which does include (almost?) all of the ARM
|
||||
// instruction set. So in v7 we don't need to change to ARM mode; we can write "universal
|
||||
// assembler" which will assemble to Thumb 2 or ARM code as appropriate. The only thing
|
||||
// we need to do to make this "universal" assembler mode work is to insert "IT" instructions
|
||||
// to annotate the conditional instructions. These are ignored in other modes (e.g. v6),
|
||||
// so they can always be present.
|
||||
|
||||
#if defined(__thumb__) && !defined(__ARM_ARCH_7A__)
|
||||
// FIXME also other v7 variants.
|
||||
#define BOOST_ATOMIC_ARM_ASM_START(TMPREG) "adr " #TMPREG ", 1f\n" "bx " #TMPREG "\n" ".arm\n" ".align 4\n" "1: "
|
||||
#define BOOST_ATOMIC_ARM_ASM_END(TMPREG) "adr " #TMPREG ", 1f + 1\n" "bx " #TMPREG "\n" ".thumb\n" ".align 2\n" "1: "
|
||||
|
||||
#else
|
||||
// The tmpreg is wasted in this case, which is non-optimal.
|
||||
#define BOOST_ATOMIC_ARM_ASM_START(TMPREG)
|
||||
#define BOOST_ATOMIC_ARM_ASM_END(TMPREG)
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_7A__)
|
||||
// FIXME ditto.
|
||||
#define BOOST_ATOMIC_ARM_DMB "dmb\n"
|
||||
#else
|
||||
#define BOOST_ATOMIC_ARM_DMB "mcr\tp15, 0, r0, c7, c10, 5\n"
|
||||
#endif
|
||||
|
||||
inline void
|
||||
arm_barrier(void)
|
||||
{
|
||||
int brtmp;
|
||||
__asm__ __volatile__ (
|
||||
BOOST_ATOMIC_ARM_ASM_START(%0)
|
||||
BOOST_ATOMIC_ARM_DMB
|
||||
BOOST_ATOMIC_ARM_ASM_END(%0)
|
||||
: "=&l" (brtmp) :: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_before(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_release:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
arm_barrier();
|
||||
case memory_order_consume:
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_acquire:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
arm_barrier();
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_before_store(memory_order order)
|
||||
{
|
||||
platform_fence_before(order);
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after_store(memory_order order)
|
||||
{
|
||||
if (order == memory_order_seq_cst)
|
||||
arm_barrier();
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after_load(memory_order order)
|
||||
{
|
||||
platform_fence_after(order);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
platform_cmpxchg32(T & expected, T desired, volatile T * ptr)
|
||||
{
|
||||
int success;
|
||||
int tmp;
|
||||
__asm__ (
|
||||
BOOST_ATOMIC_ARM_ASM_START(%2)
|
||||
"mov %1, #0\n" // success = 0
|
||||
"ldrex %0, %3\n" // expected' = *(&i)
|
||||
"teq %0, %4\n" // flags = expected'==expected
|
||||
"ittt eq\n"
|
||||
"strexeq %2, %5, %3\n" // if (flags.equal) *(&i) = desired, tmp = !OK
|
||||
"teqeq %2, #0\n" // if (flags.equal) flags = tmp==0
|
||||
"moveq %1, #1\n" // if (flags.equal) success = 1
|
||||
BOOST_ATOMIC_ARM_ASM_END(%2)
|
||||
: "=&r" (expected), // %0
|
||||
"=&r" (success), // %1
|
||||
"=&l" (tmp), // %2
|
||||
"+Q" (*ptr) // %3
|
||||
: "r" (expected), // %4
|
||||
"r" (desired) // %5
|
||||
: "cc"
|
||||
);
|
||||
return success;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_THREAD_FENCE 2
|
||||
inline void
|
||||
atomic_thread_fence(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_acquire:
|
||||
case memory_order_release:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
atomics::detail::arm_barrier();
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_SIGNAL_FENCE 2
|
||||
inline void
|
||||
atomic_signal_fence(memory_order)
|
||||
{
|
||||
__asm__ __volatile__ ("" ::: "memory");
|
||||
}
|
||||
|
||||
class atomic_flag {
|
||||
private:
|
||||
atomic_flag(const atomic_flag &) /* = delete */ ;
|
||||
atomic_flag & operator=(const atomic_flag &) /* = delete */ ;
|
||||
uint32_t v_;
|
||||
public:
|
||||
atomic_flag(void) : v_(false) {}
|
||||
|
||||
void
|
||||
clear(memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
atomics::detail::platform_fence_before_store(order);
|
||||
const_cast<volatile uint32_t &>(v_) = 0;
|
||||
atomics::detail::platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
bool
|
||||
test_and_set(memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
atomics::detail::platform_fence_before(order);
|
||||
uint32_t expected = v_;
|
||||
do {
|
||||
if (expected == 1)
|
||||
break;
|
||||
} while (!atomics::detail::platform_cmpxchg32(expected, (uint32_t)1, &v_));
|
||||
atomics::detail::platform_fence_after(order);
|
||||
return expected;
|
||||
}
|
||||
};
|
||||
#define BOOST_ATOMIC_FLAG_LOCK_FREE 2
|
||||
|
||||
}
|
||||
|
||||
#undef BOOST_ATOMIC_ARM_ASM_START
|
||||
#undef BOOST_ATOMIC_ARM_ASM_END
|
||||
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
|
||||
#if !defined(BOOST_ATOMIC_FORCE_FALLBACK)
|
||||
|
||||
#define BOOST_ATOMIC_CHAR_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_SHORT_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_INT_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_LONG_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_LLONG_LOCK_FREE 0
|
||||
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_BOOL_LOCK_FREE 2
|
||||
|
||||
#include <boost/atomic/detail/cas32weak.hpp>
|
||||
|
||||
#endif /* !defined(BOOST_ATOMIC_FORCE_FALLBACK) */
|
||||
|
||||
#endif
|
||||
|
155
cpp/BoostParts/boost/atomic/detail/gcc-cas.hpp
Normal file
155
cpp/BoostParts/boost/atomic/detail/gcc-cas.hpp
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
// Use the gnu builtin __sync_val_compare_and_swap to build
|
||||
// atomic operations for 32 bit and smaller.
|
||||
|
||||
#ifndef BOOST_ATOMIC_DETAIL_GENERIC_CAS_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_GENERIC_CAS_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#define BOOST_ATOMIC_THREAD_FENCE 2
|
||||
inline void
|
||||
atomic_thread_fence(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_relaxed:
|
||||
break;
|
||||
case memory_order_release:
|
||||
case memory_order_consume:
|
||||
case memory_order_acquire:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
__sync_synchronize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
inline void
|
||||
platform_fence_before(memory_order)
|
||||
{
|
||||
/* empty, as compare_and_swap is synchronizing already */
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after(memory_order)
|
||||
{
|
||||
/* empty, as compare_and_swap is synchronizing already */
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_before_store(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_relaxed:
|
||||
case memory_order_acquire:
|
||||
case memory_order_consume:
|
||||
break;
|
||||
case memory_order_release:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
__sync_synchronize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after_store(memory_order order)
|
||||
{
|
||||
if (order == memory_order_seq_cst)
|
||||
__sync_synchronize();
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after_load(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_relaxed:
|
||||
case memory_order_release:
|
||||
break;
|
||||
case memory_order_consume:
|
||||
case memory_order_acquire:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
__sync_synchronize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
platform_cmpxchg32_strong(T & expected, T desired, volatile T * ptr)
|
||||
{
|
||||
T found = __sync_val_compare_and_swap(ptr, expected, desired);
|
||||
bool success = (found == expected);
|
||||
expected = found;
|
||||
return success;
|
||||
}
|
||||
|
||||
class atomic_flag {
|
||||
private:
|
||||
atomic_flag(const atomic_flag &) /* = delete */ ;
|
||||
atomic_flag & operator=(const atomic_flag &) /* = delete */ ;
|
||||
uint32_t v_;
|
||||
public:
|
||||
atomic_flag(void) : v_(false) {}
|
||||
|
||||
void
|
||||
clear(memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
atomics::detail::platform_fence_before_store(order);
|
||||
const_cast<volatile uint32_t &>(v_) = 0;
|
||||
atomics::detail::platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
bool
|
||||
test_and_set(memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
atomics::detail::platform_fence_before(order);
|
||||
uint32_t expected = v_;
|
||||
do {
|
||||
if (expected == 1)
|
||||
break;
|
||||
} while (!atomics::detail::platform_cmpxchg32(expected, (uint32_t)1, &v_));
|
||||
atomics::detail::platform_fence_after(order);
|
||||
return expected;
|
||||
}
|
||||
};
|
||||
#define BOOST_ATOMIC_FLAG_LOCK_FREE 2
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
|
||||
#if !defined(BOOST_ATOMIC_FORCE_FALLBACK)
|
||||
|
||||
#define BOOST_ATOMIC_CHAR_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_SHORT_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_INT_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_LONG_LOCK_FREE (sizeof(long) <= 4 ? 2 : 0)
|
||||
#define BOOST_ATOMIC_LLONG_LOCK_FREE (sizeof(long long) <= 4 ? 2 : 0)
|
||||
#define BOOST_ATOMIC_POINTER_LOCK_FREE (sizeof(void *) <= 4 ? 2 : 0)
|
||||
#define BOOST_ATOMIC_BOOL_LOCK_FREE 2
|
||||
|
||||
#include <boost/atomic/detail/cas32strong.hpp>
|
||||
|
||||
#endif /* !defined(BOOST_ATOMIC_FORCE_FALLBACK) */
|
||||
|
||||
#endif
|
2757
cpp/BoostParts/boost/atomic/detail/gcc-ppc.hpp
Normal file
2757
cpp/BoostParts/boost/atomic/detail/gcc-ppc.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1229
cpp/BoostParts/boost/atomic/detail/gcc-sparcv9.hpp
Normal file
1229
cpp/BoostParts/boost/atomic/detail/gcc-sparcv9.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1651
cpp/BoostParts/boost/atomic/detail/gcc-x86.hpp
Normal file
1651
cpp/BoostParts/boost/atomic/detail/gcc-x86.hpp
Normal file
File diff suppressed because it is too large
Load Diff
199
cpp/BoostParts/boost/atomic/detail/generic-cas.hpp
Normal file
199
cpp/BoostParts/boost/atomic/detail/generic-cas.hpp
Normal file
@ -0,0 +1,199 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_GENERIC_CAS_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_GENERIC_CAS_HPP
|
||||
|
||||
// Copyright (c) 2009 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
#include <boost/atomic/detail/builder.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* fallback implementation for various compilation targets;
|
||||
this is *not* efficient, particularly because all operations
|
||||
are fully fenced (full memory barriers before and after
|
||||
each operation) */
|
||||
|
||||
#if defined(__GNUC__)
|
||||
namespace boost { namespace atomics { namespace detail {
|
||||
inline int32_t
|
||||
fenced_compare_exchange_strong_32(volatile int32_t *ptr, int32_t expected, int32_t desired)
|
||||
{
|
||||
return __sync_val_compare_and_swap_4(ptr, expected, desired);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS32 1
|
||||
|
||||
#if defined(__amd64__) || defined(__i686__)
|
||||
inline int64_t
|
||||
fenced_compare_exchange_strong_64(int64_t *ptr, int64_t expected, int64_t desired)
|
||||
{
|
||||
return __sync_val_compare_and_swap_8(ptr, expected, desired);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS64 1
|
||||
#endif
|
||||
}}}
|
||||
|
||||
#elif defined(__ICL) || defined(_MSC_VER)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <Windows.h>
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace atomics { namespace detail {
|
||||
inline int32_t
|
||||
fenced_compare_exchange_strong(int32_t *ptr, int32_t expected, int32_t desired)
|
||||
{
|
||||
return _InterlockedCompareExchange(reinterpret_cast<volatile long*>(ptr), desired, expected);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS32 1
|
||||
#if defined(_WIN64)
|
||||
inline int64_t
|
||||
fenced_compare_exchange_strong(int64_t *ptr, int64_t expected, int64_t desired)
|
||||
{
|
||||
return _InterlockedCompareExchange64(ptr, desired, expected);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS64 1
|
||||
#endif
|
||||
}}}
|
||||
|
||||
#elif (defined(__ICC) || defined(__ECC))
|
||||
namespace boost { namespace atomics { namespace detail {
|
||||
inline int32_t
|
||||
fenced_compare_exchange_strong_32(int32_t *ptr, int32_t expected, int32_t desired)
|
||||
{
|
||||
return _InterlockedCompareExchange((void*)ptr, desired, expected);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS32 1
|
||||
#if defined(__x86_64)
|
||||
inline int64_t
|
||||
fenced_compare_exchange_strong(int64_t *ptr, int64_t expected, int64_t desired)
|
||||
{
|
||||
return cas64<int>(ptr, expected, desired);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS64 1
|
||||
#elif defined(__ECC) //IA-64 version
|
||||
inline int64_t
|
||||
fenced_compare_exchange_strong(int64_t *ptr, int64_t expected, int64_t desired)
|
||||
{
|
||||
return _InterlockedCompareExchange64((void*)ptr, desired, expected);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS64 1
|
||||
#endif
|
||||
}}}
|
||||
|
||||
#elif (defined(__SUNPRO_CC) && defined(__sparc))
|
||||
#include <sys/atomic.h>
|
||||
namespace boost { namespace atomics { namespace detail {
|
||||
inline int32_t
|
||||
fenced_compare_exchange_strong_32(int32_t *ptr, int32_t expected, int32_t desired)
|
||||
{
|
||||
return atomic_cas_32((volatile unsigned int*)ptr, expected, desired);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS32 1
|
||||
|
||||
/* FIXME: check for 64 bit mode */
|
||||
inline int64_t
|
||||
fenced_compare_exchange_strong_64(int64_t *ptr, int64_t expected, int64_t desired)
|
||||
{
|
||||
return atomic_cas_64((volatile unsigned long long*)ptr, expected, desired);
|
||||
}
|
||||
#define BOOST_ATOMIC_HAVE_CAS64 1
|
||||
}}}
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAVE_CAS32
|
||||
template<typename T>
|
||||
class atomic_generic_cas32 {
|
||||
private:
|
||||
typedef atomic_generic_cas32 this_type;
|
||||
public:
|
||||
explicit atomic_generic_cas32(T v) : i((int32_t)v) {}
|
||||
atomic_generic_cas32() {}
|
||||
T load(memory_order order=memory_order_seq_cst) const volatile
|
||||
{
|
||||
T expected=(T)i;
|
||||
do { } while(!const_cast<this_type *>(this)->compare_exchange_weak(expected, expected, order, memory_order_relaxed));
|
||||
return expected;
|
||||
}
|
||||
void store(T v, memory_order order=memory_order_seq_cst) volatile
|
||||
{
|
||||
exchange(v);
|
||||
}
|
||||
bool compare_exchange_strong(
|
||||
T &expected,
|
||||
T desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
T found;
|
||||
found=(T)fenced_compare_exchange_strong_32(&i, (int32_t)expected, (int32_t)desired);
|
||||
bool success=(found==expected);
|
||||
expected=found;
|
||||
return success;
|
||||
}
|
||||
bool compare_exchange_weak(
|
||||
T &expected,
|
||||
T desired,
|
||||
memory_order success_order,
|
||||
memory_order failure_order) volatile
|
||||
{
|
||||
return compare_exchange_strong(expected, desired, success_order, failure_order);
|
||||
}
|
||||
T exchange(T r, memory_order order=memory_order_seq_cst) volatile
|
||||
{
|
||||
T expected=(T)i;
|
||||
do { } while(!compare_exchange_weak(expected, r, order, memory_order_relaxed));
|
||||
return expected;
|
||||
}
|
||||
|
||||
bool is_lock_free(void) const volatile {return true;}
|
||||
typedef T integral_type;
|
||||
private:
|
||||
mutable int32_t i;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class platform_atomic_integral<T, 4> : public build_atomic_from_exchange<atomic_generic_cas32<T> > {
|
||||
public:
|
||||
typedef build_atomic_from_exchange<atomic_generic_cas32<T> > super;
|
||||
explicit platform_atomic_integral(T v) : super(v) {}
|
||||
platform_atomic_integral(void) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class platform_atomic_integral<T, 1>: public build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> {
|
||||
public:
|
||||
typedef build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> super;
|
||||
|
||||
explicit platform_atomic_integral(T v) : super(v) {}
|
||||
platform_atomic_integral(void) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class platform_atomic_integral<T, 2>: public build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> {
|
||||
public:
|
||||
typedef build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> super;
|
||||
|
||||
explicit platform_atomic_integral(T v) : super(v) {}
|
||||
platform_atomic_integral(void) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
206
cpp/BoostParts/boost/atomic/detail/interlocked.hpp
Normal file
206
cpp/BoostParts/boost/atomic/detail/interlocked.hpp
Normal file
@ -0,0 +1,206 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP
|
||||
|
||||
// Copyright (c) 2009 Helge Bahmann
|
||||
// Copyright (c) 2012 Andrey Semashev
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest), exchange, compare)
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) BOOST_INTERLOCKED_EXCHANGE((long*)(dest), newval)
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) BOOST_INTERLOCKED_EXCHANGE_ADD((long*)(dest), addend)
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare)
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) BOOST_INTERLOCKED_EXCHANGE_POINTER(dest, newval)
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_INTERLOCKED_EXCHANGE_ADD((long*)(dest), byte_offset))
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd)
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval))
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
|
||||
#pragma intrinsic(_InterlockedAnd)
|
||||
#pragma intrinsic(_InterlockedOr)
|
||||
#pragma intrinsic(_InterlockedXor)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_AND(dest, arg) _InterlockedAnd((long*)(dest), (long)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_OR(dest, arg) _InterlockedOr((long*)(dest), (long)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_XOR(dest, arg) _InterlockedXor((long*)(dest), (long)(arg))
|
||||
|
||||
#endif // _MSC_VER >= 1400
|
||||
|
||||
#if _MSC_VER >= 1600
|
||||
|
||||
// MSVC 2010 and later provide intrinsics for 8 and 16 bit integers.
|
||||
// Note that for each bit count these macros must be either all defined or all not defined.
|
||||
// Otherwise atomic<> operations will be implemented inconsistently.
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange8)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd8)
|
||||
#pragma intrinsic(_InterlockedExchange8)
|
||||
#pragma intrinsic(_InterlockedAnd8)
|
||||
#pragma intrinsic(_InterlockedOr8)
|
||||
#pragma intrinsic(_InterlockedXor8)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(dest, exchange, compare) _InterlockedCompareExchange8((char*)(dest), (char)(exchange), (char)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(dest, addend) _InterlockedExchangeAdd8((char*)(dest), (char)(addend))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(dest, newval) _InterlockedExchange8((char*)(dest), (char)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_AND8(dest, arg) _InterlockedAnd8((char*)(dest), (char)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_OR8(dest, arg) _InterlockedOr8((char*)(dest), (char)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_XOR8(dest, arg) _InterlockedXor8((char*)(dest), (char)(arg))
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange16)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd16)
|
||||
#pragma intrinsic(_InterlockedExchange16)
|
||||
#pragma intrinsic(_InterlockedAnd16)
|
||||
#pragma intrinsic(_InterlockedOr16)
|
||||
#pragma intrinsic(_InterlockedXor16)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(dest, exchange, compare) _InterlockedCompareExchange16((short*)(dest), (short)(exchange), (short)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(dest, addend) _InterlockedExchangeAdd16((short*)(dest), (short)(addend))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(dest, newval) _InterlockedExchange16((short*)(dest), (short)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_AND16(dest, arg) _InterlockedAnd16((short*)(dest), (short)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_OR16(dest, arg) _InterlockedOr16((short*)(dest), (short)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_XOR16(dest, arg) _InterlockedXor16((short*)(dest), (short)(arg))
|
||||
|
||||
#endif // _MSC_VER >= 1600
|
||||
|
||||
#if defined(_M_AMD64) || defined(_M_IA64)
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchange64)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd64)
|
||||
#pragma intrinsic(_InterlockedExchange64)
|
||||
#pragma intrinsic(_InterlockedAnd64)
|
||||
#pragma intrinsic(_InterlockedOr64)
|
||||
#pragma intrinsic(_InterlockedXor64)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) _InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) _InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) _InterlockedExchange64((__int64*)(dest), (__int64)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_AND64(dest, arg) _InterlockedAnd64((__int64*)(dest), (__int64)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_OR64(dest, arg) _InterlockedOr64((__int64*)(dest), (__int64)(arg))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_XOR64(dest, arg) _InterlockedXor64((__int64*)(dest), (__int64)(arg))
|
||||
|
||||
#pragma intrinsic(_InterlockedCompareExchangePointer)
|
||||
#pragma intrinsic(_InterlockedExchangePointer)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) _InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) _InterlockedExchangePointer((void**)(dest), (void*)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64((long*)(dest), byte_offset))
|
||||
|
||||
#else // defined(_M_AMD64)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)_InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare)))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)_InterlockedExchange((long*)(dest), (long)(newval)))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD((long*)(dest), byte_offset))
|
||||
|
||||
#endif // defined(_M_AMD64)
|
||||
|
||||
#else // defined(_MSC_VER)
|
||||
|
||||
#if defined(BOOST_USE_WINDOWS_H)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) InterlockedExchange((long*)(dest), (long)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) InterlockedExchangeAdd((long*)(dest), (long)(addend))
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) InterlockedExchange64((__int64*)(dest), (__int64)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend))
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) InterlockedExchangePointer((void**)(dest), (void*)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, byte_offset))
|
||||
|
||||
#else // defined(_WIN64)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, byte_offset))
|
||||
|
||||
#endif // defined(_WIN64)
|
||||
|
||||
#else // defined(BOOST_USE_WINDOWS_H)
|
||||
|
||||
#if defined(__MINGW64__)
|
||||
#define BOOST_ATOMIC_INTERLOCKED_IMPORT
|
||||
#else
|
||||
#define BOOST_ATOMIC_INTERLOCKED_IMPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
extern "C" {
|
||||
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedCompareExchange(long volatile*, long, long);
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchange(long volatile*, long);
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchangeAdd(long volatile*, long);
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) boost::atomics::detail::InterlockedExchange((long*)(dest), (long)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) boost::atomics::detail::InterlockedExchangeAdd((long*)(dest), (long)(addend))
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedCompareExchange64(__int64 volatile*, __int64, __int64);
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchange64(__int64 volatile*, __int64);
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchangeAdd64(__int64 volatile*, __int64);
|
||||
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedCompareExchangePointer(void* volatile *, void*, void*);
|
||||
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedExchangePointer(void* volatile *, void*);
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) boost::atomics::detail::InterlockedExchange64((__int64*)(dest), (__int64)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) boost::atomics::detail::InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend))
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) boost::atomics::detail::InterlockedExchangePointer((void**)(dest), (void*)(newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, byte_offset))
|
||||
|
||||
#else // defined(_WIN64)
|
||||
|
||||
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval))
|
||||
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, byte_offset))
|
||||
|
||||
#endif // defined(_WIN64)
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#undef BOOST_ATOMIC_INTERLOCKED_IMPORT
|
||||
|
||||
#endif // defined(BOOST_USE_WINDOWS_H)
|
||||
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
#endif
|
187
cpp/BoostParts/boost/atomic/detail/linux-arm.hpp
Normal file
187
cpp/BoostParts/boost/atomic/detail/linux-arm.hpp
Normal file
@ -0,0 +1,187 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_LINUX_ARM_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_LINUX_ARM_HPP
|
||||
|
||||
// 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)
|
||||
//
|
||||
// Copyright (c) 2009, 2011 Helge Bahmann
|
||||
// Copyright (c) 2009 Phil Endecott
|
||||
// Linux-specific code by Phil Endecott
|
||||
|
||||
// Different ARM processors have different atomic instructions. In particular,
|
||||
// architecture versions before v6 (which are still in widespread use, e.g. the
|
||||
// Intel/Marvell XScale chips like the one in the NSLU2) have only atomic swap.
|
||||
// On Linux the kernel provides some support that lets us abstract away from
|
||||
// these differences: it provides emulated CAS and barrier functions at special
|
||||
// addresses that are guaranteed not to be interrupted by the kernel. Using
|
||||
// this facility is slightly slower than inline assembler would be, but much
|
||||
// faster than a system call.
|
||||
//
|
||||
// While this emulated CAS is "strong" in the sense that it does not fail
|
||||
// "spuriously" (i.e.: it never fails to perform the exchange when the value
|
||||
// found equals the value expected), it does not return the found value on
|
||||
// failure. To satisfy the atomic API, compare_exchange_{weak|strong} must
|
||||
// return the found value on failure, and we have to manually load this value
|
||||
// after the emulated CAS reports failure. This in turn introduces a race
|
||||
// between the CAS failing (due to the "wrong" value being found) and subsequently
|
||||
// loading (which might turn up the "right" value). From an application's
|
||||
// point of view this looks like "spurious failure", and therefore the
|
||||
// emulated CAS is only good enough to provide compare_exchange_weak
|
||||
// semantics.
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
inline void
|
||||
arm_barrier(void)
|
||||
{
|
||||
void (*kernel_dmb)(void) = (void (*)(void)) 0xffff0fa0;
|
||||
kernel_dmb();
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_before(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_release:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
arm_barrier();
|
||||
case memory_order_consume:
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_acquire:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
arm_barrier();
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_before_store(memory_order order)
|
||||
{
|
||||
platform_fence_before(order);
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after_store(memory_order order)
|
||||
{
|
||||
if (order == memory_order_seq_cst)
|
||||
arm_barrier();
|
||||
}
|
||||
|
||||
inline void
|
||||
platform_fence_after_load(memory_order order)
|
||||
{
|
||||
platform_fence_after(order);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
platform_cmpxchg32(T & expected, T desired, volatile T * ptr)
|
||||
{
|
||||
typedef T (*kernel_cmpxchg32_t)(T oldval, T newval, volatile T * ptr);
|
||||
|
||||
if (((kernel_cmpxchg32_t) 0xffff0fc0)(expected, desired, ptr) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
expected = *ptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_THREAD_FENCE 2
|
||||
inline void
|
||||
atomic_thread_fence(memory_order order)
|
||||
{
|
||||
switch(order) {
|
||||
case memory_order_acquire:
|
||||
case memory_order_release:
|
||||
case memory_order_acq_rel:
|
||||
case memory_order_seq_cst:
|
||||
atomics::detail::arm_barrier();
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_ATOMIC_SIGNAL_FENCE 2
|
||||
inline void
|
||||
atomic_signal_fence(memory_order)
|
||||
{
|
||||
__asm__ __volatile__ ("" ::: "memory");
|
||||
}
|
||||
|
||||
class atomic_flag {
|
||||
private:
|
||||
atomic_flag(const atomic_flag &) /* = delete */ ;
|
||||
atomic_flag & operator=(const atomic_flag &) /* = delete */ ;
|
||||
uint32_t v_;
|
||||
public:
|
||||
atomic_flag(void) : v_(false) {}
|
||||
|
||||
void
|
||||
clear(memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
atomics::detail::platform_fence_before_store(order);
|
||||
const_cast<volatile uint32_t &>(v_) = 0;
|
||||
atomics::detail::platform_fence_after_store(order);
|
||||
}
|
||||
|
||||
bool
|
||||
test_and_set(memory_order order = memory_order_seq_cst) volatile
|
||||
{
|
||||
atomics::detail::platform_fence_before(order);
|
||||
uint32_t expected = v_;
|
||||
do {
|
||||
if (expected == 1)
|
||||
break;
|
||||
} while (!atomics::detail::platform_cmpxchg32(expected, (uint32_t)1, &v_));
|
||||
atomics::detail::platform_fence_after(order);
|
||||
return expected;
|
||||
}
|
||||
};
|
||||
#define BOOST_ATOMIC_FLAG_LOCK_FREE 2
|
||||
|
||||
}
|
||||
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
|
||||
#if !defined(BOOST_ATOMIC_FORCE_FALLBACK)
|
||||
|
||||
#define BOOST_ATOMIC_CHAR_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_SHORT_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_INT_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_LONG_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_LLONG_LOCK_FREE 0
|
||||
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
|
||||
#define BOOST_ATOMIC_BOOL_LOCK_FREE 2
|
||||
|
||||
#include <boost/atomic/detail/cas32weak.hpp>
|
||||
|
||||
#endif /* !defined(BOOST_ATOMIC_FORCE_FALLBACK) */
|
||||
|
||||
#endif
|
96
cpp/BoostParts/boost/atomic/detail/lockpool.hpp
Normal file
96
cpp/BoostParts/boost/atomic/detail/lockpool.hpp
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP
|
||||
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#ifndef BOOST_ATOMIC_FLAG_LOCK_FREE
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
#ifndef BOOST_ATOMIC_FLAG_LOCK_FREE
|
||||
|
||||
class lockpool
|
||||
{
|
||||
public:
|
||||
typedef mutex lock_type;
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
lock_type& mtx_;
|
||||
|
||||
scoped_lock(scoped_lock const&) /* = delete */;
|
||||
scoped_lock& operator=(scoped_lock const&) /* = delete */;
|
||||
|
||||
public:
|
||||
explicit
|
||||
scoped_lock(const volatile void * addr) : mtx_(get_lock_for(addr))
|
||||
{
|
||||
mtx_.lock();
|
||||
}
|
||||
~scoped_lock()
|
||||
{
|
||||
mtx_.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
static BOOST_ATOMIC_DECL lock_type& get_lock_for(const volatile void * addr);
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class lockpool
|
||||
{
|
||||
public:
|
||||
typedef atomic_flag lock_type;
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
atomic_flag& flag_;
|
||||
|
||||
scoped_lock(const scoped_lock &) /* = delete */;
|
||||
scoped_lock& operator=(const scoped_lock &) /* = delete */;
|
||||
|
||||
public:
|
||||
explicit
|
||||
scoped_lock(const volatile void * addr) : flag_(get_lock_for(addr))
|
||||
{
|
||||
for (; flag_.test_and_set(memory_order_acquire);)
|
||||
{
|
||||
#if defined(BOOST_ATOMIC_X86_PAUSE)
|
||||
BOOST_ATOMIC_X86_PAUSE();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_lock(void)
|
||||
{
|
||||
flag_.clear(memory_order_release);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
static BOOST_ATOMIC_DECL lock_type& get_lock_for(const volatile void * addr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
62
cpp/BoostParts/boost/atomic/detail/platform.hpp
Normal file
62
cpp/BoostParts/boost/atomic/detail/platform.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_PLATFORM_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_PLATFORM_HPP
|
||||
|
||||
// Copyright (c) 2009 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
// Platform selection file
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
#include <boost/atomic/detail/gcc-x86.hpp>
|
||||
|
||||
#elif 0 && defined(__GNUC__) && defined(__alpha__) /* currently does not work correctly */
|
||||
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
#include <boost/atomic/detail/gcc-alpha.hpp>
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__PPC__))
|
||||
|
||||
#include <boost/atomic/detail/gcc-ppc.hpp>
|
||||
|
||||
// This list of ARM architecture versions comes from Apple's arm/arch.h header.
|
||||
// I don't know how complete it is.
|
||||
#elif defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
|
||||
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_7A__))
|
||||
|
||||
#include <boost/atomic/detail/gcc-armv6plus.hpp>
|
||||
|
||||
#elif defined(__linux__) && defined(__arm__)
|
||||
|
||||
#include <boost/atomic/detail/linux-arm.hpp>
|
||||
|
||||
#elif defined(__GNUC__) && defined(__sparc_v9__)
|
||||
|
||||
#include <boost/atomic/detail/gcc-sparcv9.hpp>
|
||||
|
||||
#elif defined(BOOST_WINDOWS) || defined(_WIN32_CE)
|
||||
|
||||
#include <boost/atomic/detail/windows.hpp>
|
||||
|
||||
#elif 0 && defined(__GNUC__) /* currently does not work correctly */
|
||||
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
#include <boost/atomic/detail/gcc-cas.hpp>
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/atomic/detail/base.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
45
cpp/BoostParts/boost/atomic/detail/type-classification.hpp
Normal file
45
cpp/BoostParts/boost/atomic/detail/type-classification.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef BOOST_ATOMIC_DETAIL_TYPE_CLASSIFICATION_HPP
|
||||
#define BOOST_ATOMIC_DETAIL_TYPE_CLASSIFICATION_HPP
|
||||
|
||||
// Copyright (c) 2011 Helge Bahmann
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
|
||||
#ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
template<typename T, bool IsInt = boost::is_integral<T>::value>
|
||||
struct classify
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct classify<T, true> {typedef int type;};
|
||||
|
||||
template<typename T>
|
||||
struct classify<T*, false> {typedef void* type;};
|
||||
|
||||
template<typename T>
|
||||
struct storage_size_of
|
||||
{
|
||||
enum _
|
||||
{
|
||||
size = sizeof(T),
|
||||
value = (size == 3 ? 4 : (size == 5 || size == 6 || size == 7 ? 8 : size))
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
1441
cpp/BoostParts/boost/atomic/detail/windows.hpp
Normal file
1441
cpp/BoostParts/boost/atomic/detail/windows.hpp
Normal file
File diff suppressed because it is too large
Load Diff
84
cpp/BoostParts/boost/container/detail/algorithms.hpp
Normal file
84
cpp/BoostParts/boost/container/detail/algorithms.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/type_traits/has_trivial_copy.hpp>
|
||||
#include <boost/type_traits/has_trivial_assign.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/iterators.hpp>
|
||||
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template<class It>
|
||||
struct is_default_construct_iterator
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class U, class D>
|
||||
struct is_default_construct_iterator<default_construct_iterator<U, D> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<class It>
|
||||
struct is_emplace_iterator
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class U, class EF, class D>
|
||||
struct is_emplace_iterator<emplace_iterator<U, EF, D> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<class A, class T, class InpIt>
|
||||
inline void construct_in_place(A &a, T* dest, InpIt source)
|
||||
{ boost::container::allocator_traits<A>::construct(a, dest, *source); }
|
||||
//#endif
|
||||
|
||||
template<class A, class T, class U, class D>
|
||||
inline void construct_in_place(A &a, T *dest, default_construct_iterator<U, D>)
|
||||
{
|
||||
boost::container::allocator_traits<A>::construct(a, dest);
|
||||
}
|
||||
|
||||
template<class A, class T, class U, class EF, class D>
|
||||
inline void construct_in_place(A &a, T *dest, emplace_iterator<U, EF, D> ei)
|
||||
{
|
||||
ei.construct_in_place(a, dest);
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
|
||||
|
54
cpp/BoostParts/boost/container/detail/allocation_type.hpp
Normal file
54
cpp/BoostParts/boost/container/detail/allocation_type.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container for documentation.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP
|
||||
#define BOOST_CONTAINER_ALLOCATION_TYPE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
/// @cond
|
||||
enum allocation_type_v
|
||||
{
|
||||
// constants for allocation commands
|
||||
allocate_new_v = 0x01,
|
||||
expand_fwd_v = 0x02,
|
||||
expand_bwd_v = 0x04,
|
||||
// expand_both = expand_fwd | expand_bwd,
|
||||
// expand_or_new = allocate_new | expand_both,
|
||||
shrink_in_place_v = 0x08,
|
||||
nothrow_allocation_v = 0x10,
|
||||
zero_memory_v = 0x20,
|
||||
try_shrink_in_place_v = 0x40
|
||||
};
|
||||
|
||||
typedef int allocation_type;
|
||||
/// @endcond
|
||||
static const allocation_type allocate_new = (allocation_type)allocate_new_v;
|
||||
static const allocation_type expand_fwd = (allocation_type)expand_fwd_v;
|
||||
static const allocation_type expand_bwd = (allocation_type)expand_bwd_v;
|
||||
static const allocation_type shrink_in_place = (allocation_type)shrink_in_place_v;
|
||||
static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in_place_v;
|
||||
static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v;
|
||||
static const allocation_type zero_memory = (allocation_type)zero_memory_v;
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_ALLOCATION_TYPE_HPP
|
@ -0,0 +1,163 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/allocator_traits.hpp> //allocator_traits
|
||||
#include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
|
||||
#include <boost/container/detail/version_type.hpp> //version_type
|
||||
#include <boost/container/detail/allocation_type.hpp> //allocation_type
|
||||
#include <boost/container/detail/mpl.hpp> //integral_constant
|
||||
#include <boost/intrusive/pointer_traits.hpp> //pointer_traits
|
||||
#include <utility> //pair
|
||||
#include <stdexcept> //runtime_error
|
||||
#include <boost/detail/no_exceptions_support.hpp> //BOOST_TRY
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
|
||||
struct allocator_version_traits
|
||||
{
|
||||
typedef ::boost::container::container_detail::integral_constant
|
||||
<unsigned, Version> alloc_version;
|
||||
|
||||
typedef typename Allocator::multiallocation_chain multiallocation_chain;
|
||||
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
|
||||
|
||||
//Node allocation interface
|
||||
static pointer allocate_one(Allocator &a)
|
||||
{ return a.allocate_one(); }
|
||||
|
||||
static void deallocate_one(Allocator &a, const pointer &p)
|
||||
{ a.deallocate_one(p); }
|
||||
|
||||
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
|
||||
{ return a.allocate_individual(n, m); }
|
||||
|
||||
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
|
||||
{ a.deallocate_individual(holder); }
|
||||
|
||||
static std::pair<pointer, bool>
|
||||
allocation_command(Allocator &a, allocation_type command,
|
||||
size_type limit_size, size_type preferred_size,
|
||||
size_type &received_size, const pointer &reuse)
|
||||
{
|
||||
return a.allocation_command
|
||||
(command, limit_size, preferred_size, received_size, reuse);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
struct allocator_version_traits<Allocator, 1>
|
||||
{
|
||||
typedef ::boost::container::container_detail::integral_constant
|
||||
<unsigned, 1> alloc_version;
|
||||
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
|
||||
|
||||
typedef typename boost::intrusive::pointer_traits<pointer>::
|
||||
template rebind_pointer<void>::type void_ptr;
|
||||
typedef container_detail::basic_multiallocation_chain
|
||||
<void_ptr> multialloc_cached_counted;
|
||||
typedef boost::container::container_detail::
|
||||
transform_multiallocation_chain
|
||||
< multialloc_cached_counted, value_type> multiallocation_chain;
|
||||
|
||||
//Node allocation interface
|
||||
static pointer allocate_one(Allocator &a)
|
||||
{ return a.allocate(1); }
|
||||
|
||||
static void deallocate_one(Allocator &a, const pointer &p)
|
||||
{ a.deallocate(p, 1); }
|
||||
|
||||
static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
|
||||
{
|
||||
while(!holder.empty()){
|
||||
a.deallocate(holder.pop_front(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
struct allocate_individual_rollback
|
||||
{
|
||||
allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
|
||||
: mr_a(a), mp_chain(&chain)
|
||||
{}
|
||||
|
||||
~allocate_individual_rollback()
|
||||
{
|
||||
if(mp_chain)
|
||||
allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
mp_chain = 0;
|
||||
}
|
||||
|
||||
Allocator &mr_a;
|
||||
multiallocation_chain * mp_chain;
|
||||
};
|
||||
|
||||
static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
|
||||
{
|
||||
allocate_individual_rollback rollback(a, m);
|
||||
while(n--){
|
||||
m.push_front(a.allocate(1));
|
||||
}
|
||||
rollback.release();
|
||||
}
|
||||
|
||||
static std::pair<pointer, bool>
|
||||
allocation_command(Allocator &a, allocation_type command,
|
||||
size_type, size_type preferred_size,
|
||||
size_type &received_size, const pointer &)
|
||||
{
|
||||
std::pair<pointer, bool> ret(pointer(), false);
|
||||
if(!(command & allocate_new)){
|
||||
if(!(command & nothrow_allocation)){
|
||||
throw std::runtime_error("version 1 allocator without allocate_new flag");
|
||||
}
|
||||
}
|
||||
else{
|
||||
received_size = preferred_size;
|
||||
BOOST_TRY{
|
||||
ret.first = a.allocate(received_size);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
if(!(command & nothrow_allocation)){
|
||||
BOOST_RETHROW
|
||||
}
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)
|
365
cpp/BoostParts/boost/container/detail/destroyers.hpp
Normal file
365
cpp/BoostParts/boost/container/detail/destroyers.hpp
Normal file
@ -0,0 +1,365 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DESTROYERS_HPP
|
||||
#define BOOST_CONTAINER_DESTROYERS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
#include <boost/container/detail/utilities.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
//!A deleter for scoped_ptr that deallocates the memory
|
||||
//!allocated for an object using a STL allocator.
|
||||
template <class A>
|
||||
struct scoped_deallocator
|
||||
{
|
||||
typedef allocator_traits<A> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::pointer pointer;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<A>::value> alloc_version;
|
||||
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
|
||||
|
||||
private:
|
||||
void priv_deallocate(allocator_v1)
|
||||
{ m_alloc.deallocate(m_ptr, 1); }
|
||||
|
||||
void priv_deallocate(allocator_v2)
|
||||
{ m_alloc.deallocate_one(m_ptr); }
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
|
||||
|
||||
public:
|
||||
|
||||
pointer m_ptr;
|
||||
A& m_alloc;
|
||||
|
||||
scoped_deallocator(pointer p, A& a)
|
||||
: m_ptr(p), m_alloc(a)
|
||||
{}
|
||||
|
||||
~scoped_deallocator()
|
||||
{ if (m_ptr)priv_deallocate(alloc_version()); }
|
||||
|
||||
scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
|
||||
: m_ptr(o.m_ptr), m_alloc(o.m_alloc)
|
||||
{ o.release(); }
|
||||
|
||||
pointer get() const
|
||||
{ return m_ptr; }
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct null_scoped_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
null_scoped_deallocator(pointer, Allocator&, size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
|
||||
pointer get() const
|
||||
{ return pointer(); }
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that deallocates the memory
|
||||
//!allocated for an array of objects using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_array_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
scoped_array_deallocator(pointer p, Allocator& a, size_type length)
|
||||
: m_ptr(p), m_alloc(a), m_length(length) {}
|
||||
|
||||
~scoped_array_deallocator()
|
||||
{ if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
private:
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
size_type m_length;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct null_scoped_array_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
null_scoped_array_deallocator(pointer, Allocator&, size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
struct scoped_destroy_deallocator
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<Allocator>::value> alloc_version;
|
||||
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
|
||||
|
||||
scoped_destroy_deallocator(pointer p, Allocator& a)
|
||||
: m_ptr(p), m_alloc(a) {}
|
||||
|
||||
~scoped_destroy_deallocator()
|
||||
{
|
||||
if(m_ptr){
|
||||
AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr));
|
||||
priv_deallocate(m_ptr, alloc_version());
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
private:
|
||||
|
||||
void priv_deallocate(const pointer &p, allocator_v1)
|
||||
{ AllocTraits::deallocate(m_alloc, p, 1); }
|
||||
|
||||
void priv_deallocate(const pointer &p, allocator_v2)
|
||||
{ m_alloc.deallocate_one(p); }
|
||||
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
};
|
||||
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_destructor_n
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
scoped_destructor_n(pointer p, Allocator& a, size_type n)
|
||||
: m_p(p), m_a(a), m_n(n)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ m_p = 0; }
|
||||
|
||||
void increment_size(size_type inc)
|
||||
{ m_n += inc; }
|
||||
|
||||
void increment_size_backwards(size_type inc)
|
||||
{ m_n += inc; m_p -= inc; }
|
||||
|
||||
void shrink_forward(size_type inc)
|
||||
{ m_n -= inc; m_p += inc; }
|
||||
|
||||
~scoped_destructor_n()
|
||||
{
|
||||
if(!m_p) return;
|
||||
value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
|
||||
while(m_n--){
|
||||
AllocTraits::destroy(m_a, raw_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pointer m_p;
|
||||
Allocator & m_a;
|
||||
size_type m_n;
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct null_scoped_destructor_n
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::size_type size_type;
|
||||
|
||||
null_scoped_destructor_n(pointer, Allocator&, size_type)
|
||||
{}
|
||||
|
||||
void increment_size(size_type)
|
||||
{}
|
||||
|
||||
void increment_size_backwards(size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
};
|
||||
|
||||
template<class A>
|
||||
class scoped_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<A> AllocTraits;
|
||||
public:
|
||||
typedef typename A::value_type value_type;
|
||||
scoped_destructor(A &a, value_type *pv)
|
||||
: pv_(pv), a_(a)
|
||||
{}
|
||||
|
||||
~scoped_destructor()
|
||||
{
|
||||
if(pv_){
|
||||
AllocTraits::destroy(a_, pv_);
|
||||
}
|
||||
}
|
||||
|
||||
void release()
|
||||
{ pv_ = 0; }
|
||||
|
||||
private:
|
||||
value_type *pv_;
|
||||
A &a_;
|
||||
};
|
||||
|
||||
|
||||
template<class A>
|
||||
class value_destructor
|
||||
{
|
||||
typedef boost::container::allocator_traits<A> AllocTraits;
|
||||
public:
|
||||
typedef typename A::value_type value_type;
|
||||
value_destructor(A &a, value_type &rv)
|
||||
: rv_(rv), a_(a)
|
||||
{}
|
||||
|
||||
~value_destructor()
|
||||
{
|
||||
AllocTraits::destroy(a_, &rv_);
|
||||
}
|
||||
|
||||
private:
|
||||
value_type &rv_;
|
||||
A &a_;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_destroyer
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<Allocator>::value> alloc_version;
|
||||
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
|
||||
|
||||
private:
|
||||
Allocator & a_;
|
||||
|
||||
private:
|
||||
void priv_deallocate(const pointer &p, allocator_v1)
|
||||
{ AllocTraits::deallocate(a_,p, 1); }
|
||||
|
||||
void priv_deallocate(const pointer &p, allocator_v2)
|
||||
{ a_.deallocate_one(p); }
|
||||
|
||||
public:
|
||||
allocator_destroyer(Allocator &a)
|
||||
: a_(a)
|
||||
{}
|
||||
|
||||
void operator()(const pointer &p)
|
||||
{
|
||||
AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
|
||||
this->priv_deallocate(p, alloc_version());
|
||||
}
|
||||
};
|
||||
|
||||
template <class A>
|
||||
class allocator_destroyer_and_chain_builder
|
||||
{
|
||||
typedef allocator_traits<A> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::value_type value_type;
|
||||
typedef typename A::multiallocation_chain multiallocation_chain;
|
||||
|
||||
A & a_;
|
||||
multiallocation_chain &c_;
|
||||
|
||||
public:
|
||||
allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
|
||||
: a_(a), c_(c)
|
||||
{}
|
||||
|
||||
void operator()(const typename A::pointer &p)
|
||||
{
|
||||
allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
|
||||
c_.push_back(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class A>
|
||||
class allocator_multialloc_chain_node_deallocator
|
||||
{
|
||||
typedef allocator_traits<A> allocator_traits_type;
|
||||
typedef typename allocator_traits_type::value_type value_type;
|
||||
typedef typename A::multiallocation_chain multiallocation_chain;
|
||||
typedef allocator_destroyer_and_chain_builder<A> chain_builder;
|
||||
|
||||
A & a_;
|
||||
multiallocation_chain c_;
|
||||
|
||||
public:
|
||||
allocator_multialloc_chain_node_deallocator(A &a)
|
||||
: a_(a), c_()
|
||||
{}
|
||||
|
||||
chain_builder get_chain_builder()
|
||||
{ return chain_builder(a_, c_); }
|
||||
|
||||
~allocator_multialloc_chain_node_deallocator()
|
||||
{
|
||||
a_.deallocate_individual(c_);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP
|
611
cpp/BoostParts/boost/container/detail/iterators.hpp
Normal file
611
cpp/BoostParts/boost/container/detail/iterators.hpp
Normal file
@ -0,0 +1,611 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2012.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/move/utility.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
#include <boost/container/detail/variadic_templates_tools.hpp>
|
||||
#else
|
||||
#include <boost/container/detail/preprocessor.hpp>
|
||||
#endif
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template <class T, class Difference = std::ptrdiff_t>
|
||||
class constant_iterator
|
||||
: public std::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
|
||||
{
|
||||
typedef constant_iterator<T, Difference> this_type;
|
||||
|
||||
public:
|
||||
explicit constant_iterator(const T &ref, Difference range_size)
|
||||
: m_ptr(&ref), m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
constant_iterator()
|
||||
: m_ptr(0), m_num(0){}
|
||||
|
||||
constant_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
constant_iterator operator++(int)
|
||||
{
|
||||
constant_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
constant_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
constant_iterator operator--(int)
|
||||
{
|
||||
constant_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend Difference operator- (const constant_iterator& i, const constant_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
constant_iterator& operator+=(Difference off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
constant_iterator operator+(Difference off) const
|
||||
{
|
||||
constant_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend constant_iterator operator+(Difference off, const constant_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
constant_iterator& operator-=(Difference off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
constant_iterator operator-(Difference off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
const T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
const T& operator[] (Difference n) const
|
||||
{ return dereference(); }
|
||||
|
||||
const T* operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
private:
|
||||
const T * m_ptr;
|
||||
Difference m_num;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
const T & dereference() const
|
||||
{ return *m_ptr; }
|
||||
|
||||
void advance(Difference n)
|
||||
{ m_num -= n; }
|
||||
|
||||
Difference distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
template <class T, class Difference = std::ptrdiff_t>
|
||||
class default_construct_iterator
|
||||
: public std::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
|
||||
{
|
||||
typedef default_construct_iterator<T, Difference> this_type;
|
||||
|
||||
public:
|
||||
explicit default_construct_iterator(Difference range_size)
|
||||
: m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
default_construct_iterator()
|
||||
: m_num(0){}
|
||||
|
||||
default_construct_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
default_construct_iterator operator++(int)
|
||||
{
|
||||
default_construct_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
default_construct_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
default_construct_iterator operator--(int)
|
||||
{
|
||||
default_construct_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const default_construct_iterator& i, const default_construct_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const default_construct_iterator& i, const default_construct_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const default_construct_iterator& i, const default_construct_iterator& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const default_construct_iterator& i, const default_construct_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const default_construct_iterator& i, const default_construct_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const default_construct_iterator& i, const default_construct_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend Difference operator- (const default_construct_iterator& i, const default_construct_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
default_construct_iterator& operator+=(Difference off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
default_construct_iterator operator+(Difference off) const
|
||||
{
|
||||
default_construct_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend default_construct_iterator operator+(Difference off, const default_construct_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
default_construct_iterator& operator-=(Difference off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
default_construct_iterator operator-(Difference off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
//This pseudo-iterator's dereference operations have no sense since value is not
|
||||
//constructed until ::boost::container::construct_in_place is called.
|
||||
//So comment them to catch bad uses
|
||||
//const T& operator*() const;
|
||||
//const T& operator[](difference_type) const;
|
||||
//const T* operator->() const;
|
||||
|
||||
private:
|
||||
Difference m_num;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
void advance(Difference n)
|
||||
{ m_num -= n; }
|
||||
|
||||
Difference distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
template <class T, class Difference = std::ptrdiff_t>
|
||||
class repeat_iterator
|
||||
: public std::iterator
|
||||
<std::random_access_iterator_tag, T, Difference>
|
||||
{
|
||||
typedef repeat_iterator<T, Difference> this_type;
|
||||
public:
|
||||
explicit repeat_iterator(T &ref, Difference range_size)
|
||||
: m_ptr(&ref), m_num(range_size){}
|
||||
|
||||
//Constructors
|
||||
repeat_iterator()
|
||||
: m_ptr(0), m_num(0){}
|
||||
|
||||
this_type& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
this_type operator++(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
this_type& operator--()
|
||||
{ increment(); return *this; }
|
||||
|
||||
this_type operator--(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const this_type& i, const this_type& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const this_type& i, const this_type& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const this_type& i, const this_type& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const this_type& i, const this_type& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const this_type& i, const this_type& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const this_type& i, const this_type& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend Difference operator- (const this_type& i, const this_type& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
this_type& operator+=(Difference off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
this_type operator+(Difference off) const
|
||||
{
|
||||
this_type other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend this_type operator+(Difference off, const this_type& right)
|
||||
{ return right + off; }
|
||||
|
||||
this_type& operator-=(Difference off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
this_type operator-(Difference off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
T& operator[] (Difference n) const
|
||||
{ return dereference(); }
|
||||
|
||||
T *operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
private:
|
||||
T * m_ptr;
|
||||
Difference m_num;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
T & dereference() const
|
||||
{ return *m_ptr; }
|
||||
|
||||
void advance(Difference n)
|
||||
{ m_num -= n; }
|
||||
|
||||
Difference distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
template <class T, class EmplaceFunctor, class Difference /*= std::ptrdiff_t*/>
|
||||
class emplace_iterator
|
||||
: public std::iterator
|
||||
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
|
||||
{
|
||||
typedef emplace_iterator this_type;
|
||||
|
||||
public:
|
||||
typedef Difference difference_type;
|
||||
explicit emplace_iterator(EmplaceFunctor&e)
|
||||
: m_num(1), m_pe(&e){}
|
||||
|
||||
emplace_iterator()
|
||||
: m_num(0), m_pe(0){}
|
||||
|
||||
this_type& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
this_type operator++(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
this_type& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
this_type operator--(int)
|
||||
{
|
||||
this_type result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const this_type& i, const this_type& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const this_type& i, const this_type& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const this_type& i, const this_type& i2)
|
||||
{ return i.less(i2); }
|
||||
|
||||
friend bool operator> (const this_type& i, const this_type& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const this_type& i, const this_type& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const this_type& i, const this_type& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend difference_type operator- (const this_type& i, const this_type& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
this_type& operator+=(difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
this_type operator+(difference_type off) const
|
||||
{
|
||||
this_type other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend this_type operator+(difference_type off, const this_type& right)
|
||||
{ return right + off; }
|
||||
|
||||
this_type& operator-=(difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
this_type operator-(difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
//This pseudo-iterator's dereference operations have no sense since value is not
|
||||
//constructed until ::boost::container::construct_in_place is called.
|
||||
//So comment them to catch bad uses
|
||||
//const T& operator*() const;
|
||||
//const T& operator[](difference_type) const;
|
||||
//const T* operator->() const;
|
||||
|
||||
template<class A>
|
||||
void construct_in_place(A &a, T* ptr)
|
||||
{ (*m_pe)(a, ptr); }
|
||||
|
||||
private:
|
||||
difference_type m_num;
|
||||
EmplaceFunctor * m_pe;
|
||||
|
||||
void increment()
|
||||
{ --m_num; }
|
||||
|
||||
void decrement()
|
||||
{ ++m_num; }
|
||||
|
||||
bool equal(const this_type &other) const
|
||||
{ return m_num == other.m_num; }
|
||||
|
||||
bool less(const this_type &other) const
|
||||
{ return other.m_num < m_num; }
|
||||
|
||||
const T & dereference() const
|
||||
{
|
||||
static T dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
void advance(difference_type n)
|
||||
{ m_num -= n; }
|
||||
|
||||
difference_type distance_to(const this_type &other)const
|
||||
{ return difference_type(m_num - other.m_num); }
|
||||
};
|
||||
|
||||
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
|
||||
template<class ...Args>
|
||||
struct emplace_functor
|
||||
{
|
||||
typedef typename container_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
emplace_functor(Args&&... args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
template<class A, class T>
|
||||
void operator()(A &a, T *ptr)
|
||||
{ emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
|
||||
|
||||
template<class A, class T, int ...IdxPack>
|
||||
void inplace_impl(A &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
|
||||
{
|
||||
allocator_traits<A>::construct
|
||||
(a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
|
||||
}
|
||||
|
||||
container_detail::tuple<Args&...> args_;
|
||||
};
|
||||
|
||||
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
BOOST_PP_EXPR_IF(n, template <) \
|
||||
BOOST_PP_ENUM_PARAMS(n, class P) \
|
||||
BOOST_PP_EXPR_IF(n, >) \
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
|
||||
{ \
|
||||
BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
|
||||
( BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
|
||||
BOOST_PP_EXPR_IF(n, :) BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_INIT, _){} \
|
||||
\
|
||||
template<class A, class T> \
|
||||
void operator()(A &a, T *ptr) \
|
||||
{ \
|
||||
allocator_traits<A>::construct \
|
||||
(a, ptr BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) ); \
|
||||
} \
|
||||
BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
|
||||
}; \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
#endif
|
||||
|
||||
namespace container_detail {
|
||||
|
||||
template<class T>
|
||||
struct has_iterator_category
|
||||
{
|
||||
template <typename X>
|
||||
static char test(int, typename X::iterator_category*);
|
||||
|
||||
template <typename X>
|
||||
static int test(int, ...);
|
||||
|
||||
static const bool value = (1 == sizeof(test<T>(0, 0)));
|
||||
};
|
||||
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_input_iterator
|
||||
{
|
||||
static const bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_input_iterator<T, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_forward_iterator
|
||||
{
|
||||
static const bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_forward_iterator<T, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T, bool = has_iterator_category<T>::value >
|
||||
struct is_bidirectional_iterator
|
||||
{
|
||||
static const bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_bidirectional_iterator<T, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T, class IIterator>
|
||||
struct iiterator_types
|
||||
{
|
||||
typedef typename std::iterator_traits<IIterator>::pointer it_pointer;
|
||||
typedef typename std::iterator_traits<IIterator>::difference_type difference_type;
|
||||
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
|
||||
template rebind_pointer<T>::type pointer;
|
||||
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
|
||||
template rebind_pointer<const T>::type const_pointer;
|
||||
typedef typename ::boost::intrusive::
|
||||
pointer_traits<pointer>::reference reference;
|
||||
typedef typename ::boost::intrusive::
|
||||
pointer_traits<const_pointer>::reference const_reference;
|
||||
};
|
||||
|
||||
|
||||
} //namespace container_detail {
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
|
286
cpp/BoostParts/boost/container/detail/multiallocation_chain.hpp
Normal file
286
cpp/BoostParts/boost/container/detail/multiallocation_chain.hpp
Normal file
@ -0,0 +1,286 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/detail/utilities.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/transform_iterator.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/move/utility.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class VoidPointer>
|
||||
class basic_multiallocation_chain
|
||||
{
|
||||
private:
|
||||
typedef bi::slist_base_hook<bi::void_pointer<VoidPointer>
|
||||
,bi::link_mode<bi::normal_link>
|
||||
> node;
|
||||
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<VoidPointer>::template rebind_pointer<char>::type char_ptr;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<char_ptr>::difference_type difference_type;
|
||||
|
||||
typedef bi::slist< node
|
||||
, bi::linear<true>
|
||||
, bi::cache_last<true>
|
||||
, bi::size_type<typename boost::make_unsigned<difference_type>::type>
|
||||
> slist_impl_t;
|
||||
slist_impl_t slist_impl_;
|
||||
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<VoidPointer>::template rebind_pointer<node>::type node_ptr;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<node_ptr> node_ptr_traits;
|
||||
|
||||
static node & to_node(const VoidPointer &p)
|
||||
{ return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
|
||||
|
||||
static VoidPointer from_node(node &n)
|
||||
{ return node_ptr_traits::pointer_to(n); }
|
||||
|
||||
static node_ptr to_node_ptr(const VoidPointer &p)
|
||||
{ return node_ptr_traits::static_cast_from(p); }
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
|
||||
|
||||
public:
|
||||
|
||||
typedef VoidPointer void_pointer;
|
||||
typedef typename slist_impl_t::iterator iterator;
|
||||
typedef typename slist_impl_t::size_type size_type;
|
||||
|
||||
basic_multiallocation_chain()
|
||||
: slist_impl_()
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
|
||||
: slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
|
||||
: slist_impl_(::boost::move(other.slist_impl_))
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
|
||||
{
|
||||
slist_impl_ = ::boost::move(other.slist_impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{ return slist_impl_.empty(); }
|
||||
|
||||
size_type size() const
|
||||
{ return slist_impl_.size(); }
|
||||
|
||||
iterator before_begin()
|
||||
{ return slist_impl_.before_begin(); }
|
||||
|
||||
iterator begin()
|
||||
{ return slist_impl_.begin(); }
|
||||
|
||||
iterator end()
|
||||
{ return slist_impl_.end(); }
|
||||
|
||||
iterator last()
|
||||
{ return slist_impl_.last(); }
|
||||
|
||||
void clear()
|
||||
{ slist_impl_.clear(); }
|
||||
|
||||
iterator insert_after(iterator it, void_pointer m)
|
||||
{ return slist_impl_.insert_after(it, to_node(m)); }
|
||||
|
||||
void push_front(const void_pointer &m)
|
||||
{ return slist_impl_.push_front(to_node(m)); }
|
||||
|
||||
void push_back(const void_pointer &m)
|
||||
{ return slist_impl_.push_back(to_node(m)); }
|
||||
|
||||
void_pointer pop_front()
|
||||
{
|
||||
node & n = slist_impl_.front();
|
||||
void_pointer ret = from_node(n);
|
||||
slist_impl_.pop_front();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
|
||||
{ slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
|
||||
|
||||
void splice_after(iterator after_this, basic_multiallocation_chain &x)
|
||||
{ slist_impl_.splice_after(after_this, x.slist_impl_); }
|
||||
|
||||
void erase_after(iterator before_b, iterator e, size_type n)
|
||||
{ slist_impl_.erase_after(before_b, e, n); }
|
||||
|
||||
void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
|
||||
{
|
||||
typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
|
||||
char_ptr elem = char_pointer_traits::static_cast_from(b);
|
||||
if(num_units){
|
||||
char_ptr prev_elem = elem;
|
||||
elem += unit_bytes;
|
||||
for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){
|
||||
::new (container_detail::to_raw_pointer(prev_elem)) void_pointer(elem);
|
||||
prev_elem = elem;
|
||||
}
|
||||
slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
|
||||
{ slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
|
||||
|
||||
void swap(basic_multiallocation_chain &x)
|
||||
{ slist_impl_.swap(x.slist_impl_); }
|
||||
|
||||
static iterator iterator_to(const void_pointer &p)
|
||||
{ return slist_impl_t::s_iterator_to(to_node(p)); }
|
||||
|
||||
std::pair<void_pointer, void_pointer> extract_data()
|
||||
{
|
||||
std::pair<void_pointer, void_pointer> ret
|
||||
(slist_impl_.begin().operator->()
|
||||
,slist_impl_.last().operator->());
|
||||
slist_impl_.clear();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct cast_functor
|
||||
{
|
||||
typedef typename container_detail::add_reference<T>::type result_type;
|
||||
template<class U>
|
||||
result_type operator()(U &ptr) const
|
||||
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
|
||||
};
|
||||
|
||||
template<class MultiallocationChain, class T>
|
||||
class transform_multiallocation_chain
|
||||
: public MultiallocationChain
|
||||
{
|
||||
private:
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
|
||||
//transform_multiallocation_chain(const transform_multiallocation_chain &);
|
||||
//transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
|
||||
|
||||
typedef typename MultiallocationChain::void_pointer void_pointer;
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<void_pointer> void_pointer_traits;
|
||||
typedef typename void_pointer_traits::template
|
||||
rebind_pointer<T>::type pointer;
|
||||
typedef typename boost::intrusive::pointer_traits
|
||||
<pointer> pointer_traits;
|
||||
|
||||
static pointer cast(const void_pointer &p)
|
||||
{ return pointer_traits::static_cast_from(p); }
|
||||
|
||||
public:
|
||||
typedef transform_iterator
|
||||
< typename MultiallocationChain::iterator
|
||||
, container_detail::cast_functor <T> > iterator;
|
||||
typedef typename MultiallocationChain::size_type size_type;
|
||||
|
||||
transform_multiallocation_chain()
|
||||
: MultiallocationChain()
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
|
||||
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
|
||||
: MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
|
||||
{
|
||||
return static_cast<MultiallocationChain&>
|
||||
(this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
|
||||
}
|
||||
/*
|
||||
void push_front(const pointer &mem)
|
||||
{ holder_.push_front(mem); }
|
||||
|
||||
void push_back(const pointer &mem)
|
||||
{ return holder_.push_back(mem); }
|
||||
|
||||
void swap(transform_multiallocation_chain &other_chain)
|
||||
{ holder_.swap(other_chain.holder_); }
|
||||
|
||||
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
|
||||
{ holder_.splice_after(after_this.base(), x.holder_, before_b.base(), before_e.base(), n); }
|
||||
|
||||
void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
|
||||
{ holder_.incorporate_after(after_this.base(), b, before_e, n); }
|
||||
*/
|
||||
pointer pop_front()
|
||||
{ return cast(this->MultiallocationChain::pop_front()); }
|
||||
/*
|
||||
bool empty() const
|
||||
{ return holder_.empty(); }
|
||||
|
||||
iterator before_begin()
|
||||
{ return iterator(holder_.before_begin()); }
|
||||
|
||||
iterator begin()
|
||||
{ return iterator(holder_.begin()); }
|
||||
|
||||
iterator end()
|
||||
{ return iterator(holder_.end()); }
|
||||
|
||||
iterator last()
|
||||
{ return iterator(holder_.last()); }
|
||||
|
||||
size_type size() const
|
||||
{ return holder_.size(); }
|
||||
|
||||
void clear()
|
||||
{ holder_.clear(); }
|
||||
*/
|
||||
iterator insert_after(iterator it, pointer m)
|
||||
{ return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
|
||||
|
||||
static iterator iterator_to(const pointer &p)
|
||||
{ return iterator(MultiallocationChain::iterator_to(p)); }
|
||||
|
||||
std::pair<pointer, pointer> extract_data()
|
||||
{
|
||||
std::pair<void_pointer, void_pointer> data(this->MultiallocationChain::extract_data());
|
||||
return std::pair<pointer, pointer>(cast(data.first), cast(data.second));
|
||||
}
|
||||
/*
|
||||
MultiallocationChain &extract_multiallocation_chain()
|
||||
{ return holder_; }*/
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
// namespace container_detail {
|
||||
// namespace container {
|
||||
// namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
384
cpp/BoostParts/boost/container/detail/node_alloc_holder.hpp
Normal file
384
cpp/BoostParts/boost/container/detail/node_alloc_holder.hpp
Normal file
@ -0,0 +1,384 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
|
||||
#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/move/utility.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/utilities.hpp>
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/destroyers.hpp>
|
||||
#include <boost/container/detail/allocator_version_traits.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
|
||||
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
#include <boost/container/detail/preprocessor.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/container/detail/algorithms.hpp>
|
||||
#include <new>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class ValueCompare, class Node>
|
||||
struct node_compare
|
||||
: private ValueCompare
|
||||
{
|
||||
typedef typename ValueCompare::key_type key_type;
|
||||
typedef typename ValueCompare::value_type value_type;
|
||||
typedef typename ValueCompare::key_of_value key_of_value;
|
||||
|
||||
node_compare(const ValueCompare &pred)
|
||||
: ValueCompare(pred)
|
||||
{}
|
||||
|
||||
ValueCompare &value_comp()
|
||||
{ return static_cast<ValueCompare &>(*this); }
|
||||
|
||||
ValueCompare &value_comp() const
|
||||
{ return static_cast<const ValueCompare &>(*this); }
|
||||
|
||||
bool operator()(const Node &a, const Node &b) const
|
||||
{ return ValueCompare::operator()(a.get_data(), b.get_data()); }
|
||||
};
|
||||
|
||||
template<class A, class ICont, class Pred = container_detail::nat>
|
||||
struct node_alloc_holder
|
||||
{
|
||||
typedef allocator_traits<A> allocator_traits_type;
|
||||
typedef node_alloc_holder<A, ICont> self_t;
|
||||
typedef typename allocator_traits_type::value_type value_type;
|
||||
typedef typename ICont::value_type Node;
|
||||
typedef typename allocator_traits_type::template
|
||||
portable_rebind_alloc<Node>::type NodeAlloc;
|
||||
typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
|
||||
typedef A ValAlloc;
|
||||
typedef typename node_allocator_traits_type::pointer NodePtr;
|
||||
typedef container_detail::scoped_deallocator<NodeAlloc> Deallocator;
|
||||
typedef typename node_allocator_traits_type::size_type size_type;
|
||||
typedef typename node_allocator_traits_type::difference_type difference_type;
|
||||
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
|
||||
typedef container_detail::integral_constant<unsigned,
|
||||
boost::container::container_detail::
|
||||
version<NodeAlloc>::value> alloc_version;
|
||||
typedef typename ICont::iterator icont_iterator;
|
||||
typedef typename ICont::const_iterator icont_citerator;
|
||||
typedef allocator_destroyer<NodeAlloc> Destroyer;
|
||||
typedef allocator_traits<NodeAlloc> NodeAllocTraits;
|
||||
typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
|
||||
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
|
||||
|
||||
public:
|
||||
|
||||
//Constructors for sequence containers
|
||||
node_alloc_holder()
|
||||
: members_()
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const ValAlloc &a)
|
||||
: members_(a)
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const node_alloc_holder &x)
|
||||
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
|
||||
: members_(boost::move(x.node_alloc()))
|
||||
{ this->icont().swap(x.icont()); }
|
||||
|
||||
//Constructors for associative containers
|
||||
explicit node_alloc_holder(const ValAlloc &a, const Pred &c)
|
||||
: members_(a, c)
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const node_alloc_holder &x, const Pred &c)
|
||||
: members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
|
||||
{}
|
||||
|
||||
explicit node_alloc_holder(const Pred &c)
|
||||
: members_(c)
|
||||
{}
|
||||
|
||||
//helpers for move assignments
|
||||
explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const Pred &c)
|
||||
: members_(boost::move(x.node_alloc()), c)
|
||||
{ this->icont().swap(x.icont()); }
|
||||
|
||||
void copy_assign_alloc(const node_alloc_holder &x)
|
||||
{
|
||||
container_detail::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
|
||||
container_detail::assign_alloc( static_cast<NodeAlloc &>(this->members_)
|
||||
, static_cast<const NodeAlloc &>(x.members_), flag);
|
||||
}
|
||||
|
||||
void move_assign_alloc( node_alloc_holder &x)
|
||||
{
|
||||
container_detail::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
|
||||
container_detail::move_alloc( static_cast<NodeAlloc &>(this->members_)
|
||||
, static_cast<NodeAlloc &>(x.members_), flag);
|
||||
}
|
||||
|
||||
~node_alloc_holder()
|
||||
{ this->clear(alloc_version()); }
|
||||
|
||||
size_type max_size() const
|
||||
{ return allocator_traits_type::max_size(this->node_alloc()); }
|
||||
|
||||
NodePtr allocate_one()
|
||||
{ return AllocVersionTraits::allocate_one(this->node_alloc()); }
|
||||
|
||||
void deallocate_one(const NodePtr &p)
|
||||
{ AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
|
||||
|
||||
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
|
||||
template<class ...Args>
|
||||
NodePtr create_node(Args &&...args)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
allocator_traits<NodeAlloc>::construct
|
||||
( this->node_alloc()
|
||||
, container_detail::addressof(p->m_data), boost::forward<Args>(args)...);
|
||||
node_deallocator.release();
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
|
||||
return (p);
|
||||
}
|
||||
|
||||
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
\
|
||||
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
|
||||
NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
|
||||
{ \
|
||||
NodePtr p = this->allocate_one(); \
|
||||
Deallocator node_deallocator(p, this->node_alloc()); \
|
||||
allocator_traits<NodeAlloc>::construct \
|
||||
(this->node_alloc(), container_detail::addressof(p->m_data) \
|
||||
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
|
||||
node_deallocator.release(); \
|
||||
typedef typename Node::hook_type hook_type; \
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type; \
|
||||
return (p); \
|
||||
} \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
|
||||
|
||||
template<class It>
|
||||
NodePtr create_node_from_it(const It &it)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it);
|
||||
node_deallocator.release();
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
|
||||
return (p);
|
||||
}
|
||||
|
||||
void destroy_node(const NodePtr &nodep)
|
||||
{
|
||||
allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep));
|
||||
this->deallocate_one(nodep);
|
||||
}
|
||||
|
||||
void swap(node_alloc_holder &x)
|
||||
{
|
||||
this->icont().swap(x.icont());
|
||||
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
|
||||
container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
|
||||
}
|
||||
|
||||
template<class FwdIterator, class Inserter>
|
||||
void allocate_many_and_construct
|
||||
(FwdIterator beg, difference_type n, Inserter inserter)
|
||||
{
|
||||
/*
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
::boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), it);
|
||||
node_deallocator.release();
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
|
||||
return (p);
|
||||
*/
|
||||
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
|
||||
|
||||
//Try to allocate memory in a single block
|
||||
typedef typename multiallocation_chain::iterator multialloc_iterator;
|
||||
multiallocation_chain mem;
|
||||
this->node_alloc().allocate_individual(n, mem);
|
||||
multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
|
||||
mem.clear();
|
||||
Node *p = 0;
|
||||
NodeAlloc &nalloc = this->node_alloc();
|
||||
BOOST_TRY{
|
||||
while(n--){
|
||||
p = container_detail::to_raw_pointer(&*itbeg);
|
||||
++itbeg;
|
||||
//This can throw
|
||||
Deallocator node_deallocator(p, nalloc);
|
||||
boost::container::construct_in_place(nalloc, container_detail::addressof(p->m_data), beg);
|
||||
++beg;
|
||||
node_deallocator.release();
|
||||
//This does not throw
|
||||
typedef typename Node::hook_type hook_type;
|
||||
::new(static_cast<hook_type*>(p)) hook_type;
|
||||
//This can throw in some containers (predicate might throw)
|
||||
inserter(*p);
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
|
||||
this->node_alloc().deallocate_individual(mem);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
void clear(allocator_v1)
|
||||
{ this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
|
||||
|
||||
void clear(allocator_v2)
|
||||
{
|
||||
typename NodeAlloc::multiallocation_chain chain;
|
||||
allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
|
||||
this->icont().clear_and_dispose(builder);
|
||||
//BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
|
||||
if(!chain.empty())
|
||||
this->node_alloc().deallocate_individual(chain);
|
||||
}
|
||||
|
||||
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v1)
|
||||
{ return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
|
||||
|
||||
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2)
|
||||
{
|
||||
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
|
||||
NodeAlloc & nalloc = this->node_alloc();
|
||||
multiallocation_chain chain;
|
||||
allocator_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
|
||||
icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
|
||||
nalloc.deallocate_individual(chain);
|
||||
return ret_it;
|
||||
}
|
||||
|
||||
template<class Key, class Comparator>
|
||||
size_type erase_key(const Key& k, const Comparator &comp, allocator_v1)
|
||||
{ return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); }
|
||||
|
||||
template<class Key, class Comparator>
|
||||
size_type erase_key(const Key& k, const Comparator &comp, allocator_v2)
|
||||
{
|
||||
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
|
||||
return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder());
|
||||
}
|
||||
|
||||
protected:
|
||||
struct cloner
|
||||
{
|
||||
cloner(node_alloc_holder &holder)
|
||||
: m_holder(holder)
|
||||
{}
|
||||
|
||||
NodePtr operator()(const Node &other) const
|
||||
{ return m_holder.create_node(other.get_data()); }
|
||||
|
||||
node_alloc_holder &m_holder;
|
||||
};
|
||||
|
||||
struct members_holder
|
||||
: public NodeAlloc
|
||||
{
|
||||
private:
|
||||
members_holder(const members_holder&);
|
||||
members_holder & operator=(const members_holder&);
|
||||
|
||||
public:
|
||||
members_holder()
|
||||
: NodeAlloc(), m_icont()
|
||||
{}
|
||||
|
||||
template<class ConvertibleToAlloc>
|
||||
explicit members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc)
|
||||
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
|
||||
, m_icont()
|
||||
{}
|
||||
|
||||
template<class ConvertibleToAlloc>
|
||||
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const Pred &c)
|
||||
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
|
||||
, m_icont(typename ICont::value_compare(c))
|
||||
{}
|
||||
|
||||
explicit members_holder(const Pred &c)
|
||||
: NodeAlloc()
|
||||
, m_icont(typename ICont::value_compare(c))
|
||||
{}
|
||||
|
||||
//The intrusive container
|
||||
ICont m_icont;
|
||||
};
|
||||
|
||||
ICont &non_const_icont() const
|
||||
{ return const_cast<ICont&>(this->members_.m_icont); }
|
||||
|
||||
ICont &icont()
|
||||
{ return this->members_.m_icont; }
|
||||
|
||||
const ICont &icont() const
|
||||
{ return this->members_.m_icont; }
|
||||
|
||||
NodeAlloc &node_alloc()
|
||||
{ return static_cast<NodeAlloc &>(this->members_); }
|
||||
|
||||
const NodeAlloc &node_alloc() const
|
||||
{ return static_cast<const NodeAlloc &>(this->members_); }
|
||||
|
||||
members_holder members_;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
|
176
cpp/BoostParts/boost/container/detail/transform_iterator.hpp
Normal file
176
cpp/BoostParts/boost/container/detail/transform_iterator.hpp
Normal file
@ -0,0 +1,176 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2012.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// 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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template <class PseudoReference>
|
||||
struct operator_arrow_proxy
|
||||
{
|
||||
operator_arrow_proxy(const PseudoReference &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
PseudoReference* operator->() const { return &m_value; }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
mutable PseudoReference m_value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct operator_arrow_proxy<T&>
|
||||
{
|
||||
operator_arrow_proxy(T &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
T* operator->() const { return const_cast<T*>(&m_value); }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
T &m_value;
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunction>
|
||||
class transform_iterator
|
||||
: public UnaryFunction
|
||||
, public std::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, typename container_detail::remove_reference<typename UnaryFunction::result_type>::type
|
||||
, typename Iterator::difference_type
|
||||
, operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
, typename UnaryFunction::result_type>
|
||||
{
|
||||
public:
|
||||
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
|
||||
: UnaryFunction(f), m_it(it)
|
||||
{}
|
||||
|
||||
explicit transform_iterator()
|
||||
: UnaryFunction(), m_it()
|
||||
{}
|
||||
|
||||
//Constructors
|
||||
transform_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
transform_iterator operator++(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
/*
|
||||
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
*/
|
||||
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
transform_iterator& operator+=(typename Iterator::difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
transform_iterator operator+(typename Iterator::difference_type off) const
|
||||
{
|
||||
transform_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
transform_iterator& operator-=(typename Iterator::difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
transform_iterator operator-(typename Iterator::difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
typename UnaryFunction::result_type operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
operator->() const
|
||||
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
|
||||
|
||||
Iterator & base()
|
||||
{ return m_it; }
|
||||
|
||||
const Iterator & base() const
|
||||
{ return m_it; }
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
|
||||
void increment()
|
||||
{ ++m_it; }
|
||||
|
||||
void decrement()
|
||||
{ --m_it; }
|
||||
|
||||
bool equal(const transform_iterator &other) const
|
||||
{ return m_it == other.m_it; }
|
||||
|
||||
bool less(const transform_iterator &other) const
|
||||
{ return other.m_it < m_it; }
|
||||
|
||||
typename UnaryFunction::result_type dereference() const
|
||||
{ return UnaryFunction::operator()(*m_it); }
|
||||
|
||||
void advance(typename Iterator::difference_type n)
|
||||
{ std::advance(m_it, n); }
|
||||
|
||||
typename Iterator::difference_type distance_to(const transform_iterator &other)const
|
||||
{ return std::distance(other.m_it, m_it); }
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunc>
|
||||
transform_iterator<Iterator, UnaryFunc>
|
||||
make_transform_iterator(Iterator it, UnaryFunc fun)
|
||||
{
|
||||
return transform_iterator<Iterator, UnaryFunc>(it, fun);
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
|
1134
cpp/BoostParts/boost/container/detail/tree.hpp
Normal file
1134
cpp/BoostParts/boost/container/detail/tree.hpp
Normal file
File diff suppressed because it is too large
Load Diff
45
cpp/BoostParts/boost/container/detail/value_init.hpp
Normal file
45
cpp/BoostParts/boost/container/detail/value_init.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<class T>
|
||||
struct value_init
|
||||
{
|
||||
value_init()
|
||||
: m_t()
|
||||
{}
|
||||
|
||||
operator T &() { return m_t; }
|
||||
|
||||
T m_t;
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
|
@ -0,0 +1,153 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <cstddef> //std::size_t
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
template<typename... Values>
|
||||
class tuple;
|
||||
|
||||
template<> class tuple<>
|
||||
{};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
class tuple<Head, Tail...>
|
||||
: private tuple<Tail...>
|
||||
{
|
||||
typedef tuple<Tail...> inherited;
|
||||
|
||||
public:
|
||||
tuple() { }
|
||||
|
||||
// implicit copy-constructor is okay
|
||||
// Construct tuple from separate arguments.
|
||||
tuple(typename add_const_reference<Head>::type v,
|
||||
typename add_const_reference<Tail>::type... vtail)
|
||||
: inherited(vtail...), m_head(v)
|
||||
{}
|
||||
|
||||
// Construct tuple from another tuple.
|
||||
template<typename... VValues>
|
||||
tuple(const tuple<VValues...>& other)
|
||||
: m_head(other.head()), inherited(other.tail())
|
||||
{}
|
||||
|
||||
template<typename... VValues>
|
||||
tuple& operator=(const tuple<VValues...>& other)
|
||||
{
|
||||
m_head = other.head();
|
||||
tail() = other.tail();
|
||||
return this;
|
||||
}
|
||||
|
||||
typename add_reference<Head>::type head() { return m_head; }
|
||||
typename add_reference<const Head>::type head() const { return m_head; }
|
||||
|
||||
inherited& tail() { return *this; }
|
||||
const inherited& tail() const { return *this; }
|
||||
|
||||
protected:
|
||||
Head m_head;
|
||||
};
|
||||
|
||||
|
||||
template<typename... Values>
|
||||
tuple<Values&&...> tie_forward(Values&&... values)
|
||||
{ return tuple<Values&&...>(values...); }
|
||||
|
||||
template<int I, typename Tuple>
|
||||
struct tuple_element;
|
||||
|
||||
template<int I, typename Head, typename... Tail>
|
||||
struct tuple_element<I, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
|
||||
};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
struct tuple_element<0, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef Head type;
|
||||
};
|
||||
|
||||
template<int I, typename Tuple>
|
||||
class get_impl;
|
||||
|
||||
template<int I, typename Head, typename... Values>
|
||||
class get_impl<I, tuple<Head, Values...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
|
||||
typedef get_impl<I-1, tuple<Values...> > Next;
|
||||
|
||||
public:
|
||||
typedef typename add_reference<Element>::type type;
|
||||
typedef typename add_const_reference<Element>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
};
|
||||
|
||||
template<typename Head, typename... Values>
|
||||
class get_impl<0, tuple<Head, Values...> >
|
||||
{
|
||||
public:
|
||||
typedef typename add_reference<Head>::type type;
|
||||
typedef typename add_const_reference<Head>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return t.head(); }
|
||||
static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
|
||||
};
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
|
||||
// be used to "unpack" into comma-separated values
|
||||
// in a function call.
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
template<int... Indexes>
|
||||
struct index_tuple{};
|
||||
|
||||
template<std::size_t Num, typename Tuple = index_tuple<> >
|
||||
struct build_number_seq;
|
||||
|
||||
template<std::size_t Num, int... Indexes>
|
||||
struct build_number_seq<Num, index_tuple<Indexes...> >
|
||||
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
|
||||
{};
|
||||
|
||||
template<int... Indexes>
|
||||
struct build_number_seq<0, index_tuple<Indexes...> >
|
||||
{ typedef index_tuple<Indexes...> type; };
|
||||
|
||||
|
||||
}}} //namespace boost { namespace container { namespace container_detail {
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
92
cpp/BoostParts/boost/container/detail/version_type.hpp
Normal file
92
cpp/BoostParts/boost/container/detail/version_type.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This code comes from N1953 document by Howard E. Hinnant
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
|
||||
#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
|
||||
|
||||
#include "config_begin.hpp"
|
||||
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace container {
|
||||
namespace container_detail {
|
||||
|
||||
//using namespace boost;
|
||||
|
||||
template <class T, unsigned V>
|
||||
struct version_type
|
||||
: public container_detail::integral_constant<unsigned, V>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
version_type(const version_type<T, 0>&);
|
||||
};
|
||||
|
||||
namespace impl{
|
||||
|
||||
template <class T,
|
||||
bool = container_detail::is_convertible<version_type<T, 0>, typename T::version>::value>
|
||||
struct extract_version
|
||||
{
|
||||
static const unsigned value = 1;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct extract_version<T, true>
|
||||
{
|
||||
static const unsigned value = T::version::value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct has_version
|
||||
{
|
||||
private:
|
||||
struct two {char _[2];};
|
||||
template <class U> static two test(...);
|
||||
template <class U> static char test(const typename U::version*);
|
||||
public:
|
||||
static const bool value = sizeof(test<T>(0)) == 1;
|
||||
void dummy(){}
|
||||
};
|
||||
|
||||
template <class T, bool = has_version<T>::value>
|
||||
struct version
|
||||
{
|
||||
static const unsigned value = 1;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct version<T, true>
|
||||
{
|
||||
static const unsigned value = extract_version<T>::value;
|
||||
};
|
||||
|
||||
} //namespace impl
|
||||
|
||||
template <class T>
|
||||
struct version
|
||||
: public container_detail::integral_constant<unsigned, impl::version<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
} //namespace container {
|
||||
} //namespace boost{
|
||||
|
||||
#include "config_end.hpp"
|
||||
|
||||
#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
|
1507
cpp/BoostParts/boost/container/map.hpp
Normal file
1507
cpp/BoostParts/boost/container/map.hpp
Normal file
File diff suppressed because it is too large
Load Diff
41
cpp/BoostParts/boost/cstdlib.hpp
Normal file
41
cpp/BoostParts/boost/cstdlib.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// boost/cstdlib.hpp header ------------------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2001. 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/utility/cstdlib.html for documentation.
|
||||
|
||||
// Revision History
|
||||
// 26 Feb 01 Initial version (Beman Dawes)
|
||||
|
||||
#ifndef BOOST_CSTDLIB_HPP
|
||||
#define BOOST_CSTDLIB_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// The intent is to propose the following for addition to namespace std
|
||||
// in the C++ Standard Library, and to then deprecate EXIT_SUCCESS and
|
||||
// EXIT_FAILURE. As an implementation detail, this header defines the
|
||||
// new constants in terms of EXIT_SUCCESS and EXIT_FAILURE. In a new
|
||||
// standard, the constants would be implementation-defined, although it
|
||||
// might be worthwhile to "suggest" (which a standard is allowed to do)
|
||||
// values of 0 and 1 respectively.
|
||||
|
||||
// Rationale for having multiple failure values: some environments may
|
||||
// wish to distinguish between different classes of errors.
|
||||
// Rationale for choice of values: programs often use values < 100 for
|
||||
// their own error reporting. Values > 255 are sometimes reserved for
|
||||
// system detected errors. 200/201 were suggested to minimize conflict.
|
||||
|
||||
const int exit_success = EXIT_SUCCESS; // implementation-defined value
|
||||
const int exit_failure = EXIT_FAILURE; // implementation-defined value
|
||||
const int exit_exception_failure = 200; // otherwise uncaught exception
|
||||
const int exit_test_failure = 201; // report_error or
|
||||
// report_critical_error called.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
767
cpp/BoostParts/boost/date_time/date_facet.hpp
Normal file
767
cpp/BoostParts/boost/date_time/date_facet.hpp
Normal file
@ -0,0 +1,767 @@
|
||||
#ifndef _DATE_TIME_DATE_FACET__HPP___
|
||||
#define _DATE_TIME_DATE_FACET__HPP___
|
||||
|
||||
/* Copyright (c) 2004-2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Martin Andrian, Jeff Garland, Bart Garst
|
||||
* $Date: 2012-09-30 16:25:22 -0700 (Sun, 30 Sep 2012) $
|
||||
*/
|
||||
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iterator> // ostreambuf_iterator
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/date_time/compiler_config.hpp>
|
||||
#include <boost/date_time/period.hpp>
|
||||
#include <boost/date_time/special_defs.hpp>
|
||||
#include <boost/date_time/special_values_formatter.hpp>
|
||||
#include <boost/date_time/period_formatter.hpp>
|
||||
#include <boost/date_time/period_parser.hpp>
|
||||
#include <boost/date_time/date_generator_formatter.hpp>
|
||||
#include <boost/date_time/date_generator_parser.hpp>
|
||||
#include <boost/date_time/format_date_parser.hpp>
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
|
||||
/*! Class that provides format based I/O facet for date types.
|
||||
*
|
||||
* This class allows the formatting of dates by using format string.
|
||||
* Format strings are:
|
||||
*
|
||||
* - %A => long_weekday_format - Full name Ex: Tuesday
|
||||
* - %a => short_weekday_format - Three letter abbreviation Ex: Tue
|
||||
* - %B => long_month_format - Full name Ex: October
|
||||
* - %b => short_month_format - Three letter abbreviation Ex: Oct
|
||||
* - %x => standard_format_specifier - defined by the locale
|
||||
* - %Y-%b-%d => default_date_format - YYYY-Mon-dd
|
||||
*
|
||||
* Default month format == %b
|
||||
* Default weekday format == %a
|
||||
*/
|
||||
template <class date_type,
|
||||
class CharT,
|
||||
class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
|
||||
class date_facet : public std::locale::facet {
|
||||
public:
|
||||
typedef typename date_type::duration_type duration_type;
|
||||
// greg_weekday is gregorian_calendar::day_of_week_type
|
||||
typedef typename date_type::day_of_week_type day_of_week_type;
|
||||
typedef typename date_type::day_type day_type;
|
||||
typedef typename date_type::month_type month_type;
|
||||
typedef boost::date_time::period<date_type,duration_type> period_type;
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
typedef CharT char_type;
|
||||
typedef boost::date_time::period_formatter<CharT> period_formatter_type;
|
||||
typedef boost::date_time::special_values_formatter<CharT> special_values_formatter_type;
|
||||
typedef std::vector<std::basic_string<CharT> > input_collection_type;
|
||||
// used for the output of the date_generators
|
||||
typedef date_generator_formatter<date_type, CharT> date_gen_formatter_type;
|
||||
typedef partial_date<date_type> partial_date_type;
|
||||
typedef nth_kday_of_month<date_type> nth_kday_type;
|
||||
typedef first_kday_of_month<date_type> first_kday_type;
|
||||
typedef last_kday_of_month<date_type> last_kday_type;
|
||||
typedef first_kday_after<date_type> kday_after_type;
|
||||
typedef first_kday_before<date_type> kday_before_type;
|
||||
static const char_type long_weekday_format[3];
|
||||
static const char_type short_weekday_format[3];
|
||||
static const char_type long_month_format[3];
|
||||
static const char_type short_month_format[3];
|
||||
static const char_type default_period_separator[4];
|
||||
static const char_type standard_format_specifier[3];
|
||||
static const char_type iso_format_specifier[7];
|
||||
static const char_type iso_format_extended_specifier[9];
|
||||
static const char_type default_date_format[9]; // YYYY-Mon-DD
|
||||
static std::locale::id id;
|
||||
|
||||
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
|
||||
std::locale::id& __get_id (void) const { return id; }
|
||||
#endif
|
||||
|
||||
explicit date_facet(::size_t a_ref = 0)
|
||||
: std::locale::facet(a_ref),
|
||||
//m_format(standard_format_specifier)
|
||||
m_format(default_date_format),
|
||||
m_month_format(short_month_format),
|
||||
m_weekday_format(short_weekday_format)
|
||||
{}
|
||||
|
||||
explicit date_facet(const char_type* format_str,
|
||||
const input_collection_type& short_names,
|
||||
::size_t ref_count = 0)
|
||||
: std::locale::facet(ref_count),
|
||||
m_format(format_str),
|
||||
m_month_format(short_month_format),
|
||||
m_weekday_format(short_weekday_format),
|
||||
m_month_short_names(short_names)
|
||||
{}
|
||||
|
||||
|
||||
explicit date_facet(const char_type* format_str,
|
||||
period_formatter_type per_formatter = period_formatter_type(),
|
||||
special_values_formatter_type sv_formatter = special_values_formatter_type(),
|
||||
date_gen_formatter_type dg_formatter = date_gen_formatter_type(),
|
||||
::size_t ref_count = 0)
|
||||
: std::locale::facet(ref_count),
|
||||
m_format(format_str),
|
||||
m_month_format(short_month_format),
|
||||
m_weekday_format(short_weekday_format),
|
||||
m_period_formatter(per_formatter),
|
||||
m_date_gen_formatter(dg_formatter),
|
||||
m_special_values_formatter(sv_formatter)
|
||||
{}
|
||||
void format(const char_type* const format_str) {
|
||||
m_format = format_str;
|
||||
}
|
||||
virtual void set_iso_format()
|
||||
{
|
||||
m_format = iso_format_specifier;
|
||||
}
|
||||
virtual void set_iso_extended_format()
|
||||
{
|
||||
m_format = iso_format_extended_specifier;
|
||||
}
|
||||
void month_format(const char_type* const format_str) {
|
||||
m_month_format = format_str;
|
||||
}
|
||||
void weekday_format(const char_type* const format_str) {
|
||||
m_weekday_format = format_str;
|
||||
}
|
||||
|
||||
void period_formatter(period_formatter_type per_formatter) {
|
||||
m_period_formatter= per_formatter;
|
||||
}
|
||||
void special_values_formatter(const special_values_formatter_type& svf)
|
||||
{
|
||||
m_special_values_formatter = svf;
|
||||
}
|
||||
void short_weekday_names(const input_collection_type& short_names)
|
||||
{
|
||||
m_weekday_short_names = short_names;
|
||||
}
|
||||
void long_weekday_names(const input_collection_type& long_names)
|
||||
{
|
||||
m_weekday_long_names = long_names;
|
||||
}
|
||||
|
||||
void short_month_names(const input_collection_type& short_names)
|
||||
{
|
||||
m_month_short_names = short_names;
|
||||
}
|
||||
|
||||
void long_month_names(const input_collection_type& long_names)
|
||||
{
|
||||
m_month_long_names = long_names;
|
||||
}
|
||||
|
||||
void date_gen_phrase_strings(const input_collection_type& new_strings,
|
||||
typename date_gen_formatter_type::phrase_elements beg_pos=date_gen_formatter_type::first)
|
||||
{
|
||||
m_date_gen_formatter.elements(new_strings, beg_pos);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const date_type& d) const
|
||||
{
|
||||
if (d.is_special()) {
|
||||
return do_put_special(next, a_ios, fill_char, d.as_special());
|
||||
}
|
||||
//The following line of code required the date to support a to_tm function
|
||||
return do_put_tm(next, a_ios, fill_char, to_tm(d), m_format);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const duration_type& dd) const
|
||||
{
|
||||
if (dd.is_special()) {
|
||||
return do_put_special(next, a_ios, fill_char, dd.get_rep().as_special());
|
||||
}
|
||||
|
||||
typedef std::num_put<CharT, OutItrT> num_put;
|
||||
if (std::has_facet<num_put>(a_ios.getloc())) {
|
||||
return std::use_facet<num_put>(a_ios.getloc()).put(next, a_ios, fill_char, dd.get_rep().as_number());
|
||||
}
|
||||
else {
|
||||
num_put* f = new num_put();
|
||||
std::locale l = std::locale(a_ios.getloc(), f);
|
||||
a_ios.imbue(l);
|
||||
return f->put(next, a_ios, fill_char, dd.get_rep().as_number());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const month_type& m) const
|
||||
{
|
||||
//if (d.is_special()) {
|
||||
// return do_put_special(next, a_ios, fill_char, d.as_special());
|
||||
//}
|
||||
//The following line of code required the date to support a to_tm function
|
||||
std::tm dtm;
|
||||
std::memset(&dtm, 0, sizeof(dtm));
|
||||
dtm.tm_mon = m - 1;
|
||||
return do_put_tm(next, a_ios, fill_char, dtm, m_month_format);
|
||||
}
|
||||
|
||||
//! puts the day of month
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const day_type& day) const
|
||||
{
|
||||
std::tm dtm;
|
||||
std::memset(&dtm, 0, sizeof(dtm));
|
||||
dtm.tm_mday = day.as_number();
|
||||
char_type tmp[3] = {'%','d'};
|
||||
string_type temp_format(tmp);
|
||||
return do_put_tm(next, a_ios, fill_char, dtm, temp_format);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const day_of_week_type& dow) const
|
||||
{
|
||||
//if (d.is_special()) {
|
||||
// return do_put_special(next, a_ios, fill_char, d.as_special());
|
||||
//}
|
||||
//The following line of code required the date to support a to_tm function
|
||||
std::tm dtm;
|
||||
std::memset(&dtm, 0, sizeof(dtm));
|
||||
dtm.tm_wday = dow;
|
||||
return do_put_tm(next, a_ios, fill_char, dtm, m_weekday_format);
|
||||
}
|
||||
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const period_type& p) const
|
||||
{
|
||||
return m_period_formatter.put_period(next, a_ios, fill_char, p, *this);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const partial_date_type& pd) const
|
||||
{
|
||||
return m_date_gen_formatter.put_partial_date(next, a_ios, fill_char, pd, *this);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const nth_kday_type& nkd) const
|
||||
{
|
||||
return m_date_gen_formatter.put_nth_kday(next, a_ios, fill_char, nkd, *this);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const first_kday_type& fkd) const
|
||||
{
|
||||
return m_date_gen_formatter.put_first_kday(next, a_ios, fill_char, fkd, *this);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const last_kday_type& lkd) const
|
||||
{
|
||||
return m_date_gen_formatter.put_last_kday(next, a_ios, fill_char, lkd, *this);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const kday_before_type& fkb) const
|
||||
{
|
||||
return m_date_gen_formatter.put_kday_before(next, a_ios, fill_char, fkb, *this);
|
||||
}
|
||||
|
||||
OutItrT put(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const kday_after_type& fka) const
|
||||
{
|
||||
return m_date_gen_formatter.put_kday_after(next, a_ios, fill_char, fka, *this);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual OutItrT do_put_special(OutItrT next,
|
||||
std::ios_base& /*a_ios*/,
|
||||
char_type /*fill_char*/,
|
||||
const boost::date_time::special_values sv) const
|
||||
{
|
||||
m_special_values_formatter.put_special(next, sv);
|
||||
return next;
|
||||
}
|
||||
virtual OutItrT do_put_tm(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type fill_char,
|
||||
const tm& tm_value,
|
||||
string_type a_format) const
|
||||
{
|
||||
// update format string with custom names
|
||||
if (m_weekday_long_names.size()) {
|
||||
boost::algorithm::replace_all(a_format,
|
||||
long_weekday_format,
|
||||
m_weekday_long_names[tm_value.tm_wday]);
|
||||
}
|
||||
if (m_weekday_short_names.size()) {
|
||||
boost::algorithm::replace_all(a_format,
|
||||
short_weekday_format,
|
||||
m_weekday_short_names[tm_value.tm_wday]);
|
||||
|
||||
}
|
||||
if (m_month_long_names.size()) {
|
||||
boost::algorithm::replace_all(a_format,
|
||||
long_month_format,
|
||||
m_month_long_names[tm_value.tm_mon]);
|
||||
}
|
||||
if (m_month_short_names.size()) {
|
||||
boost::algorithm::replace_all(a_format,
|
||||
short_month_format,
|
||||
m_month_short_names[tm_value.tm_mon]);
|
||||
}
|
||||
// use time_put facet to create final string
|
||||
const char_type* p_format = a_format.c_str();
|
||||
return std::use_facet<std::time_put<CharT> >(a_ios.getloc()).put(next, a_ios,
|
||||
fill_char,
|
||||
&tm_value,
|
||||
p_format,
|
||||
p_format + a_format.size());
|
||||
}
|
||||
protected:
|
||||
string_type m_format;
|
||||
string_type m_month_format;
|
||||
string_type m_weekday_format;
|
||||
period_formatter_type m_period_formatter;
|
||||
date_gen_formatter_type m_date_gen_formatter;
|
||||
special_values_formatter_type m_special_values_formatter;
|
||||
input_collection_type m_month_short_names;
|
||||
input_collection_type m_month_long_names;
|
||||
input_collection_type m_weekday_short_names;
|
||||
input_collection_type m_weekday_long_names;
|
||||
private:
|
||||
};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
std::locale::id date_facet<date_type, CharT, OutItrT>::id;
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] =
|
||||
{'%', 'x' };
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] =
|
||||
{'%', 'Y', '%', 'm', '%', 'd' };
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] =
|
||||
{'%', 'Y', '-', '%', 'm', '-', '%', 'd' };
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_facet<date_type, CharT, OutItrT>::default_date_format[9] =
|
||||
{'%','Y','-','%','b','-','%','d'};
|
||||
|
||||
|
||||
|
||||
//! Input facet
|
||||
template <class date_type,
|
||||
class CharT,
|
||||
class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
|
||||
class date_input_facet : public std::locale::facet {
|
||||
public:
|
||||
typedef typename date_type::duration_type duration_type;
|
||||
// greg_weekday is gregorian_calendar::day_of_week_type
|
||||
typedef typename date_type::day_of_week_type day_of_week_type;
|
||||
typedef typename date_type::day_type day_type;
|
||||
typedef typename date_type::month_type month_type;
|
||||
typedef typename date_type::year_type year_type;
|
||||
typedef boost::date_time::period<date_type,duration_type> period_type;
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
typedef CharT char_type;
|
||||
typedef boost::date_time::period_parser<date_type, CharT> period_parser_type;
|
||||
typedef boost::date_time::special_values_parser<date_type,CharT> special_values_parser_type;
|
||||
typedef std::vector<std::basic_string<CharT> > input_collection_type;
|
||||
typedef format_date_parser<date_type, CharT> format_date_parser_type;
|
||||
// date_generators stuff goes here
|
||||
typedef date_generator_parser<date_type, CharT> date_gen_parser_type;
|
||||
typedef partial_date<date_type> partial_date_type;
|
||||
typedef nth_kday_of_month<date_type> nth_kday_type;
|
||||
typedef first_kday_of_month<date_type> first_kday_type;
|
||||
typedef last_kday_of_month<date_type> last_kday_type;
|
||||
typedef first_kday_after<date_type> kday_after_type;
|
||||
typedef first_kday_before<date_type> kday_before_type;
|
||||
|
||||
static const char_type long_weekday_format[3];
|
||||
static const char_type short_weekday_format[3];
|
||||
static const char_type long_month_format[3];
|
||||
static const char_type short_month_format[3];
|
||||
static const char_type four_digit_year_format[3];
|
||||
static const char_type two_digit_year_format[3];
|
||||
static const char_type default_period_separator[4];
|
||||
static const char_type standard_format_specifier[3];
|
||||
static const char_type iso_format_specifier[7];
|
||||
static const char_type iso_format_extended_specifier[9];
|
||||
static const char_type default_date_format[9]; // YYYY-Mon-DD
|
||||
static std::locale::id id;
|
||||
|
||||
explicit date_input_facet(::size_t a_ref = 0)
|
||||
: std::locale::facet(a_ref),
|
||||
m_format(default_date_format),
|
||||
m_month_format(short_month_format),
|
||||
m_weekday_format(short_weekday_format),
|
||||
m_year_format(four_digit_year_format),
|
||||
m_parser(m_format, std::locale::classic())
|
||||
// default period_parser & special_values_parser used
|
||||
{}
|
||||
|
||||
explicit date_input_facet(const string_type& format_str,
|
||||
::size_t a_ref = 0)
|
||||
: std::locale::facet(a_ref),
|
||||
m_format(format_str),
|
||||
m_month_format(short_month_format),
|
||||
m_weekday_format(short_weekday_format),
|
||||
m_year_format(four_digit_year_format),
|
||||
m_parser(m_format, std::locale::classic())
|
||||
// default period_parser & special_values_parser used
|
||||
{}
|
||||
|
||||
explicit date_input_facet(const string_type& format_str,
|
||||
const format_date_parser_type& date_parser,
|
||||
const special_values_parser_type& sv_parser,
|
||||
const period_parser_type& per_parser,
|
||||
const date_gen_parser_type& date_gen_parser,
|
||||
::size_t ref_count = 0)
|
||||
: std::locale::facet(ref_count),
|
||||
m_format(format_str),
|
||||
m_month_format(short_month_format),
|
||||
m_weekday_format(short_weekday_format),
|
||||
m_year_format(four_digit_year_format),
|
||||
m_parser(date_parser),
|
||||
m_date_gen_parser(date_gen_parser),
|
||||
m_period_parser(per_parser),
|
||||
m_sv_parser(sv_parser)
|
||||
{}
|
||||
|
||||
|
||||
void format(const char_type* const format_str) {
|
||||
m_format = format_str;
|
||||
}
|
||||
virtual void set_iso_format()
|
||||
{
|
||||
m_format = iso_format_specifier;
|
||||
}
|
||||
virtual void set_iso_extended_format()
|
||||
{
|
||||
m_format = iso_format_extended_specifier;
|
||||
}
|
||||
void month_format(const char_type* const format_str) {
|
||||
m_month_format = format_str;
|
||||
}
|
||||
void weekday_format(const char_type* const format_str) {
|
||||
m_weekday_format = format_str;
|
||||
}
|
||||
void year_format(const char_type* const format_str) {
|
||||
m_year_format = format_str;
|
||||
}
|
||||
|
||||
void period_parser(period_parser_type per_parser) {
|
||||
m_period_parser = per_parser;
|
||||
}
|
||||
void short_weekday_names(const input_collection_type& weekday_names)
|
||||
{
|
||||
m_parser.short_weekday_names(weekday_names);
|
||||
}
|
||||
void long_weekday_names(const input_collection_type& weekday_names)
|
||||
{
|
||||
m_parser.long_weekday_names(weekday_names);
|
||||
}
|
||||
|
||||
void short_month_names(const input_collection_type& month_names)
|
||||
{
|
||||
m_parser.short_month_names(month_names);
|
||||
}
|
||||
|
||||
void long_month_names(const input_collection_type& month_names)
|
||||
{
|
||||
m_parser.long_month_names(month_names);
|
||||
}
|
||||
|
||||
void date_gen_element_strings(const input_collection_type& col)
|
||||
{
|
||||
m_date_gen_parser.element_strings(col);
|
||||
}
|
||||
void date_gen_element_strings(const string_type& first,
|
||||
const string_type& second,
|
||||
const string_type& third,
|
||||
const string_type& fourth,
|
||||
const string_type& fifth,
|
||||
const string_type& last,
|
||||
const string_type& before,
|
||||
const string_type& after,
|
||||
const string_type& of)
|
||||
|
||||
{
|
||||
m_date_gen_parser.element_strings(first,second,third,fourth,fifth,last,before,after,of);
|
||||
}
|
||||
|
||||
void special_values_parser(special_values_parser_type sv_parser)
|
||||
{
|
||||
m_sv_parser = sv_parser;
|
||||
}
|
||||
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& /*a_ios*/,
|
||||
date_type& d) const
|
||||
{
|
||||
d = m_parser.parse_date(from, to, m_format, m_sv_parser);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& /*a_ios*/,
|
||||
month_type& m) const
|
||||
{
|
||||
m = m_parser.parse_month(from, to, m_month_format);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& /*a_ios*/,
|
||||
day_of_week_type& wd) const
|
||||
{
|
||||
wd = m_parser.parse_weekday(from, to, m_weekday_format);
|
||||
return from;
|
||||
}
|
||||
//! Expects 1 or 2 digit day range: 1-31
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& /*a_ios*/,
|
||||
day_type& d) const
|
||||
{
|
||||
d = m_parser.parse_var_day_of_month(from, to);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& /*a_ios*/,
|
||||
year_type& y) const
|
||||
{
|
||||
y = m_parser.parse_year(from, to, m_year_format);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
duration_type& dd) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*from) && from != to) { ++from; }
|
||||
|
||||
/* num_get.get() will always consume the first character if it
|
||||
* is a sign indicator (+/-). Special value strings may begin
|
||||
* with one of these signs so we'll need a copy of it
|
||||
* in case num_get.get() fails. */
|
||||
char_type c = '\0';
|
||||
// TODO Are these characters somewhere in the locale?
|
||||
if(*from == '-' || *from == '+') {
|
||||
c = *from;
|
||||
}
|
||||
typedef std::num_get<CharT, InItrT> num_get;
|
||||
typename duration_type::duration_rep_type val = 0;
|
||||
std::ios_base::iostate err = std::ios_base::goodbit;
|
||||
|
||||
if (std::has_facet<num_get>(a_ios.getloc())) {
|
||||
from = std::use_facet<num_get>(a_ios.getloc()).get(from, to, a_ios, err, val);
|
||||
}
|
||||
else {
|
||||
num_get* ng = new num_get();
|
||||
std::locale l = std::locale(a_ios.getloc(), ng);
|
||||
a_ios.imbue(l);
|
||||
from = ng->get(from, to, a_ios, err, val);
|
||||
}
|
||||
if(err & std::ios_base::failbit){
|
||||
typedef typename special_values_parser_type::match_results match_results;
|
||||
match_results mr;
|
||||
if(c == '-' || c == '+') { // was the first character consumed?
|
||||
mr.cache += c;
|
||||
}
|
||||
m_sv_parser.match(from, to, mr);
|
||||
if(mr.current_match == match_results::PARSE_ERROR) {
|
||||
boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"));
|
||||
BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return from); // should never reach
|
||||
}
|
||||
dd = duration_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
else {
|
||||
dd = duration_type(val);
|
||||
}
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
period_type& p) const
|
||||
{
|
||||
p = m_period_parser.get_period(from, to, a_ios, p, duration_type::unit(), *this);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
nth_kday_type& nkd) const
|
||||
{
|
||||
nkd = m_date_gen_parser.get_nth_kday_type(from, to, a_ios, *this);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
partial_date_type& pd) const
|
||||
{
|
||||
|
||||
pd = m_date_gen_parser.get_partial_date_type(from, to, a_ios, *this);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
first_kday_type& fkd) const
|
||||
{
|
||||
fkd = m_date_gen_parser.get_first_kday_type(from, to, a_ios, *this);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
last_kday_type& lkd) const
|
||||
{
|
||||
lkd = m_date_gen_parser.get_last_kday_type(from, to, a_ios, *this);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
kday_before_type& fkb) const
|
||||
{
|
||||
fkb = m_date_gen_parser.get_kday_before_type(from, to, a_ios, *this);
|
||||
return from;
|
||||
}
|
||||
InItrT get(InItrT& from,
|
||||
InItrT& to,
|
||||
std::ios_base& a_ios,
|
||||
kday_after_type& fka) const
|
||||
{
|
||||
fka = m_date_gen_parser.get_kday_after_type(from, to, a_ios, *this);
|
||||
return from;
|
||||
}
|
||||
|
||||
protected:
|
||||
string_type m_format;
|
||||
string_type m_month_format;
|
||||
string_type m_weekday_format;
|
||||
string_type m_year_format;
|
||||
format_date_parser_type m_parser;
|
||||
date_gen_parser_type m_date_gen_parser;
|
||||
period_parser_type m_period_parser;
|
||||
special_values_parser_type m_sv_parser;
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
std::locale::id date_input_facet<date_type, CharT, OutItrT>::id;
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::four_digit_year_format[3] = {'%','Y'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::two_digit_year_format[3] = {'%','y'};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '};
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] =
|
||||
{'%', 'x' };
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] =
|
||||
{'%', 'Y', '%', 'm', '%', 'd' };
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] =
|
||||
{'%', 'Y', '-', '%', 'm', '-', '%', 'd' };
|
||||
|
||||
template <class date_type, class CharT, class OutItrT>
|
||||
const typename date_input_facet<date_type, CharT, OutItrT>::char_type
|
||||
date_input_facet<date_type, CharT, OutItrT>::default_date_format[9] =
|
||||
{'%','Y','-','%','b','-','%','d'};
|
||||
|
||||
} } // namespaces
|
||||
|
||||
|
||||
#endif
|
265
cpp/BoostParts/boost/date_time/date_generator_formatter.hpp
Normal file
265
cpp/BoostParts/boost/date_time/date_generator_formatter.hpp
Normal file
@ -0,0 +1,265 @@
|
||||
#ifndef _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___
|
||||
#define _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___
|
||||
|
||||
/* Copyright (c) 2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-11-13 11:05:31 -0800 (Thu, 13 Nov 2008) $
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "boost/date_time/date_generators.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace date_time {
|
||||
|
||||
//! Formats date_generators for output
|
||||
/*! Formatting of date_generators follows specific orders for the
|
||||
* various types of date_generators.
|
||||
* - partial_date => "dd Month"
|
||||
* - nth_day_of_the_week_in_month => "nth weekday of month"
|
||||
* - first_day_of_the_week_in_month => "first weekday of month"
|
||||
* - last_day_of_the_week_in_month => "last weekday of month"
|
||||
* - first_day_of_the_week_after => "weekday after"
|
||||
* - first_day_of_the_week_before => "weekday before"
|
||||
* While the order of the elements in these phrases cannot be changed,
|
||||
* the elements themselves can be. Weekday and Month get their formats
|
||||
* and names from the date_facet. The remaining elements are stored in
|
||||
* the date_generator_formatter and can be customized upon construction
|
||||
* or via a member function. The default elements are those shown in the
|
||||
* examples above.
|
||||
*/
|
||||
template <class date_type, class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
|
||||
class date_generator_formatter {
|
||||
public:
|
||||
typedef partial_date<date_type> partial_date_type;
|
||||
typedef nth_kday_of_month<date_type> nth_kday_type;
|
||||
typedef first_kday_of_month<date_type> first_kday_type;
|
||||
typedef last_kday_of_month<date_type> last_kday_type;
|
||||
typedef first_kday_after<date_type> kday_after_type;
|
||||
typedef first_kday_before<date_type> kday_before_type;
|
||||
|
||||
typedef CharT char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
typedef std::vector<string_type> collection_type;
|
||||
static const char_type first_string[6];
|
||||
static const char_type second_string[7];
|
||||
static const char_type third_string[6];
|
||||
static const char_type fourth_string[7];
|
||||
static const char_type fifth_string[6];
|
||||
static const char_type last_string[5];
|
||||
static const char_type before_string[8];
|
||||
static const char_type after_string[6];
|
||||
static const char_type of_string[3];
|
||||
|
||||
enum phrase_elements {first=0, second, third, fourth, fifth, last,
|
||||
before, after, of, number_of_phrase_elements};
|
||||
|
||||
//! Default format elements used
|
||||
date_generator_formatter()
|
||||
{
|
||||
phrase_strings.reserve(number_of_phrase_elements);
|
||||
phrase_strings.push_back(string_type(first_string));
|
||||
phrase_strings.push_back(string_type(second_string));
|
||||
phrase_strings.push_back(string_type(third_string));
|
||||
phrase_strings.push_back(string_type(fourth_string));
|
||||
phrase_strings.push_back(string_type(fifth_string));
|
||||
phrase_strings.push_back(string_type(last_string));
|
||||
phrase_strings.push_back(string_type(before_string));
|
||||
phrase_strings.push_back(string_type(after_string));
|
||||
phrase_strings.push_back(string_type(of_string));
|
||||
}
|
||||
|
||||
//! Constructor that allows for a custom set of phrase elements
|
||||
date_generator_formatter(const string_type& first_str,
|
||||
const string_type& second_str,
|
||||
const string_type& third_str,
|
||||
const string_type& fourth_str,
|
||||
const string_type& fifth_str,
|
||||
const string_type& last_str,
|
||||
const string_type& before_str,
|
||||
const string_type& after_str,
|
||||
const string_type& of_str)
|
||||
{
|
||||
phrase_strings.reserve(number_of_phrase_elements);
|
||||
phrase_strings.push_back(first_str);
|
||||
phrase_strings.push_back(second_str);
|
||||
phrase_strings.push_back(third_str);
|
||||
phrase_strings.push_back(fourth_str);
|
||||
phrase_strings.push_back(fifth_str);
|
||||
phrase_strings.push_back(last_str);
|
||||
phrase_strings.push_back(before_str);
|
||||
phrase_strings.push_back(after_str);
|
||||
phrase_strings.push_back(of_str);
|
||||
}
|
||||
|
||||
//! Replace the set of phrase elements with those contained in new_strings
|
||||
/*! The order of the strings in the given collection is important.
|
||||
* They must follow:
|
||||
* - first, second, third, fourth, fifth, last, before, after, of.
|
||||
*
|
||||
* It is not necessary to send in a complete set if only a few
|
||||
* elements are to be replaced as long as the correct beg_pos is used.
|
||||
*
|
||||
* Ex: To keep the default first through fifth elements, but replace
|
||||
* the rest with a collection of:
|
||||
* - "final", "prior", "following", "in".
|
||||
* The beg_pos of date_generator_formatter::last would be used.
|
||||
*/
|
||||
void elements(const collection_type& new_strings,
|
||||
phrase_elements beg_pos=first)
|
||||
{
|
||||
if(beg_pos < number_of_phrase_elements) {
|
||||
typename collection_type::iterator itr = phrase_strings.begin();
|
||||
itr += beg_pos;
|
||||
std::copy(new_strings.begin(), new_strings.end(),
|
||||
itr);
|
||||
//phrase_strings.begin());
|
||||
}
|
||||
}
|
||||
|
||||
//!Put a partial_date => "dd Month"
|
||||
template<class facet_type>
|
||||
OutItrT put_partial_date(OutItrT next, std::ios_base& a_ios,
|
||||
CharT a_fill, const partial_date_type& pd,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
facet.put(next, a_ios, a_fill, pd.day());
|
||||
next = a_fill; //TODO change this ???
|
||||
facet.put(next, a_ios, a_fill, pd.month());
|
||||
return next;
|
||||
}
|
||||
|
||||
//! Put an nth_day_of_the_week_in_month => "nth weekday of month"
|
||||
template<class facet_type>
|
||||
OutItrT put_nth_kday(OutItrT next, std::ios_base& a_ios,
|
||||
CharT a_fill, const nth_kday_type& nkd,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
put_string(next, phrase_strings[nkd.nth_week() -1]);
|
||||
next = a_fill; //TODO change this ???
|
||||
facet.put(next, a_ios, a_fill, nkd.day_of_week());
|
||||
next = a_fill; //TODO change this ???
|
||||
put_string(next, string_type(of_string));
|
||||
next = a_fill; //TODO change this ???
|
||||
facet.put(next, a_ios, a_fill, nkd.month());
|
||||
return next;
|
||||
}
|
||||
|
||||
//! Put a first_day_of_the_week_in_month => "first weekday of month"
|
||||
template<class facet_type>
|
||||
OutItrT put_first_kday(OutItrT next, std::ios_base& a_ios,
|
||||
CharT a_fill, const first_kday_type& fkd,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
put_string(next, phrase_strings[first]);
|
||||
next = a_fill; //TODO change this ???
|
||||
facet.put(next, a_ios, a_fill, fkd.day_of_week());
|
||||
next = a_fill; //TODO change this ???
|
||||
put_string(next, string_type(of_string));
|
||||
next = a_fill; //TODO change this ???
|
||||
facet.put(next, a_ios, a_fill, fkd.month());
|
||||
return next;
|
||||
}
|
||||
|
||||
//! Put a last_day_of_the_week_in_month => "last weekday of month"
|
||||
template<class facet_type>
|
||||
OutItrT put_last_kday(OutItrT next, std::ios_base& a_ios,
|
||||
CharT a_fill, const last_kday_type& lkd,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
put_string(next, phrase_strings[last]);
|
||||
next = a_fill; //TODO change this ???
|
||||
facet.put(next, a_ios, a_fill, lkd.day_of_week());
|
||||
next = a_fill; //TODO change this ???
|
||||
put_string(next, string_type(of_string));
|
||||
next = a_fill; //TODO change this ???
|
||||
facet.put(next, a_ios, a_fill, lkd.month());
|
||||
return next;
|
||||
}
|
||||
|
||||
//! Put a first_day_of_the_week_before => "weekday before"
|
||||
template<class facet_type>
|
||||
OutItrT put_kday_before(OutItrT next, std::ios_base& a_ios,
|
||||
CharT a_fill, const kday_before_type& fkb,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
facet.put(next, a_ios, a_fill, fkb.day_of_week());
|
||||
next = a_fill; //TODO change this ???
|
||||
put_string(next, phrase_strings[before]);
|
||||
return next;
|
||||
}
|
||||
|
||||
//! Put a first_day_of_the_week_after => "weekday after"
|
||||
template<class facet_type>
|
||||
OutItrT put_kday_after(OutItrT next, std::ios_base& a_ios,
|
||||
CharT a_fill, const kday_after_type& fka,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
facet.put(next, a_ios, a_fill, fka.day_of_week());
|
||||
next = a_fill; //TODO change this ???
|
||||
put_string(next, phrase_strings[after]);
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
collection_type phrase_strings;
|
||||
|
||||
//! helper function to put the various member string into stream
|
||||
OutItrT put_string(OutItrT next, const string_type& str) const
|
||||
{
|
||||
typename string_type::const_iterator itr = str.begin();
|
||||
while(itr != str.end()) {
|
||||
*next = *itr;
|
||||
++itr;
|
||||
++next;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
};
|
||||
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::first_string[6] =
|
||||
{'f','i','r','s','t'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::second_string[7] =
|
||||
{'s','e','c','o','n','d'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::third_string[6] =
|
||||
{'t','h','i','r','d'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::fourth_string[7] =
|
||||
{'f','o','u','r','t','h'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::fifth_string[6] =
|
||||
{'f','i','f','t','h'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::last_string[5] =
|
||||
{'l','a','s','t'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::before_string[8] =
|
||||
{'b','e','f','o','r','e'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::after_string[6] =
|
||||
{'a','f','t','e','r'};
|
||||
template<class date_type, class CharT, class OutItrT>
|
||||
const typename date_generator_formatter<date_type, CharT, OutItrT>::char_type
|
||||
date_generator_formatter<date_type, CharT, OutItrT>::of_string[3] =
|
||||
{'o','f'};
|
||||
} } // namespaces
|
||||
|
||||
#endif // _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___
|
330
cpp/BoostParts/boost/date_time/date_generator_parser.hpp
Normal file
330
cpp/BoostParts/boost/date_time/date_generator_parser.hpp
Normal file
@ -0,0 +1,330 @@
|
||||
|
||||
#ifndef DATE_TIME_DATE_GENERATOR_PARSER_HPP__
|
||||
#define DATE_TIME_DATE_GENERATOR_PARSER_HPP__
|
||||
|
||||
/* Copyright (c) 2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-11-12 11:37:53 -0800 (Wed, 12 Nov 2008) $
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iterator> // istreambuf_iterator
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/date_time/compiler_config.hpp>
|
||||
#include <boost/date_time/string_parse_tree.hpp>
|
||||
#include <boost/date_time/date_generators.hpp>
|
||||
#include <boost/date_time/format_date_parser.hpp>
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
//! Class for date_generator parsing
|
||||
/*! The elements of a date_generator "phrase" are parsed from the input stream in a
|
||||
* particular order. All elements are required and the order in which they appear
|
||||
* cannot change, however, the elements themselves can be changed. The default
|
||||
* elements and their order are as follows:
|
||||
*
|
||||
* - partial_date => "dd Month"
|
||||
* - nth_day_of_the_week_in_month => "nth weekday of month"
|
||||
* - first_day_of_the_week_in_month => "first weekday of month"
|
||||
* - last_day_of_the_week_in_month => "last weekday of month"
|
||||
* - first_day_of_the_week_after => "weekday after"
|
||||
* - first_day_of_the_week_before => "weekday before"
|
||||
*
|
||||
* Weekday and Month names and formats are handled via the date_input_facet.
|
||||
*
|
||||
*/
|
||||
template<class date_type, typename charT>
|
||||
class date_generator_parser
|
||||
{
|
||||
public:
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef std::istreambuf_iterator<charT> stream_itr_type;
|
||||
|
||||
typedef typename date_type::month_type month_type;
|
||||
typedef typename date_type::day_of_week_type day_of_week_type;
|
||||
typedef typename date_type::day_type day_type;
|
||||
|
||||
typedef string_parse_tree<charT> parse_tree_type;
|
||||
typedef typename parse_tree_type::parse_match_result_type match_results;
|
||||
typedef std::vector<std::basic_string<charT> > collection_type;
|
||||
|
||||
typedef partial_date<date_type> partial_date_type;
|
||||
typedef nth_kday_of_month<date_type> nth_kday_type;
|
||||
typedef first_kday_of_month<date_type> first_kday_type;
|
||||
typedef last_kday_of_month<date_type> last_kday_type;
|
||||
typedef first_kday_after<date_type> kday_after_type;
|
||||
typedef first_kday_before<date_type> kday_before_type;
|
||||
|
||||
typedef charT char_type;
|
||||
static const char_type first_string[6];
|
||||
static const char_type second_string[7];
|
||||
static const char_type third_string[6];
|
||||
static const char_type fourth_string[7];
|
||||
static const char_type fifth_string[6];
|
||||
static const char_type last_string[5];
|
||||
static const char_type before_string[8];
|
||||
static const char_type after_string[6];
|
||||
static const char_type of_string[3];
|
||||
|
||||
enum phrase_elements {first=0, second, third, fourth, fifth, last,
|
||||
before, after, of, number_of_phrase_elements};
|
||||
|
||||
//! Creates a date_generator_parser with the default set of "element_strings"
|
||||
date_generator_parser()
|
||||
{
|
||||
element_strings(string_type(first_string),
|
||||
string_type(second_string),
|
||||
string_type(third_string),
|
||||
string_type(fourth_string),
|
||||
string_type(fifth_string),
|
||||
string_type(last_string),
|
||||
string_type(before_string),
|
||||
string_type(after_string),
|
||||
string_type(of_string));
|
||||
}
|
||||
|
||||
//! Creates a date_generator_parser using a user defined set of element strings
|
||||
date_generator_parser(const string_type& first_str,
|
||||
const string_type& second_str,
|
||||
const string_type& third_str,
|
||||
const string_type& fourth_str,
|
||||
const string_type& fifth_str,
|
||||
const string_type& last_str,
|
||||
const string_type& before_str,
|
||||
const string_type& after_str,
|
||||
const string_type& of_str)
|
||||
{
|
||||
element_strings(first_str, second_str, third_str, fourth_str, fifth_str,
|
||||
last_str, before_str, after_str, of_str);
|
||||
}
|
||||
|
||||
//! Replace strings that determine nth week for generator
|
||||
void element_strings(const string_type& first_str,
|
||||
const string_type& second_str,
|
||||
const string_type& third_str,
|
||||
const string_type& fourth_str,
|
||||
const string_type& fifth_str,
|
||||
const string_type& last_str,
|
||||
const string_type& before_str,
|
||||
const string_type& after_str,
|
||||
const string_type& of_str)
|
||||
{
|
||||
collection_type phrases;
|
||||
phrases.push_back(first_str);
|
||||
phrases.push_back(second_str);
|
||||
phrases.push_back(third_str);
|
||||
phrases.push_back(fourth_str);
|
||||
phrases.push_back(fifth_str);
|
||||
phrases.push_back(last_str);
|
||||
phrases.push_back(before_str);
|
||||
phrases.push_back(after_str);
|
||||
phrases.push_back(of_str);
|
||||
m_element_strings = parse_tree_type(phrases, this->first); // enum first
|
||||
}
|
||||
|
||||
void element_strings(const collection_type& col)
|
||||
{
|
||||
m_element_strings = parse_tree_type(col, this->first); // enum first
|
||||
}
|
||||
|
||||
//! returns partial_date parsed from stream
|
||||
template<class facet_type>
|
||||
partial_date_type
|
||||
get_partial_date_type(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
std::ios_base& a_ios,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
day_type d(1);
|
||||
month_type m(1);
|
||||
facet.get(sitr, stream_end, a_ios, d);
|
||||
facet.get(sitr, stream_end, a_ios, m);
|
||||
|
||||
return partial_date_type(d,m);
|
||||
}
|
||||
|
||||
//! returns nth_kday_of_week parsed from stream
|
||||
template<class facet_type>
|
||||
nth_kday_type
|
||||
get_nth_kday_type(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
std::ios_base& a_ios,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
typename nth_kday_type::week_num wn;
|
||||
day_of_week_type wd(0); // no default constructor
|
||||
month_type m(1); // no default constructor
|
||||
|
||||
match_results mr = m_element_strings.match(sitr, stream_end);
|
||||
switch(mr.current_match) {
|
||||
case first : { wn = nth_kday_type::first; break; }
|
||||
case second : { wn = nth_kday_type::second; break; }
|
||||
case third : { wn = nth_kday_type::third; break; }
|
||||
case fourth : { wn = nth_kday_type::fourth; break; }
|
||||
case fifth : { wn = nth_kday_type::fifth; break; }
|
||||
default:
|
||||
{
|
||||
boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"));
|
||||
BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(wn = nth_kday_type::first);
|
||||
}
|
||||
} // week num
|
||||
facet.get(sitr, stream_end, a_ios, wd); // day_of_week
|
||||
extract_element(sitr, stream_end, of); // "of" element
|
||||
facet.get(sitr, stream_end, a_ios, m); // month
|
||||
|
||||
return nth_kday_type(wn, wd, m);
|
||||
}
|
||||
|
||||
//! returns first_kday_of_week parsed from stream
|
||||
template<class facet_type>
|
||||
first_kday_type
|
||||
get_first_kday_type(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
std::ios_base& a_ios,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
day_of_week_type wd(0); // no default constructor
|
||||
month_type m(1); // no default constructor
|
||||
|
||||
extract_element(sitr, stream_end, first); // "first" element
|
||||
facet.get(sitr, stream_end, a_ios, wd); // day_of_week
|
||||
extract_element(sitr, stream_end, of); // "of" element
|
||||
facet.get(sitr, stream_end, a_ios, m); // month
|
||||
|
||||
|
||||
return first_kday_type(wd, m);
|
||||
}
|
||||
|
||||
//! returns last_kday_of_week parsed from stream
|
||||
template<class facet_type>
|
||||
last_kday_type
|
||||
get_last_kday_type(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
std::ios_base& a_ios,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
day_of_week_type wd(0); // no default constructor
|
||||
month_type m(1); // no default constructor
|
||||
|
||||
extract_element(sitr, stream_end, last); // "last" element
|
||||
facet.get(sitr, stream_end, a_ios, wd); // day_of_week
|
||||
extract_element(sitr, stream_end, of); // "of" element
|
||||
facet.get(sitr, stream_end, a_ios, m); // month
|
||||
|
||||
|
||||
return last_kday_type(wd, m);
|
||||
}
|
||||
|
||||
//! returns first_kday_of_week parsed from stream
|
||||
template<class facet_type>
|
||||
kday_before_type
|
||||
get_kday_before_type(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
std::ios_base& a_ios,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
day_of_week_type wd(0); // no default constructor
|
||||
|
||||
facet.get(sitr, stream_end, a_ios, wd); // day_of_week
|
||||
extract_element(sitr, stream_end, before);// "before" element
|
||||
|
||||
return kday_before_type(wd);
|
||||
}
|
||||
|
||||
//! returns first_kday_of_week parsed from stream
|
||||
template<class facet_type>
|
||||
kday_after_type
|
||||
get_kday_after_type(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
std::ios_base& a_ios,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
day_of_week_type wd(0); // no default constructor
|
||||
|
||||
facet.get(sitr, stream_end, a_ios, wd); // day_of_week
|
||||
extract_element(sitr, stream_end, after); // "after" element
|
||||
|
||||
return kday_after_type(wd);
|
||||
}
|
||||
|
||||
private:
|
||||
parse_tree_type m_element_strings;
|
||||
|
||||
//! Extracts phrase element from input. Throws ios_base::failure on error.
|
||||
void extract_element(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
typename date_generator_parser::phrase_elements ele) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
match_results mr = m_element_strings.match(sitr, stream_end);
|
||||
if(mr.current_match != ele) {
|
||||
boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::first_string[6] =
|
||||
{'f','i','r','s','t'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::second_string[7] =
|
||||
{'s','e','c','o','n','d'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::third_string[6] =
|
||||
{'t','h','i','r','d'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::fourth_string[7] =
|
||||
{'f','o','u','r','t','h'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::fifth_string[6] =
|
||||
{'f','i','f','t','h'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::last_string[5] =
|
||||
{'l','a','s','t'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::before_string[8] =
|
||||
{'b','e','f','o','r','e'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::after_string[6] =
|
||||
{'a','f','t','e','r'};
|
||||
template<class date_type, class CharT>
|
||||
const typename date_generator_parser<date_type, CharT>::char_type
|
||||
date_generator_parser<date_type, CharT>::of_string[3] =
|
||||
{'o','f'};
|
||||
|
||||
} } //namespace
|
||||
|
||||
#endif // DATE_TIME_DATE_GENERATOR_PARSER_HPP__
|
||||
|
737
cpp/BoostParts/boost/date_time/format_date_parser.hpp
Normal file
737
cpp/BoostParts/boost/date_time/format_date_parser.hpp
Normal file
@ -0,0 +1,737 @@
|
||||
|
||||
#ifndef DATE_TIME_FORMAT_DATE_PARSER_HPP__
|
||||
#define DATE_TIME_FORMAT_DATE_PARSER_HPP__
|
||||
|
||||
/* Copyright (c) 2004-2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2012-09-30 16:25:22 -0700 (Sun, 30 Sep 2012) $
|
||||
*/
|
||||
|
||||
|
||||
#include "boost/lexical_cast.hpp"
|
||||
#include "boost/date_time/string_parse_tree.hpp"
|
||||
#include "boost/date_time/strings_from_facet.hpp"
|
||||
#include "boost/date_time/special_values_parser.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
# include <cctype>
|
||||
#else
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std {
|
||||
using ::isspace;
|
||||
using ::isdigit;
|
||||
}
|
||||
#endif
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
//! Helper function for parsing fixed length strings into integers
|
||||
/*! Will consume 'length' number of characters from stream. Consumed
|
||||
* character are transfered to parse_match_result struct.
|
||||
* Returns '-1' if no number can be parsed or incorrect number of
|
||||
* digits in stream. */
|
||||
template<typename int_type, typename charT>
|
||||
inline
|
||||
int_type
|
||||
fixed_string_to_int(std::istreambuf_iterator<charT>& itr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
parse_match_result<charT>& mr,
|
||||
unsigned int length,
|
||||
const charT& fill_char)
|
||||
{
|
||||
//typedef std::basic_string<charT> string_type;
|
||||
unsigned int j = 0;
|
||||
//string_type s;
|
||||
while (j < length && itr != stream_end &&
|
||||
(std::isdigit(*itr) || *itr == fill_char)) {
|
||||
if(*itr == fill_char) {
|
||||
/* Since a fill_char can be anything, we convert it to a zero.
|
||||
* lexical_cast will behave predictably when zero is used as fill. */
|
||||
mr.cache += ('0');
|
||||
}
|
||||
else {
|
||||
mr.cache += (*itr);
|
||||
}
|
||||
itr++;
|
||||
j++;
|
||||
}
|
||||
int_type i = -1;
|
||||
// mr.cache will hold leading zeros. size() tells us when input is too short.
|
||||
if(mr.cache.size() < length) {
|
||||
return i;
|
||||
}
|
||||
try {
|
||||
i = boost::lexical_cast<int_type>(mr.cache);
|
||||
}catch(bad_lexical_cast&){
|
||||
// we want to return -1 if the cast fails so nothing to do here
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//! Helper function for parsing fixed length strings into integers
|
||||
/*! Will consume 'length' number of characters from stream. Consumed
|
||||
* character are transfered to parse_match_result struct.
|
||||
* Returns '-1' if no number can be parsed or incorrect number of
|
||||
* digits in stream. */
|
||||
template<typename int_type, typename charT>
|
||||
inline
|
||||
int_type
|
||||
fixed_string_to_int(std::istreambuf_iterator<charT>& itr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
parse_match_result<charT>& mr,
|
||||
unsigned int length)
|
||||
{
|
||||
return fixed_string_to_int<int_type, charT>(itr, stream_end, mr, length, '0');
|
||||
}
|
||||
|
||||
//! Helper function for parsing varied length strings into integers
|
||||
/*! Will consume 'max_length' characters from stream only if those
|
||||
* characters are digits. Returns '-1' if no number can be parsed.
|
||||
* Will not parse a number preceeded by a '+' or '-'. */
|
||||
template<typename int_type, typename charT>
|
||||
inline
|
||||
int_type
|
||||
var_string_to_int(std::istreambuf_iterator<charT>& itr,
|
||||
const std::istreambuf_iterator<charT>& stream_end,
|
||||
unsigned int max_length)
|
||||
{
|
||||
typedef std::basic_string<charT> string_type;
|
||||
unsigned int j = 0;
|
||||
string_type s;
|
||||
while (itr != stream_end && (j < max_length) && std::isdigit(*itr)) {
|
||||
s += (*itr);
|
||||
++itr;
|
||||
++j;
|
||||
}
|
||||
int_type i = -1;
|
||||
if(!s.empty()) {
|
||||
i = boost::lexical_cast<int_type>(s);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
//! Class with generic date parsing using a format string
|
||||
/*! The following is the set of recognized format specifiers
|
||||
- %a - Short weekday name
|
||||
- %A - Long weekday name
|
||||
- %b - Abbreviated month name
|
||||
- %B - Full month name
|
||||
- %d - Day of the month as decimal 01 to 31
|
||||
- %j - Day of year as decimal from 001 to 366
|
||||
- %m - Month name as a decimal 01 to 12
|
||||
- %U - Week number 00 to 53 with first Sunday as the first day of week 1?
|
||||
- %w - Weekday as decimal number 0 to 6 where Sunday == 0
|
||||
- %W - Week number 00 to 53 where Monday is first day of week 1
|
||||
- %x - facet default date representation
|
||||
- %y - Year without the century - eg: 04 for 2004
|
||||
- %Y - Year with century
|
||||
|
||||
The weekday specifiers (%a and %A) do not add to the date construction,
|
||||
but they provide a way to skip over the weekday names for formats that
|
||||
provide them.
|
||||
|
||||
todo -- Another interesting feature that this approach could provide is
|
||||
an option to fill in any missing fields with the current values
|
||||
from the clock. So if you have %m-%d the parser would detect
|
||||
the missing year value and fill it in using the clock.
|
||||
|
||||
todo -- What to do with the %x. %x in the classic facet is just bad...
|
||||
|
||||
*/
|
||||
template<class date_type, typename charT>
|
||||
class format_date_parser
|
||||
{
|
||||
public:
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef std::basic_istringstream<charT> stringstream_type;
|
||||
typedef std::istreambuf_iterator<charT> stream_itr_type;
|
||||
typedef typename string_type::const_iterator const_itr;
|
||||
typedef typename date_type::year_type year_type;
|
||||
typedef typename date_type::month_type month_type;
|
||||
typedef typename date_type::day_type day_type;
|
||||
typedef typename date_type::duration_type duration_type;
|
||||
typedef typename date_type::day_of_week_type day_of_week_type;
|
||||
typedef typename date_type::day_of_year_type day_of_year_type;
|
||||
typedef string_parse_tree<charT> parse_tree_type;
|
||||
typedef typename parse_tree_type::parse_match_result_type match_results;
|
||||
typedef std::vector<std::basic_string<charT> > input_collection_type;
|
||||
|
||||
// TODO sv_parser uses its default constructor - write the others
|
||||
|
||||
format_date_parser(const string_type& format_str,
|
||||
const input_collection_type& month_short_names,
|
||||
const input_collection_type& month_long_names,
|
||||
const input_collection_type& weekday_short_names,
|
||||
const input_collection_type& weekday_long_names) :
|
||||
m_format(format_str),
|
||||
m_month_short_names(month_short_names, 1),
|
||||
m_month_long_names(month_long_names, 1),
|
||||
m_weekday_short_names(weekday_short_names),
|
||||
m_weekday_long_names(weekday_long_names)
|
||||
{}
|
||||
|
||||
format_date_parser(const string_type& format_str,
|
||||
const std::locale& locale) :
|
||||
m_format(format_str),
|
||||
m_month_short_names(gather_month_strings<charT>(locale), 1),
|
||||
m_month_long_names(gather_month_strings<charT>(locale, false), 1),
|
||||
m_weekday_short_names(gather_weekday_strings<charT>(locale)),
|
||||
m_weekday_long_names(gather_weekday_strings<charT>(locale, false))
|
||||
{}
|
||||
|
||||
format_date_parser(const format_date_parser<date_type,charT>& fdp)
|
||||
{
|
||||
this->m_format = fdp.m_format;
|
||||
this->m_month_short_names = fdp.m_month_short_names;
|
||||
this->m_month_long_names = fdp.m_month_long_names;
|
||||
this->m_weekday_short_names = fdp.m_weekday_short_names;
|
||||
this->m_weekday_long_names = fdp.m_weekday_long_names;
|
||||
}
|
||||
|
||||
string_type format() const
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
void format(string_type format_str)
|
||||
{
|
||||
m_format = format_str;
|
||||
}
|
||||
|
||||
void short_month_names(const input_collection_type& month_names)
|
||||
{
|
||||
m_month_short_names = parse_tree_type(month_names, 1);
|
||||
}
|
||||
void long_month_names(const input_collection_type& month_names)
|
||||
{
|
||||
m_month_long_names = parse_tree_type(month_names, 1);
|
||||
}
|
||||
void short_weekday_names(const input_collection_type& weekday_names)
|
||||
{
|
||||
m_weekday_short_names = parse_tree_type(weekday_names);
|
||||
}
|
||||
void long_weekday_names(const input_collection_type& weekday_names)
|
||||
{
|
||||
m_weekday_long_names = parse_tree_type(weekday_names);
|
||||
}
|
||||
|
||||
date_type
|
||||
parse_date(const string_type& value,
|
||||
const string_type& format_str,
|
||||
const special_values_parser<date_type,charT>& sv_parser) const
|
||||
{
|
||||
stringstream_type ss(value);
|
||||
stream_itr_type sitr(ss);
|
||||
stream_itr_type stream_end;
|
||||
return parse_date(sitr, stream_end, format_str, sv_parser);
|
||||
}
|
||||
|
||||
date_type
|
||||
parse_date(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
const special_values_parser<date_type,charT>& sv_parser) const
|
||||
{
|
||||
return parse_date(sitr, stream_end, m_format, sv_parser);
|
||||
}
|
||||
|
||||
/*! Of all the objects that the format_date_parser can parse, only a
|
||||
* date can be a special value. Therefore, only parse_date checks
|
||||
* for special_values. */
|
||||
date_type
|
||||
parse_date(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
string_type format_str,
|
||||
const special_values_parser<date_type,charT>& sv_parser) const
|
||||
{
|
||||
bool use_current_char = false;
|
||||
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
short year(0), month(0), day(0), day_of_year(0);// wkday(0);
|
||||
/* Initialized the following to their minimum values. These intermediate
|
||||
* objects are used so we get specific exceptions when part of the input
|
||||
* is unparsable.
|
||||
* Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/
|
||||
year_type t_year(1400);
|
||||
month_type t_month(1);
|
||||
day_type t_day(1);
|
||||
day_of_week_type wkday(0);
|
||||
|
||||
|
||||
const_itr itr(format_str.begin());
|
||||
while (itr != format_str.end() && (sitr != stream_end)) {
|
||||
if (*itr == '%') {
|
||||
itr++;
|
||||
if (*itr != '%') {
|
||||
switch(*itr) {
|
||||
case 'a':
|
||||
{
|
||||
//this value is just throw away. It could be used for
|
||||
//error checking potentially, but it isn't helpful in
|
||||
//actually constructing the date - we just need to get it
|
||||
//out of the stream
|
||||
match_results mr = m_weekday_short_names.match(sitr, stream_end);
|
||||
if(mr.current_match == match_results::PARSE_ERROR) {
|
||||
// check special_values
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
wkday = mr.current_match;
|
||||
if (mr.has_remaining()) {
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'A':
|
||||
{
|
||||
//this value is just throw away. It could be used for
|
||||
//error checking potentially, but it isn't helpful in
|
||||
//actually constructing the date - we just need to get it
|
||||
//out of the stream
|
||||
match_results mr = m_weekday_long_names.match(sitr, stream_end);
|
||||
if(mr.current_match == match_results::PARSE_ERROR) {
|
||||
// check special_values
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
wkday = mr.current_match;
|
||||
if (mr.has_remaining()) {
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
{
|
||||
match_results mr = m_month_short_names.match(sitr, stream_end);
|
||||
if(mr.current_match == match_results::PARSE_ERROR) {
|
||||
// check special_values
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
t_month = month_type(mr.current_match);
|
||||
if (mr.has_remaining()) {
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'B':
|
||||
{
|
||||
match_results mr = m_month_long_names.match(sitr, stream_end);
|
||||
if(mr.current_match == match_results::PARSE_ERROR) {
|
||||
// check special_values
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
t_month = month_type(mr.current_match);
|
||||
if (mr.has_remaining()) {
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
{
|
||||
match_results mr;
|
||||
day = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2);
|
||||
if(day == -1) {
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
t_day = day_type(day);
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
{
|
||||
match_results mr;
|
||||
day = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2, ' ');
|
||||
if(day == -1) {
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
t_day = day_type(day);
|
||||
break;
|
||||
}
|
||||
case 'j':
|
||||
{
|
||||
match_results mr;
|
||||
day_of_year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 3);
|
||||
if(day_of_year == -1) {
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
// these next two lines are so we get an exception with bad input
|
||||
day_of_year_type t_day_of_year(1);
|
||||
t_day_of_year = day_of_year_type(day_of_year);
|
||||
break;
|
||||
}
|
||||
case 'm':
|
||||
{
|
||||
match_results mr;
|
||||
month = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2);
|
||||
if(month == -1) {
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
t_month = month_type(month);
|
||||
break;
|
||||
}
|
||||
case 'Y':
|
||||
{
|
||||
match_results mr;
|
||||
year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 4);
|
||||
if(year == -1) {
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
t_year = year_type(year);
|
||||
break;
|
||||
}
|
||||
case 'y':
|
||||
{
|
||||
match_results mr;
|
||||
year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2);
|
||||
if(year == -1) {
|
||||
if(sv_parser.match(sitr, stream_end, mr)) {
|
||||
return date_type(static_cast<special_values>(mr.current_match));
|
||||
}
|
||||
}
|
||||
year += 2000; //make 2 digit years in this century
|
||||
t_year = year_type(year);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{} //ignore those we don't understand
|
||||
|
||||
}//switch
|
||||
|
||||
}
|
||||
else { // itr == '%', second consecutive
|
||||
sitr++;
|
||||
}
|
||||
|
||||
itr++; //advance past format specifier
|
||||
}
|
||||
else { //skip past chars in format and in buffer
|
||||
itr++;
|
||||
if (use_current_char) {
|
||||
use_current_char = false;
|
||||
}
|
||||
else {
|
||||
sitr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (day_of_year > 0) {
|
||||
date_type d(static_cast<unsigned short>(year-1),12,31); //end of prior year
|
||||
return d + duration_type(day_of_year);
|
||||
}
|
||||
|
||||
return date_type(t_year, t_month, t_day); // exceptions were thrown earlier
|
||||
// if input was no good
|
||||
}
|
||||
|
||||
//! Throws bad_month if unable to parse
|
||||
month_type
|
||||
parse_month(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
string_type format_str) const
|
||||
{
|
||||
match_results mr;
|
||||
return parse_month(sitr, stream_end, format_str, mr);
|
||||
}
|
||||
|
||||
//! Throws bad_month if unable to parse
|
||||
month_type
|
||||
parse_month(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
string_type format_str,
|
||||
match_results& mr) const
|
||||
{
|
||||
bool use_current_char = false;
|
||||
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
charT current_char = *sitr;
|
||||
|
||||
short month(0);
|
||||
|
||||
const_itr itr(format_str.begin());
|
||||
while (itr != format_str.end() && (sitr != stream_end)) {
|
||||
if (*itr == '%') {
|
||||
itr++;
|
||||
if (*itr != '%') {
|
||||
switch(*itr) {
|
||||
case 'b':
|
||||
{
|
||||
mr = m_month_short_names.match(sitr, stream_end);
|
||||
month = mr.current_match;
|
||||
if (mr.has_remaining()) {
|
||||
current_char = mr.last_char();
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'B':
|
||||
{
|
||||
mr = m_month_long_names.match(sitr, stream_end);
|
||||
month = mr.current_match;
|
||||
if (mr.has_remaining()) {
|
||||
current_char = mr.last_char();
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'm':
|
||||
{
|
||||
month = var_string_to_int<short, charT>(sitr, stream_end, 2);
|
||||
// var_string_to_int returns -1 if parse failed. That will
|
||||
// cause a bad_month exception to be thrown so we do nothing here
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{} //ignore those we don't understand
|
||||
|
||||
}//switch
|
||||
|
||||
}
|
||||
else { // itr == '%', second consecutive
|
||||
sitr++;
|
||||
}
|
||||
|
||||
itr++; //advance past format specifier
|
||||
}
|
||||
else { //skip past chars in format and in buffer
|
||||
itr++;
|
||||
if (use_current_char) {
|
||||
use_current_char = false;
|
||||
current_char = *sitr;
|
||||
}
|
||||
else {
|
||||
sitr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return month_type(month); // throws bad_month exception when values are zero
|
||||
}
|
||||
|
||||
//! Expects 1 or 2 digits 1-31. Throws bad_day_of_month if unable to parse
|
||||
day_type
|
||||
parse_var_day_of_month(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
return day_type(var_string_to_int<short, charT>(sitr, stream_end, 2));
|
||||
}
|
||||
//! Expects 2 digits 01-31. Throws bad_day_of_month if unable to parse
|
||||
day_type
|
||||
parse_day_of_month(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
//return day_type(var_string_to_int<short, charT>(sitr, stream_end, 2));
|
||||
match_results mr;
|
||||
return day_type(fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2));
|
||||
}
|
||||
|
||||
day_of_week_type
|
||||
parse_weekday(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
string_type format_str) const
|
||||
{
|
||||
match_results mr;
|
||||
return parse_weekday(sitr, stream_end, format_str, mr);
|
||||
}
|
||||
day_of_week_type
|
||||
parse_weekday(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
string_type format_str,
|
||||
match_results& mr) const
|
||||
{
|
||||
bool use_current_char = false;
|
||||
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
charT current_char = *sitr;
|
||||
|
||||
short wkday(0);
|
||||
|
||||
const_itr itr(format_str.begin());
|
||||
while (itr != format_str.end() && (sitr != stream_end)) {
|
||||
if (*itr == '%') {
|
||||
itr++;
|
||||
if (*itr != '%') {
|
||||
switch(*itr) {
|
||||
case 'a':
|
||||
{
|
||||
//this value is just throw away. It could be used for
|
||||
//error checking potentially, but it isn't helpful in
|
||||
//actually constructing the date - we just need to get it
|
||||
//out of the stream
|
||||
mr = m_weekday_short_names.match(sitr, stream_end);
|
||||
wkday = mr.current_match;
|
||||
if (mr.has_remaining()) {
|
||||
current_char = mr.last_char();
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'A':
|
||||
{
|
||||
//this value is just throw away. It could be used for
|
||||
//error checking potentially, but it isn't helpful in
|
||||
//actually constructing the date - we just need to get it
|
||||
//out of the stream
|
||||
mr = m_weekday_long_names.match(sitr, stream_end);
|
||||
wkday = mr.current_match;
|
||||
if (mr.has_remaining()) {
|
||||
current_char = mr.last_char();
|
||||
use_current_char = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'w':
|
||||
{
|
||||
// weekday as number 0-6, Sunday == 0
|
||||
wkday = var_string_to_int<short, charT>(sitr, stream_end, 2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{} //ignore those we don't understand
|
||||
|
||||
}//switch
|
||||
|
||||
}
|
||||
else { // itr == '%', second consecutive
|
||||
sitr++;
|
||||
}
|
||||
|
||||
itr++; //advance past format specifier
|
||||
}
|
||||
else { //skip past chars in format and in buffer
|
||||
itr++;
|
||||
if (use_current_char) {
|
||||
use_current_char = false;
|
||||
current_char = *sitr;
|
||||
}
|
||||
else {
|
||||
sitr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return day_of_week_type(wkday); // throws bad_day_of_month exception
|
||||
// when values are zero
|
||||
}
|
||||
|
||||
//! throws bad_year if unable to parse
|
||||
year_type
|
||||
parse_year(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
string_type format_str) const
|
||||
{
|
||||
match_results mr;
|
||||
return parse_year(sitr, stream_end, format_str, mr);
|
||||
}
|
||||
|
||||
//! throws bad_year if unable to parse
|
||||
year_type
|
||||
parse_year(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
string_type format_str,
|
||||
match_results& mr) const
|
||||
{
|
||||
bool use_current_char = false;
|
||||
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
charT current_char = *sitr;
|
||||
|
||||
unsigned short year(0);
|
||||
|
||||
const_itr itr(format_str.begin());
|
||||
while (itr != format_str.end() && (sitr != stream_end)) {
|
||||
if (*itr == '%') {
|
||||
itr++;
|
||||
if (*itr != '%') {
|
||||
//match_results mr;
|
||||
switch(*itr) {
|
||||
case 'Y':
|
||||
{
|
||||
// year from 4 digit string
|
||||
year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 4);
|
||||
break;
|
||||
}
|
||||
case 'y':
|
||||
{
|
||||
// year from 2 digit string (no century)
|
||||
year = fixed_string_to_int<short, charT>(sitr, stream_end, mr, 2);
|
||||
year += 2000; //make 2 digit years in this century
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{} //ignore those we don't understand
|
||||
|
||||
}//switch
|
||||
|
||||
}
|
||||
else { // itr == '%', second consecutive
|
||||
sitr++;
|
||||
}
|
||||
|
||||
itr++; //advance past format specifier
|
||||
}
|
||||
else { //skip past chars in format and in buffer
|
||||
itr++;
|
||||
if (use_current_char) {
|
||||
use_current_char = false;
|
||||
current_char = *sitr;
|
||||
}
|
||||
else {
|
||||
sitr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return year_type(year); // throws bad_year exception when values are zero
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
string_type m_format;
|
||||
parse_tree_type m_month_short_names;
|
||||
parse_tree_type m_month_long_names;
|
||||
parse_tree_type m_weekday_short_names;
|
||||
parse_tree_type m_weekday_long_names;
|
||||
|
||||
};
|
||||
|
||||
} } //namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
38
cpp/BoostParts/boost/date_time/gregorian/gregorian.hpp
Normal file
38
cpp/BoostParts/boost/date_time/gregorian/gregorian.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef GREGORIAN_HPP__
|
||||
#define GREGORIAN_HPP__
|
||||
|
||||
/* Copyright (c) 2002-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $
|
||||
*/
|
||||
|
||||
/*! @file gregorian.hpp
|
||||
Single file header that provides overall include for all elements of
|
||||
the gregorian date-time system. This includes the various types
|
||||
defined, but also other functions for formatting and parsing.
|
||||
*/
|
||||
|
||||
|
||||
#include "boost/date_time/compiler_config.hpp"
|
||||
#include "boost/date_time/gregorian/gregorian_types.hpp"
|
||||
#include "boost/date_time/gregorian/conversion.hpp"
|
||||
#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS)
|
||||
#include "boost/date_time/gregorian/formatters_limited.hpp"
|
||||
#else
|
||||
#include "boost/date_time/gregorian/formatters.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO)
|
||||
#include "boost/date_time/gregorian/greg_facet.hpp"
|
||||
#else
|
||||
#include "boost/date_time/gregorian/gregorian_io.hpp"
|
||||
#endif // USE_DATE_TIME_PRE_1_33_FACET_IO
|
||||
|
||||
#include "boost/date_time/gregorian/parsers.hpp"
|
||||
|
||||
|
||||
|
||||
#endif
|
784
cpp/BoostParts/boost/date_time/gregorian/gregorian_io.hpp
Normal file
784
cpp/BoostParts/boost/date_time/gregorian/gregorian_io.hpp
Normal file
@ -0,0 +1,784 @@
|
||||
#ifndef DATE_TIME_GREGORIAN_IO_HPP__
|
||||
#define DATE_TIME_GREGORIAN_IO_HPP__
|
||||
|
||||
/* Copyright (c) 2004-2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-11-12 11:37:53 -0800 (Wed, 12 Nov 2008) $
|
||||
*/
|
||||
|
||||
#include <locale>
|
||||
#include <iostream>
|
||||
#include <iterator> // i/ostreambuf_iterator
|
||||
#include <boost/io/ios_state.hpp>
|
||||
#include <boost/date_time/date_facet.hpp>
|
||||
#include <boost/date_time/period_parser.hpp>
|
||||
#include <boost/date_time/period_formatter.hpp>
|
||||
#include <boost/date_time/special_values_parser.hpp>
|
||||
#include <boost/date_time/special_values_formatter.hpp>
|
||||
#include <boost/date_time/gregorian/gregorian_types.hpp>
|
||||
#include <boost/date_time/gregorian/conversion.hpp> // to_tm will be needed in the facets
|
||||
|
||||
namespace boost {
|
||||
namespace gregorian {
|
||||
|
||||
|
||||
typedef boost::date_time::period_formatter<wchar_t> wperiod_formatter;
|
||||
typedef boost::date_time::period_formatter<char> period_formatter;
|
||||
|
||||
typedef boost::date_time::date_facet<date,wchar_t> wdate_facet;
|
||||
typedef boost::date_time::date_facet<date,char> date_facet;
|
||||
|
||||
typedef boost::date_time::period_parser<date,char> period_parser;
|
||||
typedef boost::date_time::period_parser<date,wchar_t> wperiod_parser;
|
||||
|
||||
typedef boost::date_time::special_values_formatter<char> special_values_formatter;
|
||||
typedef boost::date_time::special_values_formatter<wchar_t> wspecial_values_formatter;
|
||||
|
||||
typedef boost::date_time::special_values_parser<date,char> special_values_parser;
|
||||
typedef boost::date_time::special_values_parser<date,wchar_t> wspecial_values_parser;
|
||||
|
||||
typedef boost::date_time::date_input_facet<date,char> date_input_facet;
|
||||
typedef boost::date_time::date_input_facet<date,wchar_t> wdate_input_facet;
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::date& d) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), d);
|
||||
else {
|
||||
//instantiate a custom facet for dealing with dates since the user
|
||||
//has not put one in the stream so far. This is for efficiency
|
||||
//since we would always need to reconstruct for every date
|
||||
//if the locale did not already exist. Of course this will be overridden
|
||||
//if the user imbues at some later point. With the default settings
|
||||
//for the facet the resulting format will be the same as the
|
||||
//std::time_facet settings.
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), d);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for date
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, date& d)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, d);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, d);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
// mask tells us what exceptions are turned on
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
// if the user wants exceptions on failbit, we'll rethrow our
|
||||
// date_time exception & set the failbit
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {} // ignore this one
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
// if the user want's to fail quietly, we simply set the failbit
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::date_duration& dd) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), dd);
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), dd);
|
||||
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for date_duration
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, date_duration& dd)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, dd);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, dd);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::date_period& dp) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), dp);
|
||||
else {
|
||||
//instantiate a custom facet for dealing with date periods since the user
|
||||
//has not put one in the stream so far. This is for efficiency
|
||||
//since we would always need to reconstruct for every time period
|
||||
//if the local did not already exist. Of course this will be overridden
|
||||
//if the user imbues at some later point. With the default settings
|
||||
//for the facet the resulting format will be the same as the
|
||||
//std::time_facet settings.
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), dp);
|
||||
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for date_period
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, date_period& dp)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, dp);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, dp);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
/********** small gregorian types **********/
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::greg_month& gm) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), gm);
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();//-> 10/1074199752/32 because year & day not initialized in put(...)
|
||||
//custom_date_facet* f = new custom_date_facet("%B");
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), gm);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for greg_month
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, greg_month& m)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, m);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, m);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::greg_weekday& gw) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), gw);
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), gw);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for greg_weekday
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, greg_weekday& wd)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, wd);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, wd);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
//NOTE: output operator for greg_day was not necessary
|
||||
|
||||
//! input operator for greg_day
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, greg_day& gd)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, gd);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, gd);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
//NOTE: output operator for greg_year was not necessary
|
||||
|
||||
//! input operator for greg_year
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, greg_year& gy)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, gy);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, gy);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
/********** date generator types **********/
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::partial_date& pd) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), pd);
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), pd);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for partial_date
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is, partial_date& pd)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, pd);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, pd);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::nth_day_of_the_week_in_month& nkd) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), nkd);
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), nkd);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for nth_day_of_the_week_in_month
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is,
|
||||
nth_day_of_the_week_in_month& nday)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, nday);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, nday);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::first_day_of_the_week_in_month& fkd) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), fkd);
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), fkd);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for first_day_of_the_week_in_month
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is,
|
||||
first_day_of_the_week_in_month& fkd)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, fkd);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, fkd);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::last_day_of_the_week_in_month& lkd) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc()))
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), lkd);
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), lkd);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for last_day_of_the_week_in_month
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is,
|
||||
last_day_of_the_week_in_month& lkd)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, lkd);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, lkd);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::first_day_of_the_week_after& fda) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc())) {
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), fda);
|
||||
}
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), fda);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for first_day_of_the_week_after
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is,
|
||||
first_day_of_the_week_after& fka)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, fka);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, fka);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template <class CharT, class TraitsT>
|
||||
inline std::basic_ostream<CharT, TraitsT>&
|
||||
operator<<(std::basic_ostream<CharT, TraitsT>& os, const boost::gregorian::first_day_of_the_week_before& fdb) {
|
||||
boost::io::ios_flags_saver iflags(os);
|
||||
typedef boost::date_time::date_facet<date, CharT> custom_date_facet;
|
||||
std::ostreambuf_iterator<CharT> output_itr(os);
|
||||
if (std::has_facet<custom_date_facet>(os.getloc())) {
|
||||
std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), fdb);
|
||||
}
|
||||
else {
|
||||
custom_date_facet* f = new custom_date_facet();
|
||||
std::locale l = std::locale(os.getloc(), f);
|
||||
os.imbue(l);
|
||||
f->put(output_itr, os, os.fill(), fdb);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
//! input operator for first_day_of_the_week_before
|
||||
template <class CharT, class Traits>
|
||||
inline
|
||||
std::basic_istream<CharT, Traits>&
|
||||
operator>>(std::basic_istream<CharT, Traits>& is,
|
||||
first_day_of_the_week_before& fkb)
|
||||
{
|
||||
boost::io::ios_flags_saver iflags(is);
|
||||
typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
|
||||
if (strm_sentry) {
|
||||
try {
|
||||
typedef typename date_time::date_input_facet<date, CharT> date_input_facet;
|
||||
|
||||
std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
|
||||
if(std::has_facet<date_input_facet>(is.getloc())) {
|
||||
std::use_facet<date_input_facet>(is.getloc()).get(sit, str_end, is, fkb);
|
||||
}
|
||||
else {
|
||||
date_input_facet* f = new date_input_facet();
|
||||
std::locale l = std::locale(is.getloc(), f);
|
||||
is.imbue(l);
|
||||
f->get(sit, str_end, is, fkb);
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
std::ios_base::iostate exception_mask = is.exceptions();
|
||||
if(std::ios_base::failbit & exception_mask) {
|
||||
try { is.setstate(std::ios_base::failbit); }
|
||||
catch(std::ios_base::failure&) {}
|
||||
throw; // rethrow original exception
|
||||
}
|
||||
else {
|
||||
is.setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
} } // namespaces
|
||||
|
||||
#endif // DATE_TIME_GREGORIAN_IO_HPP__
|
196
cpp/BoostParts/boost/date_time/period_formatter.hpp
Normal file
196
cpp/BoostParts/boost/date_time/period_formatter.hpp
Normal file
@ -0,0 +1,196 @@
|
||||
|
||||
#ifndef DATETIME_PERIOD_FORMATTER_HPP___
|
||||
#define DATETIME_PERIOD_FORMATTER_HPP___
|
||||
|
||||
/* Copyright (c) 2002-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2012-09-22 15:33:33 -0700 (Sat, 22 Sep 2012) $
|
||||
*/
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
|
||||
//! Not a facet, but a class used to specify and control period formats
|
||||
/*! Provides settings for the following:
|
||||
* - period_separator -- default '/'
|
||||
* - period_open_start_delimeter -- default '['
|
||||
* - period_open_range_end_delimeter -- default ')'
|
||||
* - period_closed_range_end_delimeter -- default ']'
|
||||
* - display_as_open_range, display_as_closed_range -- default closed_range
|
||||
*
|
||||
* Thus the default formatting for a period is as follows:
|
||||
*@code
|
||||
* [period.start()/period.last()]
|
||||
*@endcode
|
||||
* So for a typical date_period this would be
|
||||
*@code
|
||||
* [2004-Jan-04/2004-Feb-01]
|
||||
*@endcode
|
||||
* where the date formatting is controlled by the date facet
|
||||
*/
|
||||
template <class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
|
||||
class period_formatter {
|
||||
public:
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
typedef CharT char_type;
|
||||
typedef typename std::basic_string<char_type>::const_iterator const_itr_type;
|
||||
typedef std::vector<std::basic_string<CharT> > collection_type;
|
||||
|
||||
static const char_type default_period_separator[2];
|
||||
static const char_type default_period_start_delimeter[2];
|
||||
static const char_type default_period_open_range_end_delimeter[2];
|
||||
static const char_type default_period_closed_range_end_delimeter[2];
|
||||
|
||||
enum range_display_options { AS_OPEN_RANGE, AS_CLOSED_RANGE };
|
||||
|
||||
//! Constructor that sets up period formatter options -- default should suffice most cases.
|
||||
period_formatter(range_display_options range_option_in = AS_CLOSED_RANGE,
|
||||
const char_type* const period_separator = default_period_separator,
|
||||
const char_type* const period_start_delimeter = default_period_start_delimeter,
|
||||
const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter,
|
||||
const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) :
|
||||
m_range_option(range_option_in),
|
||||
m_period_separator(period_separator),
|
||||
m_period_start_delimeter(period_start_delimeter),
|
||||
m_open_range_end_delimeter(period_open_range_end_delimeter),
|
||||
m_closed_range_end_delimeter(period_closed_range_end_delimeter)
|
||||
{}
|
||||
|
||||
//! Puts the characters between period elements into stream -- default is /
|
||||
OutItrT put_period_separator(OutItrT& oitr) const
|
||||
{
|
||||
const_itr_type ci = m_period_separator.begin();
|
||||
while (ci != m_period_separator.end()) {
|
||||
*oitr = *ci;
|
||||
ci++;
|
||||
}
|
||||
return oitr;
|
||||
}
|
||||
|
||||
//! Puts the period start characters into stream -- default is [
|
||||
OutItrT put_period_start_delimeter(OutItrT& oitr) const
|
||||
{
|
||||
const_itr_type ci = m_period_start_delimeter.begin();
|
||||
while (ci != m_period_start_delimeter.end()) {
|
||||
*oitr = *ci;
|
||||
ci++;
|
||||
}
|
||||
return oitr;
|
||||
}
|
||||
|
||||
//! Puts the period end characters into stream as controled by open/closed range setting.
|
||||
OutItrT put_period_end_delimeter(OutItrT& oitr) const
|
||||
{
|
||||
|
||||
const_itr_type ci, end;
|
||||
if (m_range_option == AS_OPEN_RANGE) {
|
||||
ci = m_open_range_end_delimeter.begin();
|
||||
end = m_open_range_end_delimeter.end();
|
||||
}
|
||||
else {
|
||||
ci = m_closed_range_end_delimeter.begin();
|
||||
end = m_closed_range_end_delimeter.end();
|
||||
}
|
||||
while (ci != end) {
|
||||
*oitr = *ci;
|
||||
ci++;
|
||||
}
|
||||
return oitr;
|
||||
}
|
||||
|
||||
range_display_options range_option() const
|
||||
{
|
||||
return m_range_option;
|
||||
}
|
||||
|
||||
//! Reset the range_option control
|
||||
void
|
||||
range_option(range_display_options option) const
|
||||
{
|
||||
m_range_option = option;
|
||||
}
|
||||
void delimiter_strings(const string_type& ,
|
||||
const string_type& ,
|
||||
const string_type& ,
|
||||
const string_type& )
|
||||
{
|
||||
m_period_separator;
|
||||
m_period_start_delimeter;
|
||||
m_open_range_end_delimeter;
|
||||
m_closed_range_end_delimeter;
|
||||
}
|
||||
|
||||
|
||||
//! Generic code to output a period -- no matter the period type.
|
||||
/*! This generic code will output any period using a facet to
|
||||
* to output the 'elements'. For example, in the case of a date_period
|
||||
* the elements will be instances of a date which will be formatted
|
||||
* according the to setup in the passed facet parameter.
|
||||
*
|
||||
* The steps for formatting a period are always the same:
|
||||
* - put the start delimiter
|
||||
* - put start element
|
||||
* - put the separator
|
||||
* - put either last or end element depending on range settings
|
||||
* - put end delimeter depending on range settings
|
||||
*
|
||||
* Thus for a typical date period the result might look like this:
|
||||
*@code
|
||||
*
|
||||
* [March 01, 2004/June 07, 2004] <-- closed range
|
||||
* [March 01, 2004/June 08, 2004) <-- open range
|
||||
*
|
||||
*@endcode
|
||||
*/
|
||||
template<class period_type, class facet_type>
|
||||
OutItrT put_period(OutItrT next,
|
||||
std::ios_base& a_ios,
|
||||
char_type a_fill,
|
||||
const period_type& p,
|
||||
const facet_type& facet) const {
|
||||
put_period_start_delimeter(next);
|
||||
next = facet.put(next, a_ios, a_fill, p.begin());
|
||||
put_period_separator(next);
|
||||
if (m_range_option == AS_CLOSED_RANGE) {
|
||||
facet.put(next, a_ios, a_fill, p.last());
|
||||
}
|
||||
else {
|
||||
facet.put(next, a_ios, a_fill, p.end());
|
||||
}
|
||||
put_period_end_delimeter(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
range_display_options m_range_option;
|
||||
string_type m_period_separator;
|
||||
string_type m_period_start_delimeter;
|
||||
string_type m_open_range_end_delimeter;
|
||||
string_type m_closed_range_end_delimeter;
|
||||
};
|
||||
|
||||
template <class CharT, class OutItrT>
|
||||
const typename period_formatter<CharT, OutItrT>::char_type
|
||||
period_formatter<CharT, OutItrT>::default_period_separator[2] = {'/'};
|
||||
|
||||
template <class CharT, class OutItrT>
|
||||
const typename period_formatter<CharT, OutItrT>::char_type
|
||||
period_formatter<CharT, OutItrT>::default_period_start_delimeter[2] = {'['};
|
||||
|
||||
template <class CharT, class OutItrT>
|
||||
const typename period_formatter<CharT, OutItrT>::char_type
|
||||
period_formatter<CharT, OutItrT>::default_period_open_range_end_delimeter[2] = {')'};
|
||||
|
||||
template <class CharT, class OutItrT>
|
||||
const typename period_formatter<CharT, OutItrT>::char_type
|
||||
period_formatter<CharT, OutItrT>::default_period_closed_range_end_delimeter[2] = {']'};
|
||||
|
||||
} } //namespace boost::date_time
|
||||
|
||||
#endif
|
198
cpp/BoostParts/boost/date_time/period_parser.hpp
Normal file
198
cpp/BoostParts/boost/date_time/period_parser.hpp
Normal file
@ -0,0 +1,198 @@
|
||||
|
||||
#ifndef DATETIME_PERIOD_PARSER_HPP___
|
||||
#define DATETIME_PERIOD_PARSER_HPP___
|
||||
|
||||
/* Copyright (c) 2002-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-11-13 12:10:23 -0800 (Thu, 13 Nov 2008) $
|
||||
*/
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/date_time/string_parse_tree.hpp>
|
||||
#include <boost/date_time/string_convert.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
|
||||
//! Not a facet, but a class used to specify and control period parsing
|
||||
/*! Provides settings for the following:
|
||||
* - period_separator -- default '/'
|
||||
* - period_open_start_delimeter -- default '['
|
||||
* - period_open_range_end_delimeter -- default ')'
|
||||
* - period_closed_range_end_delimeter -- default ']'
|
||||
* - display_as_open_range, display_as_closed_range -- default closed_range
|
||||
*
|
||||
* For a typical date_period, the contents of the input stream would be
|
||||
*@code
|
||||
* [2004-Jan-04/2004-Feb-01]
|
||||
*@endcode
|
||||
* where the date format is controlled by the date facet
|
||||
*/
|
||||
template<class date_type, typename CharT>
|
||||
class period_parser {
|
||||
public:
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
typedef CharT char_type;
|
||||
//typedef typename std::basic_string<char_type>::const_iterator const_itr_type;
|
||||
typedef std::istreambuf_iterator<CharT> stream_itr_type;
|
||||
typedef string_parse_tree<CharT> parse_tree_type;
|
||||
typedef typename parse_tree_type::parse_match_result_type match_results;
|
||||
typedef std::vector<std::basic_string<CharT> > collection_type;
|
||||
|
||||
static const char_type default_period_separator[2];
|
||||
static const char_type default_period_start_delimeter[2];
|
||||
static const char_type default_period_open_range_end_delimeter[2];
|
||||
static const char_type default_period_closed_range_end_delimeter[2];
|
||||
|
||||
enum period_range_option { AS_OPEN_RANGE, AS_CLOSED_RANGE };
|
||||
|
||||
//! Constructor that sets up period parser options
|
||||
period_parser(period_range_option range_opt = AS_CLOSED_RANGE,
|
||||
const char_type* const period_separator = default_period_separator,
|
||||
const char_type* const period_start_delimeter = default_period_start_delimeter,
|
||||
const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter,
|
||||
const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter)
|
||||
: m_range_option(range_opt)
|
||||
{
|
||||
delimiters.push_back(string_type(period_separator));
|
||||
delimiters.push_back(string_type(period_start_delimeter));
|
||||
delimiters.push_back(string_type(period_open_range_end_delimeter));
|
||||
delimiters.push_back(string_type(period_closed_range_end_delimeter));
|
||||
}
|
||||
|
||||
period_parser(const period_parser<date_type,CharT>& p_parser)
|
||||
{
|
||||
this->delimiters = p_parser.delimiters;
|
||||
this->m_range_option = p_parser.m_range_option;
|
||||
}
|
||||
|
||||
period_range_option range_option() const
|
||||
{
|
||||
return m_range_option;
|
||||
}
|
||||
void range_option(period_range_option option)
|
||||
{
|
||||
m_range_option = option;
|
||||
}
|
||||
collection_type delimiter_strings() const
|
||||
{
|
||||
return delimiters;
|
||||
}
|
||||
void delimiter_strings(const string_type& separator,
|
||||
const string_type& start_delim,
|
||||
const string_type& open_end_delim,
|
||||
const string_type& closed_end_delim)
|
||||
{
|
||||
delimiters.clear();
|
||||
delimiters.push_back(separator);
|
||||
delimiters.push_back(start_delim);
|
||||
delimiters.push_back(open_end_delim);
|
||||
delimiters.push_back(closed_end_delim);
|
||||
}
|
||||
|
||||
//! Generic code to parse a period -- no matter the period type.
|
||||
/*! This generic code will parse any period using a facet to
|
||||
* to get the 'elements'. For example, in the case of a date_period
|
||||
* the elements will be instances of a date which will be parsed
|
||||
* according the to setup in the passed facet parameter.
|
||||
*
|
||||
* The steps for parsing a period are always the same:
|
||||
* - consume the start delimiter
|
||||
* - get start element
|
||||
* - consume the separator
|
||||
* - get either last or end element depending on range settings
|
||||
* - consume the end delimeter depending on range settings
|
||||
*
|
||||
* Thus for a typical date period the contents of the input stream
|
||||
* might look like this:
|
||||
*@code
|
||||
*
|
||||
* [March 01, 2004/June 07, 2004] <-- closed range
|
||||
* [March 01, 2004/June 08, 2004) <-- open range
|
||||
*
|
||||
*@endcode
|
||||
*/
|
||||
template<class period_type, class duration_type, class facet_type>
|
||||
period_type get_period(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
std::ios_base& a_ios,
|
||||
const period_type& /* p */,
|
||||
const duration_type& dur_unit,
|
||||
const facet_type& facet) const
|
||||
{
|
||||
// skip leading whitespace
|
||||
while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
|
||||
|
||||
typedef typename period_type::point_type point_type;
|
||||
point_type p1(not_a_date_time), p2(not_a_date_time);
|
||||
|
||||
|
||||
consume_delim(sitr, stream_end, delimiters[START]); // start delim
|
||||
facet.get(sitr, stream_end, a_ios, p1); // first point
|
||||
consume_delim(sitr, stream_end, delimiters[SEPARATOR]); // separator
|
||||
facet.get(sitr, stream_end, a_ios, p2); // second point
|
||||
|
||||
// period construction parameters are always open range [begin, end)
|
||||
if (m_range_option == AS_CLOSED_RANGE) {
|
||||
consume_delim(sitr, stream_end, delimiters[CLOSED_END]);// end delim
|
||||
// add 1 duration unit to p2 to make range open
|
||||
p2 += dur_unit;
|
||||
}
|
||||
else {
|
||||
consume_delim(sitr, stream_end, delimiters[OPEN_END]); // end delim
|
||||
}
|
||||
|
||||
return period_type(p1, p2);
|
||||
}
|
||||
|
||||
private:
|
||||
collection_type delimiters;
|
||||
period_range_option m_range_option;
|
||||
|
||||
enum delim_ids { SEPARATOR, START, OPEN_END, CLOSED_END };
|
||||
|
||||
//! throws ios_base::failure if delimiter and parsed data do not match
|
||||
void consume_delim(stream_itr_type& sitr,
|
||||
stream_itr_type& stream_end,
|
||||
const string_type& delim) const
|
||||
{
|
||||
/* string_parse_tree will not parse a string of punctuation characters
|
||||
* without knowing exactly how many characters to process
|
||||
* Ex [2000. Will not parse out the '[' string without knowing
|
||||
* to process only one character. By using length of the delimiter
|
||||
* string we can safely iterate past it. */
|
||||
string_type s;
|
||||
for(unsigned int i = 0; i < delim.length() && sitr != stream_end; ++i) {
|
||||
s += *sitr;
|
||||
++sitr;
|
||||
}
|
||||
if(s != delim) {
|
||||
boost::throw_exception(std::ios_base::failure("Parse failed. Expected '"
|
||||
+ convert_string_type<char_type,char>(delim) + "' but found '" + convert_string_type<char_type,char>(s) + "'"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class date_type, class char_type>
|
||||
const typename period_parser<date_type, char_type>::char_type
|
||||
period_parser<date_type, char_type>::default_period_separator[2] = {'/'};
|
||||
|
||||
template <class date_type, class char_type>
|
||||
const typename period_parser<date_type, char_type>::char_type
|
||||
period_parser<date_type, char_type>::default_period_start_delimeter[2] = {'['};
|
||||
|
||||
template <class date_type, class char_type>
|
||||
const typename period_parser<date_type, char_type>::char_type
|
||||
period_parser<date_type, char_type>::default_period_open_range_end_delimeter[2] = {')'};
|
||||
|
||||
template <class date_type, class char_type>
|
||||
const typename period_parser<date_type, char_type>::char_type
|
||||
period_parser<date_type, char_type>::default_period_closed_range_end_delimeter[2] = {']'};
|
||||
|
||||
} } //namespace boost::date_time
|
||||
|
||||
#endif // DATETIME_PERIOD_PARSER_HPP___
|
289
cpp/BoostParts/boost/date_time/posix_time/time_formatters.hpp
Normal file
289
cpp/BoostParts/boost/date_time/posix_time/time_formatters.hpp
Normal file
@ -0,0 +1,289 @@
|
||||
#ifndef POSIXTIME_FORMATTERS_HPP___
|
||||
#define POSIXTIME_FORMATTERS_HPP___
|
||||
|
||||
/* Copyright (c) 2002-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2010-01-10 11:17:23 -0800 (Sun, 10 Jan 2010) $
|
||||
*/
|
||||
|
||||
#include <boost/date_time/gregorian/gregorian.hpp>
|
||||
#include <boost/date_time/compiler_config.hpp>
|
||||
#include <boost/date_time/iso_format.hpp>
|
||||
#include <boost/date_time/date_format_simple.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/date_time/time_formatting_streams.hpp>
|
||||
#include <boost/date_time/time_resolution_traits.hpp> // absolute_value
|
||||
#include <boost/date_time/time_parsing.hpp>
|
||||
|
||||
/* NOTE: The "to_*_string" code for older compilers, ones that define
|
||||
* BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in
|
||||
* formatters_limited.hpp
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace posix_time {
|
||||
|
||||
// template function called by wrapper functions:
|
||||
// to_*_string(time_duration) & to_*_wstring(time_duration)
|
||||
template<class charT>
|
||||
inline std::basic_string<charT> to_simple_string_type(time_duration td) {
|
||||
std::basic_ostringstream<charT> ss;
|
||||
if(td.is_special()) {
|
||||
/* simply using 'ss << td.get_rep()' won't work on compilers
|
||||
* that don't support locales. This way does. */
|
||||
// switch copied from date_names_put.hpp
|
||||
switch(td.get_rep().as_special())
|
||||
{
|
||||
case not_a_date_time:
|
||||
//ss << "not-a-number";
|
||||
ss << "not-a-date-time";
|
||||
break;
|
||||
case pos_infin:
|
||||
ss << "+infinity";
|
||||
break;
|
||||
case neg_infin:
|
||||
ss << "-infinity";
|
||||
break;
|
||||
default:
|
||||
ss << "";
|
||||
}
|
||||
}
|
||||
else {
|
||||
charT fill_char = '0';
|
||||
if(td.is_negative()) {
|
||||
ss << '-';
|
||||
}
|
||||
ss << std::setw(2) << std::setfill(fill_char)
|
||||
<< date_time::absolute_value(td.hours()) << ":";
|
||||
ss << std::setw(2) << std::setfill(fill_char)
|
||||
<< date_time::absolute_value(td.minutes()) << ":";
|
||||
ss << std::setw(2) << std::setfill(fill_char)
|
||||
<< date_time::absolute_value(td.seconds());
|
||||
//TODO the following is totally non-generic, yelling FIXME
|
||||
#if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
|
||||
boost::int64_t frac_sec =
|
||||
date_time::absolute_value(td.fractional_seconds());
|
||||
// JDG [7/6/02 VC++ compatibility]
|
||||
charT buff[32];
|
||||
_i64toa(frac_sec, buff, 10);
|
||||
#else
|
||||
time_duration::fractional_seconds_type frac_sec =
|
||||
date_time::absolute_value(td.fractional_seconds());
|
||||
#endif
|
||||
if (frac_sec != 0) {
|
||||
ss << "." << std::setw(time_duration::num_fractional_digits())
|
||||
<< std::setfill(fill_char)
|
||||
|
||||
// JDG [7/6/02 VC++ compatibility]
|
||||
#if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
|
||||
<< buff;
|
||||
#else
|
||||
<< frac_sec;
|
||||
#endif
|
||||
}
|
||||
}// else
|
||||
return ss.str();
|
||||
}
|
||||
//! Time duration to string -hh::mm::ss.fffffff. Example: 10:09:03.0123456
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::string to_simple_string(time_duration td) {
|
||||
return to_simple_string_type<char>(td);
|
||||
}
|
||||
|
||||
|
||||
// template function called by wrapper functions:
|
||||
// to_*_string(time_duration) & to_*_wstring(time_duration)
|
||||
template<class charT>
|
||||
inline std::basic_string<charT> to_iso_string_type(time_duration td)
|
||||
{
|
||||
std::basic_ostringstream<charT> ss;
|
||||
if(td.is_special()) {
|
||||
/* simply using 'ss << td.get_rep()' won't work on compilers
|
||||
* that don't support locales. This way does. */
|
||||
// switch copied from date_names_put.hpp
|
||||
switch(td.get_rep().as_special()) {
|
||||
case not_a_date_time:
|
||||
//ss << "not-a-number";
|
||||
ss << "not-a-date-time";
|
||||
break;
|
||||
case pos_infin:
|
||||
ss << "+infinity";
|
||||
break;
|
||||
case neg_infin:
|
||||
ss << "-infinity";
|
||||
break;
|
||||
default:
|
||||
ss << "";
|
||||
}
|
||||
}
|
||||
else {
|
||||
charT fill_char = '0';
|
||||
if(td.is_negative()) {
|
||||
ss << '-';
|
||||
}
|
||||
ss << std::setw(2) << std::setfill(fill_char)
|
||||
<< date_time::absolute_value(td.hours());
|
||||
ss << std::setw(2) << std::setfill(fill_char)
|
||||
<< date_time::absolute_value(td.minutes());
|
||||
ss << std::setw(2) << std::setfill(fill_char)
|
||||
<< date_time::absolute_value(td.seconds());
|
||||
//TODO the following is totally non-generic, yelling FIXME
|
||||
#if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
|
||||
boost::int64_t frac_sec =
|
||||
date_time::absolute_value(td.fractional_seconds());
|
||||
// JDG [7/6/02 VC++ compatibility]
|
||||
charT buff[32];
|
||||
_i64toa(frac_sec, buff, 10);
|
||||
#else
|
||||
time_duration::fractional_seconds_type frac_sec =
|
||||
date_time::absolute_value(td.fractional_seconds());
|
||||
#endif
|
||||
if (frac_sec != 0) {
|
||||
ss << "." << std::setw(time_duration::num_fractional_digits())
|
||||
<< std::setfill(fill_char)
|
||||
|
||||
// JDG [7/6/02 VC++ compatibility]
|
||||
#if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
|
||||
<< buff;
|
||||
#else
|
||||
<< frac_sec;
|
||||
#endif
|
||||
}
|
||||
}// else
|
||||
return ss.str();
|
||||
}
|
||||
//! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::string to_iso_string(time_duration td){
|
||||
return to_iso_string_type<char>(td);
|
||||
}
|
||||
|
||||
//! Time to simple format CCYY-mmm-dd hh:mm:ss.fffffff
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
template<class charT>
|
||||
inline std::basic_string<charT> to_simple_string_type(ptime t)
|
||||
{
|
||||
// can't use this w/gcc295, no to_simple_string_type<>(td) available
|
||||
std::basic_string<charT> ts = gregorian::to_simple_string_type<charT>(t.date());// + " ";
|
||||
if(!t.time_of_day().is_special()) {
|
||||
charT space = ' ';
|
||||
return ts + space + to_simple_string_type<charT>(t.time_of_day());
|
||||
}
|
||||
else {
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
inline std::string to_simple_string(ptime t){
|
||||
return to_simple_string_type<char>(t);
|
||||
}
|
||||
|
||||
// function called by wrapper functions to_*_string(time_period)
|
||||
// & to_*_wstring(time_period)
|
||||
template<class charT>
|
||||
inline std::basic_string<charT> to_simple_string_type(time_period tp)
|
||||
{
|
||||
charT beg = '[', mid = '/', end = ']';
|
||||
std::basic_string<charT> d1(to_simple_string_type<charT>(tp.begin()));
|
||||
std::basic_string<charT> d2(to_simple_string_type<charT>(tp.last()));
|
||||
return std::basic_string<charT>(beg + d1 + mid + d2 + end);
|
||||
}
|
||||
//! Convert to string of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff]
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::string to_simple_string(time_period tp){
|
||||
return to_simple_string_type<char>(tp);
|
||||
}
|
||||
|
||||
// function called by wrapper functions to_*_string(time_period)
|
||||
// & to_*_wstring(time_period)
|
||||
template<class charT>
|
||||
inline std::basic_string<charT> to_iso_string_type(ptime t)
|
||||
{
|
||||
std::basic_string<charT> ts = gregorian::to_iso_string_type<charT>(t.date());// + "T";
|
||||
if(!t.time_of_day().is_special()) {
|
||||
charT sep = 'T';
|
||||
return ts + sep + to_iso_string_type<charT>(t.time_of_day());
|
||||
}
|
||||
else {
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
//! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::string to_iso_string(ptime t){
|
||||
return to_iso_string_type<char>(t);
|
||||
}
|
||||
|
||||
|
||||
// function called by wrapper functions to_*_string(time_period)
|
||||
// & to_*_wstring(time_period)
|
||||
template<class charT>
|
||||
inline std::basic_string<charT> to_iso_extended_string_type(ptime t)
|
||||
{
|
||||
std::basic_string<charT> ts = gregorian::to_iso_extended_string_type<charT>(t.date());// + "T";
|
||||
if(!t.time_of_day().is_special()) {
|
||||
charT sep = 'T';
|
||||
return ts + sep + to_simple_string_type<charT>(t.time_of_day());
|
||||
}
|
||||
else {
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
//! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::string to_iso_extended_string(ptime t){
|
||||
return to_iso_extended_string_type<char>(t);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_STD_WSTRING)
|
||||
//! Time duration to wstring -hh::mm::ss.fffffff. Example: 10:09:03.0123456
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::wstring to_simple_wstring(time_duration td) {
|
||||
return to_simple_string_type<wchar_t>(td);
|
||||
}
|
||||
//! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::wstring to_iso_wstring(time_duration td){
|
||||
return to_iso_string_type<wchar_t>(td);
|
||||
}
|
||||
inline std::wstring to_simple_wstring(ptime t){
|
||||
return to_simple_string_type<wchar_t>(t);
|
||||
}
|
||||
//! Convert to wstring of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff]
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::wstring to_simple_wstring(time_period tp){
|
||||
return to_simple_string_type<wchar_t>(tp);
|
||||
}
|
||||
//! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::wstring to_iso_wstring(ptime t){
|
||||
return to_iso_string_type<wchar_t>(t);
|
||||
}
|
||||
//! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator
|
||||
/*!\ingroup time_format
|
||||
*/
|
||||
inline std::wstring to_iso_extended_wstring(ptime t){
|
||||
return to_iso_extended_string_type<wchar_t>(t);
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_STD_WSTRING
|
||||
|
||||
|
||||
} } //namespace posix_time
|
||||
|
||||
|
||||
#endif
|
||||
|
96
cpp/BoostParts/boost/date_time/special_values_formatter.hpp
Normal file
96
cpp/BoostParts/boost/date_time/special_values_formatter.hpp
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
#ifndef DATETIME_SPECIAL_VALUE_FORMATTER_HPP___
|
||||
#define DATETIME_SPECIAL_VALUE_FORMATTER_HPP___
|
||||
|
||||
/* Copyright (c) 2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland
|
||||
* $Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "boost/date_time/special_defs.hpp"
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
|
||||
//! Class that provides generic formmatting ostream formatting for special values
|
||||
/*! This class provides for the formmating of special values to an output stream.
|
||||
* In particular, it produces strings for the values of negative and positive
|
||||
* infinity as well as not_a_date_time.
|
||||
*
|
||||
* While not a facet, this class is used by the date and time facets for formatting
|
||||
* special value types.
|
||||
*
|
||||
*/
|
||||
template <class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
|
||||
class special_values_formatter
|
||||
{
|
||||
public:
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
typedef CharT char_type;
|
||||
typedef std::vector<string_type> collection_type;
|
||||
static const char_type default_special_value_names[3][17];
|
||||
|
||||
//! Construct special values formatter using default strings.
|
||||
/*! Default strings are not-a-date-time -infinity +infinity
|
||||
*/
|
||||
special_values_formatter()
|
||||
{
|
||||
std::copy(&default_special_value_names[0],
|
||||
&default_special_value_names[3],
|
||||
std::back_inserter(m_special_value_names));
|
||||
}
|
||||
|
||||
//! Construct special values formatter from array of strings
|
||||
/*! This constructor will take pair of iterators from an array of strings
|
||||
* that represent the special values and copy them for use in formatting
|
||||
* special values.
|
||||
*@code
|
||||
* const char* const special_value_names[]={"nadt","-inf","+inf" };
|
||||
*
|
||||
* special_value_formatter svf(&special_value_names[0], &special_value_names[3]);
|
||||
*@endcode
|
||||
*/
|
||||
special_values_formatter(const char_type* const* begin, const char_type* const* end)
|
||||
{
|
||||
std::copy(begin, end, std::back_inserter(m_special_value_names));
|
||||
}
|
||||
special_values_formatter(typename collection_type::iterator beg, typename collection_type::iterator end)
|
||||
{
|
||||
std::copy(beg, end, std::back_inserter(m_special_value_names));
|
||||
}
|
||||
|
||||
OutItrT put_special(OutItrT next,
|
||||
const boost::date_time::special_values& value) const
|
||||
{
|
||||
|
||||
unsigned int index = value;
|
||||
if (index < m_special_value_names.size()) {
|
||||
std::copy(m_special_value_names[index].begin(),
|
||||
m_special_value_names[index].end(),
|
||||
next);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
protected:
|
||||
collection_type m_special_value_names;
|
||||
};
|
||||
|
||||
//! Storage for the strings used to indicate special values
|
||||
/* using c_strings to initialize these worked fine in testing, however,
|
||||
* a project that compiled its objects separately, then linked in a separate
|
||||
* step wound up with redefinition errors for the values in this array.
|
||||
* Initializing individual characters eliminated this problem */
|
||||
template <class CharT, class OutItrT>
|
||||
const typename special_values_formatter<CharT, OutItrT>::char_type special_values_formatter<CharT, OutItrT>::default_special_value_names[3][17] = {
|
||||
{'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'},
|
||||
{'-','i','n','f','i','n','i','t','y'},
|
||||
{'+','i','n','f','i','n','i','t','y'} };
|
||||
|
||||
} } //namespace boost::date_time
|
||||
|
||||
#endif
|
159
cpp/BoostParts/boost/date_time/special_values_parser.hpp
Normal file
159
cpp/BoostParts/boost/date_time/special_values_parser.hpp
Normal file
@ -0,0 +1,159 @@
|
||||
|
||||
#ifndef DATE_TIME_SPECIAL_VALUES_PARSER_HPP__
|
||||
#define DATE_TIME_SPECIAL_VALUES_PARSER_HPP__
|
||||
|
||||
/* Copyright (c) 2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date:
|
||||
*/
|
||||
|
||||
|
||||
#include "boost/date_time/string_parse_tree.hpp"
|
||||
#include "boost/date_time/special_defs.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
//! Class for special_value parsing
|
||||
/*!
|
||||
* TODO: add doc-comments for which elements can be changed
|
||||
* Parses input stream for strings representing special_values.
|
||||
* Special values parsed are:
|
||||
* - not_a_date_time
|
||||
* - neg_infin
|
||||
* - pod_infin
|
||||
* - min_date_time
|
||||
* - max_date_time
|
||||
*/
|
||||
template<class date_type, typename charT>
|
||||
class special_values_parser
|
||||
{
|
||||
public:
|
||||
typedef std::basic_string<charT> string_type;
|
||||
//typedef std::basic_stringstream<charT> stringstream_type;
|
||||
typedef std::istreambuf_iterator<charT> stream_itr_type;
|
||||
//typedef typename string_type::const_iterator const_itr;
|
||||
//typedef typename date_type::year_type year_type;
|
||||
//typedef typename date_type::month_type month_type;
|
||||
typedef typename date_type::duration_type duration_type;
|
||||
//typedef typename date_type::day_of_week_type day_of_week_type;
|
||||
//typedef typename date_type::day_type day_type;
|
||||
typedef string_parse_tree<charT> parse_tree_type;
|
||||
typedef typename parse_tree_type::parse_match_result_type match_results;
|
||||
typedef std::vector<std::basic_string<charT> > collection_type;
|
||||
|
||||
typedef charT char_type;
|
||||
static const char_type nadt_string[16];
|
||||
static const char_type neg_inf_string[10];
|
||||
static const char_type pos_inf_string[10];
|
||||
static const char_type min_date_time_string[18];
|
||||
static const char_type max_date_time_string[18];
|
||||
|
||||
//! Creates a special_values_parser with the default set of "sv_strings"
|
||||
special_values_parser()
|
||||
{
|
||||
sv_strings(string_type(nadt_string),
|
||||
string_type(neg_inf_string),
|
||||
string_type(pos_inf_string),
|
||||
string_type(min_date_time_string),
|
||||
string_type(max_date_time_string));
|
||||
}
|
||||
|
||||
//! Creates a special_values_parser using a user defined set of element strings
|
||||
special_values_parser(const string_type& nadt_str,
|
||||
const string_type& neg_inf_str,
|
||||
const string_type& pos_inf_str,
|
||||
const string_type& min_dt_str,
|
||||
const string_type& max_dt_str)
|
||||
{
|
||||
sv_strings(nadt_str, neg_inf_str, pos_inf_str, min_dt_str, max_dt_str);
|
||||
}
|
||||
|
||||
special_values_parser(typename collection_type::iterator beg, typename collection_type::iterator end)
|
||||
{
|
||||
collection_type phrases;
|
||||
std::copy(beg, end, std::back_inserter(phrases));
|
||||
m_sv_strings = parse_tree_type(phrases, static_cast<int>(not_a_date_time));
|
||||
}
|
||||
|
||||
special_values_parser(const special_values_parser<date_type,charT>& svp)
|
||||
{
|
||||
this->m_sv_strings = svp.m_sv_strings;
|
||||
}
|
||||
|
||||
//! Replace special value strings
|
||||
void sv_strings(const string_type& nadt_str,
|
||||
const string_type& neg_inf_str,
|
||||
const string_type& pos_inf_str,
|
||||
const string_type& min_dt_str,
|
||||
const string_type& max_dt_str)
|
||||
{
|
||||
collection_type phrases;
|
||||
phrases.push_back(nadt_str);
|
||||
phrases.push_back(neg_inf_str);
|
||||
phrases.push_back(pos_inf_str);
|
||||
phrases.push_back(min_dt_str);
|
||||
phrases.push_back(max_dt_str);
|
||||
m_sv_strings = parse_tree_type(phrases, static_cast<int>(not_a_date_time));
|
||||
}
|
||||
|
||||
/* Does not return a special_value because if the parsing fails,
|
||||
* the return value will always be not_a_date_time
|
||||
* (mr.current_match retains its default value of -1 on a failed
|
||||
* parse and that casts to not_a_date_time). */
|
||||
//! Sets match_results.current_match to the corresponding special_value or -1
|
||||
bool match(stream_itr_type& sitr,
|
||||
stream_itr_type& str_end,
|
||||
match_results& mr) const
|
||||
{
|
||||
unsigned int level = 0;
|
||||
m_sv_strings.match(sitr, str_end, mr, level);
|
||||
return (mr.current_match != match_results::PARSE_ERROR);
|
||||
}
|
||||
/*special_values match(stream_itr_type& sitr,
|
||||
stream_itr_type& str_end,
|
||||
match_results& mr) const
|
||||
{
|
||||
unsigned int level = 0;
|
||||
m_sv_strings.match(sitr, str_end, mr, level);
|
||||
if(mr.current_match == match_results::PARSE_ERROR) {
|
||||
throw std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'");
|
||||
}
|
||||
return static_cast<special_values>(mr.current_match);
|
||||
}*/
|
||||
|
||||
|
||||
private:
|
||||
parse_tree_type m_sv_strings;
|
||||
|
||||
};
|
||||
|
||||
template<class date_type, class CharT>
|
||||
const typename special_values_parser<date_type, CharT>::char_type
|
||||
special_values_parser<date_type, CharT>::nadt_string[16] =
|
||||
{'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'};
|
||||
template<class date_type, class CharT>
|
||||
const typename special_values_parser<date_type, CharT>::char_type
|
||||
special_values_parser<date_type, CharT>::neg_inf_string[10] =
|
||||
{'-','i','n','f','i','n','i','t','y'};
|
||||
template<class date_type, class CharT>
|
||||
const typename special_values_parser<date_type, CharT>::char_type
|
||||
special_values_parser<date_type, CharT>::pos_inf_string[10] =
|
||||
{'+','i','n','f','i','n','i','t','y'};
|
||||
template<class date_type, class CharT>
|
||||
const typename special_values_parser<date_type, CharT>::char_type
|
||||
special_values_parser<date_type, CharT>::min_date_time_string[18] =
|
||||
{'m','i','n','i','m','u','m','-','d','a','t','e','-','t','i','m','e'};
|
||||
template<class date_type, class CharT>
|
||||
const typename special_values_parser<date_type, CharT>::char_type
|
||||
special_values_parser<date_type, CharT>::max_date_time_string[18] =
|
||||
{'m','a','x','i','m','u','m','-','d','a','t','e','-','t','i','m','e'};
|
||||
|
||||
} } //namespace
|
||||
|
||||
#endif // DATE_TIME_SPECIAL_VALUES_PARSER_HPP__
|
||||
|
33
cpp/BoostParts/boost/date_time/string_convert.hpp
Normal file
33
cpp/BoostParts/boost/date_time/string_convert.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef _STRING_CONVERT_HPP___
|
||||
#define _STRING_CONVERT_HPP___
|
||||
|
||||
/* Copyright (c) 2005 CrystalClear Software, Inc.
|
||||
* Subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $
|
||||
*/
|
||||
|
||||
#include "boost/date_time/compiler_config.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace date_time {
|
||||
|
||||
//! Converts a string from one value_type to another
|
||||
/*! Converts a wstring to a string (or a string to wstring). If both template parameters
|
||||
* are of same type, a copy of the input string is returned. */
|
||||
template<class InputT, class OutputT>
|
||||
inline
|
||||
std::basic_string<OutputT> convert_string_type(const std::basic_string<InputT>& inp_str)
|
||||
{
|
||||
typedef std::basic_string<InputT> input_type;
|
||||
typedef std::basic_string<OutputT> output_type;
|
||||
output_type result;
|
||||
result.insert(result.begin(), inp_str.begin(), inp_str.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
}} // namespace boost::date_time
|
||||
|
||||
#endif // _STRING_CONVERT_HPP___
|
278
cpp/BoostParts/boost/date_time/string_parse_tree.hpp
Normal file
278
cpp/BoostParts/boost/date_time/string_parse_tree.hpp
Normal file
@ -0,0 +1,278 @@
|
||||
#ifndef BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__
|
||||
#define BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__
|
||||
|
||||
/* Copyright (c) 2004-2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-11-12 11:37:53 -0800 (Wed, 12 Nov 2008) $
|
||||
*/
|
||||
|
||||
|
||||
#include "boost/lexical_cast.hpp" //error without?
|
||||
#include "boost/algorithm/string/case_conv.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
|
||||
template<typename charT>
|
||||
struct parse_match_result
|
||||
{
|
||||
parse_match_result() :
|
||||
match_depth(0),
|
||||
current_match(-1)// -1 is match_not-found value
|
||||
{}
|
||||
typedef std::basic_string<charT> string_type;
|
||||
string_type remaining() const
|
||||
{
|
||||
if (match_depth == cache.size()) {
|
||||
return string_type();
|
||||
}
|
||||
if (current_match == -1) {
|
||||
return cache;
|
||||
}
|
||||
//some of the cache was used return the rest
|
||||
return string_type(cache, match_depth);
|
||||
}
|
||||
charT last_char() const
|
||||
{
|
||||
return cache[cache.size()-1];
|
||||
}
|
||||
//! Returns true if more characters were parsed than was necessary
|
||||
/*! Should be used in conjunction with last_char()
|
||||
* to get the remaining character.
|
||||
*/
|
||||
bool has_remaining() const
|
||||
{
|
||||
return (cache.size() > match_depth);
|
||||
}
|
||||
|
||||
// cache will hold characters that have been read from the stream
|
||||
string_type cache;
|
||||
unsigned short match_depth;
|
||||
short current_match;
|
||||
enum PARSE_STATE { PARSE_ERROR= -1 };
|
||||
};
|
||||
|
||||
//for debug -- really only char streams...
|
||||
template<typename charT>
|
||||
std::basic_ostream<charT>&
|
||||
operator<<(std::basic_ostream<charT>& os, parse_match_result<charT>& mr)
|
||||
{
|
||||
os << "cm: " << mr.current_match
|
||||
<< " C: '" << mr.cache
|
||||
<< "' md: " << mr.match_depth
|
||||
<< " R: " << mr.remaining();
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Recursive data structure to allow efficient parsing of various strings
|
||||
/*! This class provides a quick lookup by building what amounts to a
|
||||
* tree data structure. It also features a match function which can
|
||||
* can handle nasty input interators by caching values as it recurses
|
||||
* the tree so that it can backtrack as needed.
|
||||
*/
|
||||
template<typename charT>
|
||||
struct string_parse_tree
|
||||
{
|
||||
#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) )
|
||||
typedef std::multimap<charT, string_parse_tree< charT> > ptree_coll;
|
||||
#else
|
||||
typedef std::multimap<charT, string_parse_tree > ptree_coll;
|
||||
#endif
|
||||
typedef typename ptree_coll::value_type value_type;
|
||||
typedef typename ptree_coll::iterator iterator;
|
||||
typedef typename ptree_coll::const_iterator const_iterator;
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef std::vector<std::basic_string<charT> > collection_type;
|
||||
typedef parse_match_result<charT> parse_match_result_type;
|
||||
|
||||
/*! Parameter "starting_point" designates where the numbering begins.
|
||||
* A starting_point of zero will start the numbering at zero
|
||||
* (Sun=0, Mon=1, ...) were a starting_point of one starts the
|
||||
* numbering at one (Jan=1, Feb=2, ...). The default is zero,
|
||||
* negative vaules are not allowed */
|
||||
string_parse_tree(collection_type names, unsigned int starting_point=0)
|
||||
{
|
||||
// iterate thru all the elements and build the tree
|
||||
unsigned short index = 0;
|
||||
while (index != names.size() ) {
|
||||
string_type s = boost::algorithm::to_lower_copy(names[index]);
|
||||
insert(s, static_cast<unsigned short>(index + starting_point));
|
||||
index++;
|
||||
}
|
||||
//set the last tree node = index+1 indicating a value
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
string_parse_tree(short value = -1) :
|
||||
m_value(value)
|
||||
{}
|
||||
ptree_coll m_next_chars;
|
||||
short m_value;
|
||||
|
||||
void insert(const string_type& s, unsigned short value)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
iterator ti;
|
||||
while(i < s.size()) {
|
||||
if (i==0) {
|
||||
if (i == (s.size()-1)) {
|
||||
ti = m_next_chars.insert(value_type(s[i],
|
||||
string_parse_tree<charT>(value)));
|
||||
}
|
||||
else {
|
||||
ti = m_next_chars.insert(value_type(s[i],
|
||||
string_parse_tree<charT>()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (i == (s.size()-1)) {
|
||||
ti = ti->second.m_next_chars.insert(value_type(s[i],
|
||||
string_parse_tree<charT>(value)));
|
||||
}
|
||||
|
||||
else {
|
||||
ti = ti->second.m_next_chars.insert(value_type(s[i],
|
||||
string_parse_tree<charT>()));
|
||||
}
|
||||
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Recursive function that finds a matching string in the tree.
|
||||
/*! Must check match_results::has_remaining() after match() is
|
||||
* called. This is required so the user can determine if
|
||||
* stream iterator is already pointing to the expected
|
||||
* character or not (match() might advance sitr to next char in stream).
|
||||
*
|
||||
* A parse_match_result that has been returned from a failed match
|
||||
* attempt can be sent in to the match function of a different
|
||||
* string_parse_tree to attempt a match there. Use the iterators
|
||||
* for the partially consumed stream, the parse_match_result object,
|
||||
* and '0' for the level parameter. */
|
||||
short
|
||||
match(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end,
|
||||
parse_match_result_type& result,
|
||||
unsigned int& level) const
|
||||
{
|
||||
|
||||
level++;
|
||||
charT c;
|
||||
// if we conditionally advance sitr, we won't have
|
||||
// to consume the next character past the input
|
||||
bool adv_itr = true;
|
||||
if (level > result.cache.size()) {
|
||||
if (sitr == stream_end) return 0; //bail - input exhausted
|
||||
c = static_cast<charT>(std::tolower(*sitr));
|
||||
//result.cache += c;
|
||||
//sitr++;
|
||||
}
|
||||
else {
|
||||
// if we're looking for characters from the cache,
|
||||
// we don't want to increment sitr
|
||||
adv_itr = false;
|
||||
c = static_cast<charT>(std::tolower(result.cache[level-1]));
|
||||
}
|
||||
const_iterator litr = m_next_chars.lower_bound(c);
|
||||
const_iterator uitr = m_next_chars.upper_bound(c);
|
||||
while (litr != uitr) { // equal if not found
|
||||
if(adv_itr) {
|
||||
sitr++;
|
||||
result.cache += c;
|
||||
}
|
||||
if (litr->second.m_value != -1) { // -1 is default value
|
||||
if (result.match_depth < level) {
|
||||
result.current_match = litr->second.m_value;
|
||||
result.match_depth = static_cast<unsigned short>(level);
|
||||
}
|
||||
litr->second.match(sitr, stream_end,
|
||||
result, level);
|
||||
level--;
|
||||
}
|
||||
else {
|
||||
litr->second.match(sitr, stream_end,
|
||||
result, level);
|
||||
level--;
|
||||
}
|
||||
|
||||
if(level <= result.cache.size()) {
|
||||
adv_itr = false;
|
||||
}
|
||||
|
||||
litr++;
|
||||
}
|
||||
return result.current_match;
|
||||
|
||||
}
|
||||
|
||||
/*! Must check match_results::has_remaining() after match() is
|
||||
* called. This is required so the user can determine if
|
||||
* stream iterator is already pointing to the expected
|
||||
* character or not (match() might advance sitr to next char in stream).
|
||||
*/
|
||||
parse_match_result_type
|
||||
match(std::istreambuf_iterator<charT>& sitr,
|
||||
std::istreambuf_iterator<charT>& stream_end) const
|
||||
{
|
||||
// lookup to_lower of char in tree.
|
||||
unsigned int level = 0;
|
||||
// string_type cache;
|
||||
parse_match_result_type result;
|
||||
match(sitr, stream_end, result, level);
|
||||
return result;
|
||||
}
|
||||
|
||||
void printme(std::ostream& os, int& level)
|
||||
{
|
||||
level++;
|
||||
iterator itr = m_next_chars.begin();
|
||||
iterator end = m_next_chars.end();
|
||||
// os << "starting level: " << level << std::endl;
|
||||
while (itr != end) {
|
||||
os << "level: " << level
|
||||
<< " node: " << itr->first
|
||||
<< " value: " << itr->second.m_value
|
||||
<< std::endl;
|
||||
itr->second.printme(os, level);
|
||||
itr++;
|
||||
}
|
||||
level--;
|
||||
}
|
||||
|
||||
void print(std::ostream& os)
|
||||
{
|
||||
int level = 0;
|
||||
printme(os, level);
|
||||
}
|
||||
|
||||
void printmatch(std::ostream& os, charT c)
|
||||
{
|
||||
iterator litr = m_next_chars.lower_bound(c);
|
||||
iterator uitr = m_next_chars.upper_bound(c);
|
||||
os << "matches for: " << c << std::endl;
|
||||
while (litr != uitr) {
|
||||
os << " node: " << litr->first
|
||||
<< " value: " << litr->second.m_value
|
||||
<< std::endl;
|
||||
litr++;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
} } //namespace
|
||||
#endif
|
125
cpp/BoostParts/boost/date_time/strings_from_facet.hpp
Normal file
125
cpp/BoostParts/boost/date_time/strings_from_facet.hpp
Normal file
@ -0,0 +1,125 @@
|
||||
#ifndef DATE_TIME_STRINGS_FROM_FACET__HPP___
|
||||
#define DATE_TIME_STRINGS_FROM_FACET__HPP___
|
||||
|
||||
/* Copyright (c) 2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland
|
||||
* $Date: 2012-09-22 09:04:10 -0700 (Sat, 22 Sep 2012) $
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <locale>
|
||||
|
||||
namespace boost { namespace date_time {
|
||||
|
||||
//! This function gathers up all the month strings from a std::locale
|
||||
/*! Using the time_put facet, this function creates a collection of
|
||||
* all the month strings from a locale. This is handy when building
|
||||
* custom date parsers or formatters that need to be localized.
|
||||
*
|
||||
*@param charT The type of char to use when gathering typically char
|
||||
* or wchar_t.
|
||||
*@param locale The locale to use when gathering the strings
|
||||
*@param short_strings True(default) to gather short strings,
|
||||
* false for long strings.
|
||||
*@return A vector of strings containing the strings in order. eg:
|
||||
* Jan, Feb, Mar, etc.
|
||||
*/
|
||||
template<typename charT>
|
||||
std::vector<std::basic_string<charT> >
|
||||
gather_month_strings(const std::locale& locale, bool short_strings=true)
|
||||
{
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef std::vector<string_type> collection_type;
|
||||
typedef std::basic_ostringstream<charT> ostream_type;
|
||||
typedef std::ostreambuf_iterator<charT> ostream_iter_type;
|
||||
typedef std::basic_ostringstream<charT> stringstream_type;
|
||||
typedef std::time_put<charT> time_put_facet_type;
|
||||
charT short_fmt[3] = { '%', 'b' };
|
||||
charT long_fmt[3] = { '%', 'B' };
|
||||
collection_type months;
|
||||
string_type outfmt(short_fmt);
|
||||
if (!short_strings) {
|
||||
outfmt = long_fmt;
|
||||
}
|
||||
{
|
||||
//grab the needed strings by using the locale to
|
||||
//output each month
|
||||
const charT* p_outfmt = outfmt.c_str(), *p_outfmt_end = p_outfmt + outfmt.size();
|
||||
tm tm_value = {};
|
||||
for (int m=0; m < 12; m++) {
|
||||
tm_value.tm_mon = m;
|
||||
stringstream_type ss;
|
||||
ostream_iter_type oitr(ss);
|
||||
std::use_facet<time_put_facet_type>(locale).put(oitr, ss, ss.fill(),
|
||||
&tm_value,
|
||||
p_outfmt,
|
||||
p_outfmt_end);
|
||||
months.push_back(ss.str());
|
||||
}
|
||||
}
|
||||
return months;
|
||||
}
|
||||
|
||||
//! This function gathers up all the weekday strings from a std::locale
|
||||
/*! Using the time_put facet, this function creates a collection of
|
||||
* all the weekday strings from a locale starting with the string for
|
||||
* 'Sunday'. This is handy when building custom date parsers or
|
||||
* formatters that need to be localized.
|
||||
*
|
||||
*@param charT The type of char to use when gathering typically char
|
||||
* or wchar_t.
|
||||
*@param locale The locale to use when gathering the strings
|
||||
*@param short_strings True(default) to gather short strings,
|
||||
* false for long strings.
|
||||
*@return A vector of strings containing the weekdays in order. eg:
|
||||
* Sun, Mon, Tue, Wed, Thu, Fri, Sat
|
||||
*/
|
||||
template<typename charT>
|
||||
std::vector<std::basic_string<charT> >
|
||||
gather_weekday_strings(const std::locale& locale, bool short_strings=true)
|
||||
{
|
||||
typedef std::basic_string<charT> string_type;
|
||||
typedef std::vector<string_type> collection_type;
|
||||
typedef std::basic_ostringstream<charT> ostream_type;
|
||||
typedef std::ostreambuf_iterator<charT> ostream_iter_type;
|
||||
typedef std::basic_ostringstream<charT> stringstream_type;
|
||||
typedef std::time_put<charT> time_put_facet_type;
|
||||
charT short_fmt[3] = { '%', 'a' };
|
||||
charT long_fmt[3] = { '%', 'A' };
|
||||
|
||||
collection_type weekdays;
|
||||
|
||||
|
||||
string_type outfmt(short_fmt);
|
||||
if (!short_strings) {
|
||||
outfmt = long_fmt;
|
||||
}
|
||||
{
|
||||
//grab the needed strings by using the locale to
|
||||
//output each month / weekday
|
||||
const charT* p_outfmt = outfmt.c_str(), *p_outfmt_end = p_outfmt + outfmt.size();
|
||||
tm tm_value = {};
|
||||
for (int i=0; i < 7; i++) {
|
||||
tm_value.tm_wday = i;
|
||||
stringstream_type ss;
|
||||
ostream_iter_type oitr(ss);
|
||||
std::use_facet<time_put_facet_type>(locale).put(oitr, ss, ss.fill(),
|
||||
&tm_value,
|
||||
p_outfmt,
|
||||
p_outfmt_end);
|
||||
|
||||
weekdays.push_back(ss.str());
|
||||
}
|
||||
}
|
||||
return weekdays;
|
||||
}
|
||||
|
||||
} } //namespace
|
||||
|
||||
|
||||
#endif
|
122
cpp/BoostParts/boost/date_time/time_formatting_streams.hpp
Normal file
122
cpp/BoostParts/boost/date_time/time_formatting_streams.hpp
Normal file
@ -0,0 +1,122 @@
|
||||
#ifndef DATE_TIME_TIME_FORMATTING_STREAMS_HPP___
|
||||
#define DATE_TIME_TIME_FORMATTING_STREAMS_HPP___
|
||||
|
||||
/* Copyright (c) 2002,2003 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2008-11-12 11:37:53 -0800 (Wed, 12 Nov 2008) $
|
||||
*/
|
||||
|
||||
#include <boost/date_time/compiler_config.hpp>
|
||||
|
||||
#ifndef BOOST_DATE_TIME_NO_LOCALE
|
||||
|
||||
#include <locale>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <boost/date_time/date_formatting_locales.hpp>
|
||||
#include <boost/date_time/time_resolution_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace date_time {
|
||||
|
||||
|
||||
//! Put a time type into a stream using appropriate facets
|
||||
template<class time_duration_type,
|
||||
class charT = char>
|
||||
class ostream_time_duration_formatter
|
||||
{
|
||||
public:
|
||||
typedef std::basic_ostream<charT> ostream_type;
|
||||
typedef typename time_duration_type::fractional_seconds_type fractional_seconds_type;
|
||||
|
||||
//! Put time into an ostream
|
||||
static void duration_put(const time_duration_type& td,
|
||||
ostream_type& os)
|
||||
{
|
||||
if(td.is_special()) {
|
||||
os << td.get_rep();
|
||||
}
|
||||
else {
|
||||
charT fill_char = '0';
|
||||
if(td.is_negative()) {
|
||||
os << '-';
|
||||
}
|
||||
os << std::setw(2) << std::setfill(fill_char)
|
||||
<< absolute_value(td.hours()) << ":";
|
||||
os << std::setw(2) << std::setfill(fill_char)
|
||||
<< absolute_value(td.minutes()) << ":";
|
||||
os << std::setw(2) << std::setfill(fill_char)
|
||||
<< absolute_value(td.seconds());
|
||||
fractional_seconds_type frac_sec =
|
||||
absolute_value(td.fractional_seconds());
|
||||
if (frac_sec != 0) {
|
||||
os << "."
|
||||
<< std::setw(time_duration_type::num_fractional_digits())
|
||||
<< std::setfill(fill_char)
|
||||
<< frac_sec;
|
||||
}
|
||||
} // else
|
||||
} // duration_put
|
||||
}; //class ostream_time_duration_formatter
|
||||
|
||||
//! Put a time type into a stream using appropriate facets
|
||||
template<class time_type,
|
||||
class charT = char>
|
||||
class ostream_time_formatter
|
||||
{
|
||||
public:
|
||||
typedef std::basic_ostream<charT> ostream_type;
|
||||
typedef typename time_type::date_type date_type;
|
||||
typedef typename time_type::time_duration_type time_duration_type;
|
||||
typedef ostream_time_duration_formatter<time_duration_type, charT> duration_formatter;
|
||||
|
||||
//! Put time into an ostream
|
||||
static void time_put(const time_type& t,
|
||||
ostream_type& os)
|
||||
{
|
||||
date_type d = t.date();
|
||||
os << d;
|
||||
if(!d.is_infinity() && !d.is_not_a_date())
|
||||
{
|
||||
os << " "; //TODO: fix the separator here.
|
||||
duration_formatter::duration_put(t.time_of_day(), os);
|
||||
}
|
||||
|
||||
} // time_to_ostream
|
||||
}; //class ostream_time_formatter
|
||||
|
||||
|
||||
//! Put a time period into a stream using appropriate facets
|
||||
template<class time_period_type,
|
||||
class charT = char>
|
||||
class ostream_time_period_formatter
|
||||
{
|
||||
public:
|
||||
typedef std::basic_ostream<charT> ostream_type;
|
||||
typedef typename time_period_type::point_type time_type;
|
||||
typedef ostream_time_formatter<time_type, charT> time_formatter;
|
||||
|
||||
//! Put time into an ostream
|
||||
static void period_put(const time_period_type& tp,
|
||||
ostream_type& os)
|
||||
{
|
||||
os << '['; //TODO: facet or manipulator for periods?
|
||||
time_formatter::time_put(tp.begin(), os);
|
||||
os << '/'; //TODO: facet or manipulator for periods?
|
||||
time_formatter::time_put(tp.last(), os);
|
||||
os << ']';
|
||||
|
||||
} // period_put
|
||||
|
||||
}; //class ostream_time_period_formatter
|
||||
|
||||
|
||||
|
||||
} } //namespace date_time
|
||||
|
||||
#endif //BOOST_DATE_TIME_NO_LOCALE
|
||||
|
||||
#endif
|
324
cpp/BoostParts/boost/date_time/time_parsing.hpp
Normal file
324
cpp/BoostParts/boost/date_time/time_parsing.hpp
Normal file
@ -0,0 +1,324 @@
|
||||
#ifndef _DATE_TIME_TIME_PARSING_HPP___
|
||||
#define _DATE_TIME_TIME_PARSING_HPP___
|
||||
|
||||
/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date: 2012-10-10 12:05:03 -0700 (Wed, 10 Oct 2012) $
|
||||
*/
|
||||
|
||||
#include "boost/tokenizer.hpp"
|
||||
#include "boost/lexical_cast.hpp"
|
||||
#include "boost/date_time/date_parsing.hpp"
|
||||
#include "boost/cstdint.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace boost {
|
||||
namespace date_time {
|
||||
|
||||
//! computes exponential math like 2^8 => 256, only works with positive integers
|
||||
//Not general purpose, but needed b/c std::pow is not available
|
||||
//everywehere. Hasn't been tested with negatives and zeros
|
||||
template<class int_type>
|
||||
inline
|
||||
int_type power(int_type base, int_type exponent)
|
||||
{
|
||||
int_type result = 1;
|
||||
for(int i = 0; i < exponent; ++i){
|
||||
result *= base;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Creates a time_duration object from a delimited string
|
||||
/*! Expected format for string is "[-]h[h][:mm][:ss][.fff]".
|
||||
* If the number of fractional digits provided is greater than the
|
||||
* precision of the time duration type then the extra digits are
|
||||
* truncated.
|
||||
*
|
||||
* A negative duration will be created if the first character in
|
||||
* string is a '-', all other '-' will be treated as delimiters.
|
||||
* Accepted delimiters are "-:,.".
|
||||
*/
|
||||
template<class time_duration, class char_type>
|
||||
inline
|
||||
time_duration
|
||||
str_from_delimited_time_duration(const std::basic_string<char_type>& s)
|
||||
{
|
||||
unsigned short min=0, sec =0;
|
||||
int hour =0;
|
||||
bool is_neg = (s.at(0) == '-');
|
||||
boost::int64_t fs=0;
|
||||
int pos = 0;
|
||||
|
||||
typedef typename std::basic_string<char_type>::traits_type traits_type;
|
||||
typedef boost::char_separator<char_type, traits_type> char_separator_type;
|
||||
typedef boost::tokenizer<char_separator_type,
|
||||
typename std::basic_string<char_type>::const_iterator,
|
||||
std::basic_string<char_type> > tokenizer;
|
||||
typedef typename boost::tokenizer<char_separator_type,
|
||||
typename std::basic_string<char_type>::const_iterator,
|
||||
typename std::basic_string<char_type> >::iterator tokenizer_iterator;
|
||||
|
||||
char_type sep_chars[5] = {'-',':',',','.'};
|
||||
char_separator_type sep(sep_chars);
|
||||
tokenizer tok(s,sep);
|
||||
for(tokenizer_iterator beg=tok.begin(); beg!=tok.end();++beg){
|
||||
switch(pos) {
|
||||
case 0: {
|
||||
hour = boost::lexical_cast<int>(*beg);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
min = boost::lexical_cast<unsigned short>(*beg);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
sec = boost::lexical_cast<unsigned short>(*beg);
|
||||
break;
|
||||
};
|
||||
case 3: {
|
||||
int digits = static_cast<int>(beg->length());
|
||||
//Works around a bug in MSVC 6 library that does not support
|
||||
//operator>> thus meaning lexical_cast will fail to compile.
|
||||
#if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
|
||||
// msvc wouldn't compile 'time_duration::num_fractional_digits()'
|
||||
// (required template argument list) as a workaround a temp
|
||||
// time_duration object was used
|
||||
time_duration td(hour,min,sec,fs);
|
||||
int precision = td.num_fractional_digits();
|
||||
// _atoi64 is an MS specific function
|
||||
if(digits >= precision) {
|
||||
// drop excess digits
|
||||
fs = _atoi64(beg->substr(0, precision).c_str());
|
||||
}
|
||||
else {
|
||||
fs = _atoi64(beg->c_str());
|
||||
}
|
||||
#else
|
||||
int precision = time_duration::num_fractional_digits();
|
||||
if(digits >= precision) {
|
||||
// drop excess digits
|
||||
fs = boost::lexical_cast<boost::int64_t>(beg->substr(0, precision));
|
||||
}
|
||||
else {
|
||||
fs = boost::lexical_cast<boost::int64_t>(*beg);
|
||||
}
|
||||
#endif
|
||||
if(digits < precision){
|
||||
// trailing zeros get dropped from the string,
|
||||
// "1:01:01.1" would yield .000001 instead of .100000
|
||||
// the power() compensates for the missing decimal places
|
||||
fs *= power(10, precision - digits);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}//switch
|
||||
pos++;
|
||||
}
|
||||
if(is_neg) {
|
||||
return -time_duration(hour, min, sec, fs);
|
||||
}
|
||||
else {
|
||||
return time_duration(hour, min, sec, fs);
|
||||
}
|
||||
}
|
||||
|
||||
//! Creates a time_duration object from a delimited string
|
||||
/*! Expected format for string is "[-]h[h][:mm][:ss][.fff]".
|
||||
* If the number of fractional digits provided is greater than the
|
||||
* precision of the time duration type then the extra digits are
|
||||
* truncated.
|
||||
*
|
||||
* A negative duration will be created if the first character in
|
||||
* string is a '-', all other '-' will be treated as delimiters.
|
||||
* Accepted delimiters are "-:,.".
|
||||
*/
|
||||
template<class time_duration>
|
||||
inline
|
||||
time_duration
|
||||
parse_delimited_time_duration(const std::string& s)
|
||||
{
|
||||
return str_from_delimited_time_duration<time_duration,char>(s);
|
||||
}
|
||||
|
||||
//! Utility function to split appart string
|
||||
inline
|
||||
bool
|
||||
split(const std::string& s,
|
||||
char sep,
|
||||
std::string& first,
|
||||
std::string& second)
|
||||
{
|
||||
std::string::size_type sep_pos = s.find(sep);
|
||||
first = s.substr(0,sep_pos);
|
||||
if (sep_pos!=std::string::npos)
|
||||
second = s.substr(sep_pos+1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class time_type>
|
||||
inline
|
||||
time_type
|
||||
parse_delimited_time(const std::string& s, char sep)
|
||||
{
|
||||
typedef typename time_type::time_duration_type time_duration;
|
||||
typedef typename time_type::date_type date_type;
|
||||
|
||||
//split date/time on a unique delimiter char such as ' ' or 'T'
|
||||
std::string date_string, tod_string;
|
||||
split(s, sep, date_string, tod_string);
|
||||
//call parse_date with first string
|
||||
date_type d = parse_date<date_type>(date_string);
|
||||
//call parse_time_duration with remaining string
|
||||
time_duration td = parse_delimited_time_duration<time_duration>(tod_string);
|
||||
//construct a time
|
||||
return time_type(d, td);
|
||||
|
||||
}
|
||||
|
||||
//! Parse time duration part of an iso time of form: [-]hhmmss[.fff...] (eg: 120259.123 is 12 hours, 2 min, 59 seconds, 123000 microseconds)
|
||||
template<class time_duration>
|
||||
inline
|
||||
time_duration
|
||||
parse_undelimited_time_duration(const std::string& s)
|
||||
{
|
||||
int precision = 0;
|
||||
{
|
||||
// msvc wouldn't compile 'time_duration::num_fractional_digits()'
|
||||
// (required template argument list) as a workaround, a temp
|
||||
// time_duration object was used
|
||||
time_duration tmp(0,0,0,1);
|
||||
precision = tmp.num_fractional_digits();
|
||||
}
|
||||
// 'precision+1' is so we grab all digits, plus the decimal
|
||||
int offsets[] = {2,2,2, precision+1};
|
||||
int pos = 0, sign = 0;
|
||||
int hours = 0;
|
||||
short min=0, sec=0;
|
||||
boost::int64_t fs=0;
|
||||
// increment one position if the string was "signed"
|
||||
if(s.at(sign) == '-')
|
||||
{
|
||||
++sign;
|
||||
}
|
||||
// stlport choked when passing s.substr() to tokenizer
|
||||
// using a new string fixed the error
|
||||
std::string remain = s.substr(sign);
|
||||
/* We do not want the offset_separator to wrap the offsets, we
|
||||
* will never want to process more than:
|
||||
* 2 char, 2 char, 2 char, frac_sec length.
|
||||
* We *do* want the offset_separator to give us a partial for the
|
||||
* last characters if there were not enough provided in the input string. */
|
||||
bool wrap_off = false;
|
||||
bool ret_part = true;
|
||||
boost::offset_separator osf(offsets, offsets+4, wrap_off, ret_part);
|
||||
typedef boost::tokenizer<boost::offset_separator,
|
||||
std::basic_string<char>::const_iterator,
|
||||
std::basic_string<char> > tokenizer;
|
||||
typedef boost::tokenizer<boost::offset_separator,
|
||||
std::basic_string<char>::const_iterator,
|
||||
std::basic_string<char> >::iterator tokenizer_iterator;
|
||||
tokenizer tok(remain, osf);
|
||||
for(tokenizer_iterator ti=tok.begin(); ti!=tok.end();++ti){
|
||||
switch(pos) {
|
||||
case 0:
|
||||
{
|
||||
hours = boost::lexical_cast<int>(*ti);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
min = boost::lexical_cast<short>(*ti);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
sec = boost::lexical_cast<short>(*ti);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
std::string char_digits(ti->substr(1)); // digits w/no decimal
|
||||
int digits = static_cast<int>(char_digits.length());
|
||||
|
||||
//Works around a bug in MSVC 6 library that does not support
|
||||
//operator>> thus meaning lexical_cast will fail to compile.
|
||||
#if (defined(BOOST_MSVC) && (_MSC_VER <= 1200)) // 1200 == VC++ 6.0
|
||||
// _atoi64 is an MS specific function
|
||||
if(digits >= precision) {
|
||||
// drop excess digits
|
||||
fs = _atoi64(char_digits.substr(0, precision).c_str());
|
||||
}
|
||||
else if(digits == 0) {
|
||||
fs = 0; // just in case _atoi64 doesn't like an empty string
|
||||
}
|
||||
else {
|
||||
fs = _atoi64(char_digits.c_str());
|
||||
}
|
||||
#else
|
||||
if(digits >= precision) {
|
||||
// drop excess digits
|
||||
fs = boost::lexical_cast<boost::int64_t>(char_digits.substr(0, precision));
|
||||
}
|
||||
else if(digits == 0) {
|
||||
fs = 0; // lexical_cast doesn't like empty strings
|
||||
}
|
||||
else {
|
||||
fs = boost::lexical_cast<boost::int64_t>(char_digits);
|
||||
}
|
||||
#endif
|
||||
if(digits < precision){
|
||||
// trailing zeros get dropped from the string,
|
||||
// "1:01:01.1" would yield .000001 instead of .100000
|
||||
// the power() compensates for the missing decimal places
|
||||
fs *= power(10, precision - digits);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
};
|
||||
pos++;
|
||||
}
|
||||
if(sign) {
|
||||
return -time_duration(hours, min, sec, fs);
|
||||
}
|
||||
else {
|
||||
return time_duration(hours, min, sec, fs);
|
||||
}
|
||||
}
|
||||
|
||||
//! Parse time string of form YYYYMMDDThhmmss where T is delimeter between date and time
|
||||
template<class time_type>
|
||||
inline
|
||||
time_type
|
||||
parse_iso_time(const std::string& s, char sep)
|
||||
{
|
||||
typedef typename time_type::time_duration_type time_duration;
|
||||
typedef typename time_type::date_type date_type;
|
||||
|
||||
//split date/time on a unique delimiter char such as ' ' or 'T'
|
||||
std::string date_string, tod_string;
|
||||
split(s, sep, date_string, tod_string);
|
||||
//call parse_date with first string
|
||||
date_type d = parse_undelimited_date<date_type>(date_string);
|
||||
//call parse_time_duration with remaining string
|
||||
time_duration td = parse_undelimited_time_duration<time_duration>(tod_string);
|
||||
//construct a time
|
||||
return time_type(d, td);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} }//namespace date_time
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
306
cpp/BoostParts/boost/interprocess/allocators/allocator.hpp
Normal file
306
cpp/BoostParts/boost/interprocess/allocators/allocator.hpp
Normal file
@ -0,0 +1,306 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_ALLOCATOR_HPP
|
||||
#define BOOST_INTERPROCESS_ALLOCATOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/containers/allocation_type.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/containers/version_type.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
|
||||
//!\file
|
||||
//!Describes an allocator that allocates portions of fixed size
|
||||
//!memory buffer (shared memory, mapped file...)
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
|
||||
//!An STL compatible allocator that uses a segment manager as
|
||||
//!memory source. The internal pointer type will of the same type (raw, smart) as
|
||||
//!"typename SegmentManager::void_pointer" type. This allows
|
||||
//!placing the allocator in shared memory, memory mapped-files, etc...
|
||||
template<class T, class SegmentManager>
|
||||
class allocator
|
||||
{
|
||||
public:
|
||||
//Segment manager
|
||||
typedef SegmentManager segment_manager;
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
|
||||
//Self type
|
||||
typedef allocator<T, SegmentManager> self_t;
|
||||
|
||||
//Pointer to void
|
||||
typedef typename segment_manager::void_pointer aux_pointer_t;
|
||||
|
||||
//Typedef to const void pointer
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<aux_pointer_t>::template
|
||||
rebind_pointer<const void>::type cvoid_ptr;
|
||||
|
||||
//Pointer to the allocator
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<cvoid_ptr>::template
|
||||
rebind_pointer<segment_manager>::type alloc_ptr_t;
|
||||
|
||||
//Not assignable from related allocator
|
||||
template<class T2, class SegmentManager2>
|
||||
allocator& operator=(const allocator<T2, SegmentManager2>&);
|
||||
|
||||
//Not assignable from other allocator
|
||||
allocator& operator=(const allocator&);
|
||||
|
||||
//Pointer to the allocator
|
||||
alloc_ptr_t mp_mngr;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<cvoid_ptr>::template
|
||||
rebind_pointer<T>::type pointer;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<pointer>::template
|
||||
rebind_pointer<const T>::type const_pointer;
|
||||
typedef typename ipcdetail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename ipcdetail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef typename segment_manager::size_type size_type;
|
||||
typedef typename segment_manager::difference_type difference_type;
|
||||
|
||||
typedef boost::interprocess::version_type<allocator, 2> version;
|
||||
|
||||
/// @cond
|
||||
|
||||
//Experimental. Don't use.
|
||||
typedef boost::container::container_detail::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
/// @endcond
|
||||
|
||||
//!Obtains an allocator that allocates
|
||||
//!objects of type T2
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef allocator<T2, SegmentManager> other;
|
||||
};
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const
|
||||
{ return ipcdetail::to_raw_pointer(mp_mngr); }
|
||||
|
||||
//!Constructor from the segment manager.
|
||||
//!Never throws
|
||||
allocator(segment_manager *segment_mngr)
|
||||
: mp_mngr(segment_mngr) { }
|
||||
|
||||
//!Constructor from other allocator.
|
||||
//!Never throws
|
||||
allocator(const allocator &other)
|
||||
: mp_mngr(other.get_segment_manager()){ }
|
||||
|
||||
//!Constructor from related allocator.
|
||||
//!Never throws
|
||||
template<class T2>
|
||||
allocator(const allocator<T2, SegmentManager> &other)
|
||||
: mp_mngr(other.get_segment_manager()){}
|
||||
|
||||
//!Allocates memory for an array of count elements.
|
||||
//!Throws boost::interprocess::bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count, cvoid_ptr hint = 0)
|
||||
{
|
||||
(void)hint;
|
||||
if(size_overflows<sizeof(T)>(count)){
|
||||
throw bad_alloc();
|
||||
}
|
||||
return pointer(static_cast<value_type*>(mp_mngr->allocate(count*sizeof(T))));
|
||||
}
|
||||
|
||||
//!Deallocates memory previously allocated.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type)
|
||||
{ mp_mngr->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); }
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const
|
||||
{ return mp_mngr->get_size()/sizeof(T); }
|
||||
|
||||
//!Swap segment manager. Does not throw. If each allocator is placed in
|
||||
//!different memory segments, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2)
|
||||
{ ipcdetail::do_swap(alloc1.mp_mngr, alloc2.mp_mngr); }
|
||||
|
||||
//!Returns maximum the number of objects the previously allocated memory
|
||||
//!pointed by p can hold. This size only works for memory allocated with
|
||||
//!allocate, allocation_command and allocate_many.
|
||||
size_type size(const pointer &p) const
|
||||
{
|
||||
return (size_type)mp_mngr->size(ipcdetail::to_raw_pointer(p))/sizeof(T);
|
||||
}
|
||||
|
||||
std::pair<pointer, bool>
|
||||
allocation_command(boost::interprocess::allocation_type command,
|
||||
size_type limit_size,
|
||||
size_type preferred_size,
|
||||
size_type &received_size, const pointer &reuse = 0)
|
||||
{
|
||||
return mp_mngr->allocation_command
|
||||
(command, limit_size, preferred_size, received_size, ipcdetail::to_raw_pointer(reuse));
|
||||
}
|
||||
|
||||
//!Allocates many elements of size elem_size in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. The elements must be deallocated
|
||||
//!with deallocate(...)
|
||||
void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain)
|
||||
{
|
||||
if(size_overflows<sizeof(T)>(elem_size)){
|
||||
throw bad_alloc();
|
||||
}
|
||||
mp_mngr->allocate_many(elem_size*sizeof(T), num_elements, chain);
|
||||
}
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T), chain);
|
||||
}
|
||||
|
||||
//!Allocates many elements of size elem_size in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. The elements must be deallocated
|
||||
//!with deallocate(...)
|
||||
void deallocate_many(multiallocation_chain &chain)
|
||||
{ mp_mngr->deallocate_many(chain); }
|
||||
|
||||
//!Allocates just one object. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
//!Throws boost::interprocess::bad_alloc if there is no enough memory
|
||||
pointer allocate_one()
|
||||
{ return this->allocate(1); }
|
||||
|
||||
//!Allocates many elements of size == 1 in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
void allocate_individual(size_type num_elements, multiallocation_chain &chain)
|
||||
{ this->allocate_many(1, num_elements, chain); }
|
||||
|
||||
//!Deallocates memory previously allocated with allocate_one().
|
||||
//!You should never use deallocate_one to deallocate memory allocated
|
||||
//!with other functions different from allocate_one(). Never throws
|
||||
void deallocate_one(const pointer &p)
|
||||
{ return this->deallocate(p, 1); }
|
||||
|
||||
//!Allocates many elements of size == 1 in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
void deallocate_individual(multiallocation_chain &chain)
|
||||
{ this->deallocate_many(chain); }
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const
|
||||
{ return pointer(boost::addressof(value)); }
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const
|
||||
{ return const_pointer(boost::addressof(value)); }
|
||||
|
||||
//!Constructs an object
|
||||
//!Throws if T's constructor throws
|
||||
//!For backwards compatibility with libraries using C++03 allocators
|
||||
template<class P>
|
||||
void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
|
||||
{ ::new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(::boost::forward<P>(p)); }
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr)
|
||||
{ BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); }
|
||||
|
||||
};
|
||||
|
||||
//!Equality test for same type
|
||||
//!of allocator
|
||||
template<class T, class SegmentManager> inline
|
||||
bool operator==(const allocator<T , SegmentManager> &alloc1,
|
||||
const allocator<T, SegmentManager> &alloc2)
|
||||
{ return alloc1.get_segment_manager() == alloc2.get_segment_manager(); }
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of allocator
|
||||
template<class T, class SegmentManager> inline
|
||||
bool operator!=(const allocator<T, SegmentManager> &alloc1,
|
||||
const allocator<T, SegmentManager> &alloc2)
|
||||
{ return alloc1.get_segment_manager() != alloc2.get_segment_manager(); }
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
template<class T>
|
||||
struct has_trivial_destructor;
|
||||
|
||||
template<class T, class SegmentManager>
|
||||
struct has_trivial_destructor
|
||||
<boost::interprocess::allocator <T, SegmentManager> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_ALLOCATOR_HPP
|
||||
|
@ -0,0 +1,850 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-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_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
|
||||
#define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp> //to_raw_pointer
|
||||
#include <boost/utility/addressof.hpp> //boost::addressof
|
||||
#include <boost/assert.hpp> //BOOST_ASSERT
|
||||
#include <boost/interprocess/exceptions.hpp> //bad_alloc
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp> //scoped_lock
|
||||
#include <boost/interprocess/containers/allocation_type.hpp> //boost::interprocess::allocation_type
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
|
||||
#include <boost/interprocess/detail/segment_manager_helper.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <algorithm> //std::swap
|
||||
#include <utility> //std::pair
|
||||
#include <new>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
template <class T>
|
||||
struct sizeof_value
|
||||
{
|
||||
static const std::size_t value = sizeof(T);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct sizeof_value<void>
|
||||
{
|
||||
static const std::size_t value = sizeof(void*);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct sizeof_value<const void>
|
||||
{
|
||||
static const std::size_t value = sizeof(void*);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct sizeof_value<volatile void>
|
||||
{
|
||||
static const std::size_t value = sizeof(void*);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct sizeof_value<const volatile void>
|
||||
{
|
||||
static const std::size_t value = sizeof(void*);
|
||||
};
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
//!Object function that creates the node allocator if it is not created and
|
||||
//!increments reference count if it is already created
|
||||
template<class NodePool>
|
||||
struct get_or_create_node_pool_func
|
||||
{
|
||||
|
||||
//!This connects or constructs the unique instance of node_pool_t
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
void operator()()
|
||||
{
|
||||
//Find or create the node_pool_t
|
||||
mp_node_pool = mp_segment_manager->template find_or_construct
|
||||
<NodePool>(boost::interprocess::unique_instance)(mp_segment_manager);
|
||||
//If valid, increment link count
|
||||
if(mp_node_pool != 0)
|
||||
mp_node_pool->inc_ref_count();
|
||||
}
|
||||
|
||||
//!Constructor. Initializes function
|
||||
//!object parameters
|
||||
get_or_create_node_pool_func(typename NodePool::segment_manager *mngr)
|
||||
: mp_segment_manager(mngr){}
|
||||
|
||||
NodePool *mp_node_pool;
|
||||
typename NodePool::segment_manager *mp_segment_manager;
|
||||
};
|
||||
|
||||
template<class NodePool>
|
||||
inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgnr)
|
||||
{
|
||||
ipcdetail::get_or_create_node_pool_func<NodePool> func(mgnr);
|
||||
mgnr->atomic_func(func);
|
||||
return func.mp_node_pool;
|
||||
}
|
||||
|
||||
//!Object function that decrements the reference count. If the count
|
||||
//!reaches to zero destroys the node allocator from memory.
|
||||
//!Never throws
|
||||
template<class NodePool>
|
||||
struct destroy_if_last_link_func
|
||||
{
|
||||
//!Decrements reference count and destroys the object if there is no
|
||||
//!more attached allocators. Never throws
|
||||
void operator()()
|
||||
{
|
||||
//If not the last link return
|
||||
if(mp_node_pool->dec_ref_count() != 0) return;
|
||||
|
||||
//Last link, let's destroy the segment_manager
|
||||
mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance);
|
||||
}
|
||||
|
||||
//!Constructor. Initializes function
|
||||
//!object parameters
|
||||
destroy_if_last_link_func(NodePool *pool)
|
||||
: mp_node_pool(pool)
|
||||
{}
|
||||
|
||||
NodePool *mp_node_pool;
|
||||
};
|
||||
|
||||
//!Destruction function, initializes and executes destruction function
|
||||
//!object. Never throws
|
||||
template<class NodePool>
|
||||
inline void destroy_node_pool_if_last_link(NodePool *pool)
|
||||
{
|
||||
//Get segment manager
|
||||
typename NodePool::segment_manager *mngr = pool->get_segment_manager();
|
||||
//Execute destruction functor atomically
|
||||
destroy_if_last_link_func<NodePool>func(pool);
|
||||
mngr->atomic_func(func);
|
||||
}
|
||||
|
||||
template<class NodePool>
|
||||
class cache_impl
|
||||
{
|
||||
typedef typename NodePool::segment_manager::
|
||||
void_pointer void_pointer;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<void_pointer>::template
|
||||
rebind_pointer<NodePool>::type node_pool_ptr;
|
||||
typedef typename NodePool::multiallocation_chain multiallocation_chain;
|
||||
typedef typename NodePool::segment_manager::size_type size_type;
|
||||
node_pool_ptr mp_node_pool;
|
||||
multiallocation_chain m_cached_nodes;
|
||||
size_type m_max_cached_nodes;
|
||||
|
||||
public:
|
||||
typedef typename NodePool::segment_manager segment_manager;
|
||||
|
||||
cache_impl(segment_manager *segment_mngr, size_type max_cached_nodes)
|
||||
: mp_node_pool(get_or_create_node_pool<NodePool>(segment_mngr))
|
||||
, m_max_cached_nodes(max_cached_nodes)
|
||||
{}
|
||||
|
||||
cache_impl(const cache_impl &other)
|
||||
: mp_node_pool(other.get_node_pool())
|
||||
, m_max_cached_nodes(other.get_max_cached_nodes())
|
||||
{
|
||||
mp_node_pool->inc_ref_count();
|
||||
}
|
||||
|
||||
~cache_impl()
|
||||
{
|
||||
this->deallocate_all_cached_nodes();
|
||||
ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool));
|
||||
}
|
||||
|
||||
NodePool *get_node_pool() const
|
||||
{ return ipcdetail::to_raw_pointer(mp_node_pool); }
|
||||
|
||||
segment_manager *get_segment_manager() const
|
||||
{ return mp_node_pool->get_segment_manager(); }
|
||||
|
||||
size_type get_max_cached_nodes() const
|
||||
{ return m_max_cached_nodes; }
|
||||
|
||||
void *cached_allocation()
|
||||
{
|
||||
//If don't have any cached node, we have to get a new list of free nodes from the pool
|
||||
if(m_cached_nodes.empty()){
|
||||
mp_node_pool->allocate_nodes(m_max_cached_nodes/2, m_cached_nodes);
|
||||
}
|
||||
void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cached_allocation(size_type n, multiallocation_chain &chain)
|
||||
{
|
||||
size_type count = n, allocated(0);
|
||||
BOOST_TRY{
|
||||
//If don't have any cached node, we have to get a new list of free nodes from the pool
|
||||
while(!m_cached_nodes.empty() && count--){
|
||||
void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front());
|
||||
chain.push_back(ret);
|
||||
++allocated;
|
||||
}
|
||||
|
||||
if(allocated != n){
|
||||
mp_node_pool->allocate_nodes(n - allocated, chain);
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
this->cached_deallocation(chain);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
void cached_deallocation(void *ptr)
|
||||
{
|
||||
//Check if cache is full
|
||||
if(m_cached_nodes.size() >= m_max_cached_nodes){
|
||||
//This only occurs if this allocator deallocate memory allocated
|
||||
//with other equal allocator. Since the cache is full, and more
|
||||
//deallocations are probably coming, we'll make some room in cache
|
||||
//in a single, efficient multi node deallocation.
|
||||
this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2);
|
||||
}
|
||||
m_cached_nodes.push_front(ptr);
|
||||
}
|
||||
|
||||
void cached_deallocation(multiallocation_chain &chain)
|
||||
{
|
||||
m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain);
|
||||
|
||||
//Check if cache is full
|
||||
if(m_cached_nodes.size() >= m_max_cached_nodes){
|
||||
//This only occurs if this allocator deallocate memory allocated
|
||||
//with other equal allocator. Since the cache is full, and more
|
||||
//deallocations are probably coming, we'll make some room in cache
|
||||
//in a single, efficient multi node deallocation.
|
||||
this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2);
|
||||
}
|
||||
}
|
||||
|
||||
//!Sets the new max cached nodes value. This can provoke deallocations
|
||||
//!if "newmax" is less than current cached nodes. Never throws
|
||||
void set_max_cached_nodes(size_type newmax)
|
||||
{
|
||||
m_max_cached_nodes = newmax;
|
||||
this->priv_deallocate_remaining_nodes();
|
||||
}
|
||||
|
||||
//!Frees all cached nodes.
|
||||
//!Never throws
|
||||
void deallocate_all_cached_nodes()
|
||||
{
|
||||
if(m_cached_nodes.empty()) return;
|
||||
mp_node_pool->deallocate_nodes(m_cached_nodes);
|
||||
}
|
||||
|
||||
private:
|
||||
//!Frees all cached nodes at once.
|
||||
//!Never throws
|
||||
void priv_deallocate_remaining_nodes()
|
||||
{
|
||||
if(m_cached_nodes.size() > m_max_cached_nodes){
|
||||
priv_deallocate_n_nodes(m_cached_nodes.size()-m_max_cached_nodes);
|
||||
}
|
||||
}
|
||||
|
||||
//!Frees n cached nodes at once. Never throws
|
||||
void priv_deallocate_n_nodes(size_type n)
|
||||
{
|
||||
//This only occurs if this allocator deallocate memory allocated
|
||||
//with other equal allocator. Since the cache is full, and more
|
||||
//deallocations are probably coming, we'll make some room in cache
|
||||
//in a single, efficient multi node deallocation.
|
||||
size_type count(n);
|
||||
typename multiallocation_chain::iterator it(m_cached_nodes.before_begin());
|
||||
while(count--){
|
||||
++it;
|
||||
}
|
||||
multiallocation_chain chain;
|
||||
chain.splice_after(chain.before_begin(), m_cached_nodes, m_cached_nodes.before_begin(), it, n);
|
||||
//Deallocate all new linked list at once
|
||||
mp_node_pool->deallocate_nodes(chain);
|
||||
}
|
||||
|
||||
public:
|
||||
void swap(cache_impl &other)
|
||||
{
|
||||
ipcdetail::do_swap(mp_node_pool, other.mp_node_pool);
|
||||
m_cached_nodes.swap(other.m_cached_nodes);
|
||||
ipcdetail::do_swap(m_max_cached_nodes, other.m_max_cached_nodes);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Derived, class T, class SegmentManager>
|
||||
class array_allocation_impl
|
||||
{
|
||||
const Derived *derived() const
|
||||
{ return static_cast<const Derived*>(this); }
|
||||
Derived *derived()
|
||||
{ return static_cast<Derived*>(this); }
|
||||
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
|
||||
public:
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<void_pointer>::template
|
||||
rebind_pointer<T>::type pointer;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<void_pointer>::template
|
||||
rebind_pointer<const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename ipcdetail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename ipcdetail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef typename SegmentManager::size_type size_type;
|
||||
typedef typename SegmentManager::difference_type difference_type;
|
||||
typedef boost::container::container_detail::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
|
||||
|
||||
public:
|
||||
//!Returns maximum the number of objects the previously allocated memory
|
||||
//!pointed by p can hold. This size only works for memory allocated with
|
||||
//!allocate, allocation_command and allocate_many.
|
||||
size_type size(const pointer &p) const
|
||||
{
|
||||
return (size_type)this->derived()->get_segment_manager()->size(ipcdetail::to_raw_pointer(p))/sizeof(T);
|
||||
}
|
||||
|
||||
std::pair<pointer, bool>
|
||||
allocation_command(boost::interprocess::allocation_type command,
|
||||
size_type limit_size,
|
||||
size_type preferred_size,
|
||||
size_type &received_size, const pointer &reuse = 0)
|
||||
{
|
||||
return this->derived()->get_segment_manager()->allocation_command
|
||||
(command, limit_size, preferred_size, received_size, ipcdetail::to_raw_pointer(reuse));
|
||||
}
|
||||
|
||||
//!Allocates many elements of size elem_size in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. The elements must be deallocated
|
||||
//!with deallocate(...)
|
||||
void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain)
|
||||
{
|
||||
if(size_overflows<sizeof(T)>(elem_size)){
|
||||
throw bad_alloc();
|
||||
}
|
||||
this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements, chain);
|
||||
}
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T), chain);
|
||||
}
|
||||
|
||||
//!Allocates many elements of size elem_size in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. The elements must be deallocated
|
||||
//!with deallocate(...)
|
||||
void deallocate_many(multiallocation_chain &chain)
|
||||
{ this->derived()->get_segment_manager()->deallocate_many(chain); }
|
||||
|
||||
//!Returns the number of elements that could be
|
||||
//!allocated. Never throws
|
||||
size_type max_size() const
|
||||
{ return this->derived()->get_segment_manager()->get_size()/sizeof(T); }
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const
|
||||
{ return pointer(boost::addressof(value)); }
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const
|
||||
{ return const_pointer(boost::addressof(value)); }
|
||||
|
||||
//!Constructs an object
|
||||
//!Throws if T's constructor throws
|
||||
//!For backwards compatibility with libraries using C++03 allocators
|
||||
template<class P>
|
||||
void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
|
||||
{ ::new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(::boost::forward<P>(p)); }
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr)
|
||||
{ BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); }
|
||||
};
|
||||
|
||||
|
||||
template<class Derived, unsigned int Version, class T, class SegmentManager>
|
||||
class node_pool_allocation_impl
|
||||
: public array_allocation_impl
|
||||
< Derived
|
||||
, T
|
||||
, SegmentManager>
|
||||
{
|
||||
const Derived *derived() const
|
||||
{ return static_cast<const Derived*>(this); }
|
||||
Derived *derived()
|
||||
{ return static_cast<Derived*>(this); }
|
||||
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<void_pointer>::template
|
||||
rebind_pointer<const void>::type cvoid_pointer;
|
||||
|
||||
public:
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<void_pointer>::template
|
||||
rebind_pointer<T>::type pointer;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<void_pointer>::template
|
||||
rebind_pointer<const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename ipcdetail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename ipcdetail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef typename SegmentManager::size_type size_type;
|
||||
typedef typename SegmentManager::difference_type difference_type;
|
||||
typedef boost::container::container_detail::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
|
||||
|
||||
template <int Dummy>
|
||||
struct node_pool
|
||||
{
|
||||
typedef typename Derived::template node_pool<0>::type type;
|
||||
static type *get(void *p)
|
||||
{ return static_cast<type*>(p); }
|
||||
};
|
||||
|
||||
public:
|
||||
//!Allocate memory for an array of count elements.
|
||||
//!Throws boost::interprocess::bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count, cvoid_pointer hint = 0)
|
||||
{
|
||||
(void)hint;
|
||||
typedef typename node_pool<0>::type node_pool_t;
|
||||
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
|
||||
if(size_overflows<sizeof(T)>(count)){
|
||||
throw bad_alloc();
|
||||
}
|
||||
else if(Version == 1 && count == 1){
|
||||
return pointer(static_cast<value_type*>
|
||||
(pool->allocate_node()));
|
||||
}
|
||||
else{
|
||||
return pointer(static_cast<value_type*>
|
||||
(pool->get_segment_manager()->allocate(count*sizeof(T))));
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocate allocated memory. Never throws
|
||||
void deallocate(const pointer &ptr, size_type count)
|
||||
{
|
||||
(void)count;
|
||||
typedef typename node_pool<0>::type node_pool_t;
|
||||
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
|
||||
if(Version == 1 && count == 1)
|
||||
pool->deallocate_node(ipcdetail::to_raw_pointer(ptr));
|
||||
else
|
||||
pool->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr));
|
||||
}
|
||||
|
||||
//!Allocates just one object. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
//!Throws boost::interprocess::bad_alloc if there is no enough memory
|
||||
pointer allocate_one()
|
||||
{
|
||||
typedef typename node_pool<0>::type node_pool_t;
|
||||
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
|
||||
return pointer(static_cast<value_type*>(pool->allocate_node()));
|
||||
}
|
||||
|
||||
//!Allocates many elements of size == 1 in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
void allocate_individual(size_type num_elements, multiallocation_chain &chain)
|
||||
{
|
||||
typedef typename node_pool<0>::type node_pool_t;
|
||||
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
|
||||
pool->allocate_nodes(num_elements, chain);
|
||||
}
|
||||
|
||||
//!Deallocates memory previously allocated with allocate_one().
|
||||
//!You should never use deallocate_one to deallocate memory allocated
|
||||
//!with other functions different from allocate_one(). Never throws
|
||||
void deallocate_one(const pointer &p)
|
||||
{
|
||||
typedef typename node_pool<0>::type node_pool_t;
|
||||
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
|
||||
pool->deallocate_node(ipcdetail::to_raw_pointer(p));
|
||||
}
|
||||
|
||||
//!Allocates many elements of size == 1 in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
void deallocate_individual(multiallocation_chain &chain)
|
||||
{
|
||||
node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes
|
||||
(chain);
|
||||
}
|
||||
|
||||
//!Deallocates all free blocks of the pool
|
||||
void deallocate_free_blocks()
|
||||
{ node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); }
|
||||
|
||||
//!Deprecated, use deallocate_free_blocks.
|
||||
//!Deallocates all free chunks of the pool.
|
||||
void deallocate_free_chunks()
|
||||
{ node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); }
|
||||
};
|
||||
|
||||
template<class T, class NodePool, unsigned int Version>
|
||||
class cached_allocator_impl
|
||||
: public array_allocation_impl
|
||||
<cached_allocator_impl<T, NodePool, Version>, T, typename NodePool::segment_manager>
|
||||
{
|
||||
cached_allocator_impl & operator=(const cached_allocator_impl& other);
|
||||
typedef array_allocation_impl
|
||||
< cached_allocator_impl
|
||||
<T, NodePool, Version>
|
||||
, T
|
||||
, typename NodePool::segment_manager> base_t;
|
||||
|
||||
public:
|
||||
typedef NodePool node_pool_t;
|
||||
typedef typename NodePool::segment_manager segment_manager;
|
||||
typedef typename segment_manager::void_pointer void_pointer;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<void_pointer>::template
|
||||
rebind_pointer<const void>::type cvoid_pointer;
|
||||
typedef typename base_t::pointer pointer;
|
||||
typedef typename base_t::size_type size_type;
|
||||
typedef typename base_t::multiallocation_chain multiallocation_chain;
|
||||
typedef typename base_t::value_type value_type;
|
||||
|
||||
public:
|
||||
static const std::size_t DEFAULT_MAX_CACHED_NODES = 64;
|
||||
|
||||
cached_allocator_impl(segment_manager *segment_mngr, size_type max_cached_nodes)
|
||||
: m_cache(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
cached_allocator_impl(const cached_allocator_impl &other)
|
||||
: m_cache(other.m_cache)
|
||||
{}
|
||||
|
||||
//!Copy constructor from related cached_adaptive_pool_base. If not present, constructs
|
||||
//!a node pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
template<class T2, class NodePool2>
|
||||
cached_allocator_impl
|
||||
(const cached_allocator_impl
|
||||
<T2, NodePool2, Version> &other)
|
||||
: m_cache(other.get_segment_manager(), other.get_max_cached_nodes())
|
||||
{}
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
node_pool_t* get_node_pool() const
|
||||
{ return m_cache.get_node_pool(); }
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const
|
||||
{ return m_cache.get_segment_manager(); }
|
||||
|
||||
//!Sets the new max cached nodes value. This can provoke deallocations
|
||||
//!if "newmax" is less than current cached nodes. Never throws
|
||||
void set_max_cached_nodes(size_type newmax)
|
||||
{ m_cache.set_max_cached_nodes(newmax); }
|
||||
|
||||
//!Returns the max cached nodes parameter.
|
||||
//!Never throws
|
||||
size_type get_max_cached_nodes() const
|
||||
{ return m_cache.get_max_cached_nodes(); }
|
||||
|
||||
//!Allocate memory for an array of count elements.
|
||||
//!Throws boost::interprocess::bad_alloc if there is no enough memory
|
||||
pointer allocate(size_type count, cvoid_pointer hint = 0)
|
||||
{
|
||||
(void)hint;
|
||||
void * ret;
|
||||
if(size_overflows<sizeof(T)>(count)){
|
||||
throw bad_alloc();
|
||||
}
|
||||
else if(Version == 1 && count == 1){
|
||||
ret = m_cache.cached_allocation();
|
||||
}
|
||||
else{
|
||||
ret = this->get_segment_manager()->allocate(count*sizeof(T));
|
||||
}
|
||||
return pointer(static_cast<T*>(ret));
|
||||
}
|
||||
|
||||
//!Deallocate allocated memory. Never throws
|
||||
void deallocate(const pointer &ptr, size_type count)
|
||||
{
|
||||
(void)count;
|
||||
if(Version == 1 && count == 1){
|
||||
m_cache.cached_deallocation(ipcdetail::to_raw_pointer(ptr));
|
||||
}
|
||||
else{
|
||||
this->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr));
|
||||
}
|
||||
}
|
||||
|
||||
//!Allocates just one object. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
//!Throws boost::interprocess::bad_alloc if there is no enough memory
|
||||
pointer allocate_one()
|
||||
{ return pointer(static_cast<value_type*>(this->m_cache.cached_allocation())); }
|
||||
|
||||
//!Allocates many elements of size == 1 in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
void allocate_individual(size_type num_elements, multiallocation_chain &chain)
|
||||
{ this->m_cache.cached_allocation(num_elements, chain); }
|
||||
|
||||
//!Deallocates memory previously allocated with allocate_one().
|
||||
//!You should never use deallocate_one to deallocate memory allocated
|
||||
//!with other functions different from allocate_one(). Never throws
|
||||
void deallocate_one(const pointer &p)
|
||||
{ this->m_cache.cached_deallocation(ipcdetail::to_raw_pointer(p)); }
|
||||
|
||||
//!Allocates many elements of size == 1 in a contiguous block
|
||||
//!of memory. The minimum number to be allocated is min_elements,
|
||||
//!the preferred and maximum number is
|
||||
//!preferred_elements. The number of actually allocated elements is
|
||||
//!will be assigned to received_size. Memory allocated with this function
|
||||
//!must be deallocated only with deallocate_one().
|
||||
void deallocate_individual(multiallocation_chain &chain)
|
||||
{ m_cache.cached_deallocation(chain); }
|
||||
|
||||
//!Deallocates all free blocks of the pool
|
||||
void deallocate_free_blocks()
|
||||
{ m_cache.get_node_pool()->deallocate_free_blocks(); }
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different shared memory segments, the result is undefined.
|
||||
friend void swap(cached_allocator_impl &alloc1, cached_allocator_impl &alloc2)
|
||||
{ alloc1.m_cache.swap(alloc2.m_cache); }
|
||||
|
||||
void deallocate_cache()
|
||||
{ m_cache.deallocate_all_cached_nodes(); }
|
||||
|
||||
//!Deprecated use deallocate_free_blocks.
|
||||
void deallocate_free_chunks()
|
||||
{ m_cache.get_node_pool()->deallocate_free_blocks(); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
cache_impl<node_pool_t> m_cache;
|
||||
};
|
||||
|
||||
//!Equality test for same type of
|
||||
//!cached_allocator_impl
|
||||
template<class T, class N, unsigned int V> inline
|
||||
bool operator==(const cached_allocator_impl<T, N, V> &alloc1,
|
||||
const cached_allocator_impl<T, N, V> &alloc2)
|
||||
{ return alloc1.get_node_pool() == alloc2.get_node_pool(); }
|
||||
|
||||
//!Inequality test for same type of
|
||||
//!cached_allocator_impl
|
||||
template<class T, class N, unsigned int V> inline
|
||||
bool operator!=(const cached_allocator_impl<T, N, V> &alloc1,
|
||||
const cached_allocator_impl<T, N, V> &alloc2)
|
||||
{ return alloc1.get_node_pool() != alloc2.get_node_pool(); }
|
||||
|
||||
|
||||
//!Pooled shared memory allocator using adaptive pool. Includes
|
||||
//!a reference count but the class does not delete itself, this is
|
||||
//!responsibility of user classes. Node size (NodeSize) and the number of
|
||||
//!nodes allocated per block (NodesPerBlock) are known at compile time
|
||||
template<class private_node_allocator_t>
|
||||
class shared_pool_impl
|
||||
: public private_node_allocator_t
|
||||
{
|
||||
public:
|
||||
//!Segment manager typedef
|
||||
typedef typename private_node_allocator_t::
|
||||
segment_manager segment_manager;
|
||||
typedef typename private_node_allocator_t::
|
||||
multiallocation_chain multiallocation_chain;
|
||||
typedef typename private_node_allocator_t::
|
||||
size_type size_type;
|
||||
|
||||
private:
|
||||
typedef typename segment_manager::mutex_family::mutex_type mutex_type;
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. Never throws
|
||||
shared_pool_impl(segment_manager *segment_mngr)
|
||||
: private_node_allocator_t(segment_mngr)
|
||||
{}
|
||||
|
||||
//!Destructor. Deallocates all allocated blocks. Never throws
|
||||
~shared_pool_impl()
|
||||
{}
|
||||
|
||||
//!Allocates array of count elements. Can throw boost::interprocess::bad_alloc
|
||||
void *allocate_node()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::allocate_node();
|
||||
}
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
void deallocate_node(void *ptr)
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_node(ptr);
|
||||
}
|
||||
|
||||
//!Allocates n nodes.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
void allocate_nodes(const size_type n, multiallocation_chain &chain)
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::allocate_nodes(n, chain);
|
||||
}
|
||||
|
||||
//!Deallocates a linked list of nodes ending in null pointer. Never throws
|
||||
void deallocate_nodes(multiallocation_chain &nodes, size_type num)
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_nodes(nodes, num);
|
||||
}
|
||||
|
||||
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
|
||||
void deallocate_nodes(multiallocation_chain &chain)
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_nodes(chain);
|
||||
}
|
||||
|
||||
//!Deallocates all the free blocks of memory. Never throws
|
||||
void deallocate_free_blocks()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_free_blocks();
|
||||
}
|
||||
|
||||
//!Deallocates all used memory from the common pool.
|
||||
//!Precondition: all nodes allocated from this pool should
|
||||
//!already be deallocated. Otherwise, undefined behavior. Never throws
|
||||
void purge_blocks()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::purge_blocks();
|
||||
}
|
||||
|
||||
//!Increments internal reference count and returns new count. Never throws
|
||||
size_type inc_ref_count()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
return ++m_header.m_usecount;
|
||||
}
|
||||
|
||||
//!Decrements internal reference count and returns new count. Never throws
|
||||
size_type dec_ref_count()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
BOOST_ASSERT(m_header.m_usecount > 0);
|
||||
return --m_header.m_usecount;
|
||||
}
|
||||
|
||||
//!Deprecated, use deallocate_free_blocks.
|
||||
void deallocate_free_chunks()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::deallocate_free_blocks();
|
||||
}
|
||||
|
||||
//!Deprecated, use purge_blocks.
|
||||
void purge_chunks()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
private_node_allocator_t::purge_blocks();
|
||||
}
|
||||
|
||||
private:
|
||||
//!This struct includes needed data and derives from
|
||||
//!the mutex type to allow EBO when using null_mutex
|
||||
struct header_t : mutex_type
|
||||
{
|
||||
size_type m_usecount; //Number of attached allocators
|
||||
|
||||
header_t()
|
||||
: m_usecount(0) {}
|
||||
} m_header;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
|
@ -0,0 +1,40 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_ALLOCATION_TYPE_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/allocation_type.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
typedef int allocation_type;
|
||||
/// @endcond
|
||||
static const allocation_type allocate_new = boost::container::allocate_new;
|
||||
static const allocation_type expand_fwd = boost::container::expand_fwd;
|
||||
static const allocation_type expand_bwd = boost::container::expand_bwd;
|
||||
static const allocation_type shrink_in_place = boost::container::shrink_in_place;
|
||||
static const allocation_type try_shrink_in_place= boost::container::try_shrink_in_place;
|
||||
static const allocation_type nothrow_allocation = boost::container::nothrow_allocation;
|
||||
static const allocation_type zero_memory = boost::container::zero_memory;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
|
@ -0,0 +1,33 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-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_CONTAINERS_VERSION_TYPE_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/version_type.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::container::container_detail::version_type;
|
||||
using boost::container::container_detail::version;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
|
||||
|
77
cpp/BoostParts/boost/interprocess/creation_tags.hpp
Normal file
77
cpp/BoostParts/boost/interprocess/creation_tags.hpp
Normal file
@ -0,0 +1,77 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_CREATION_TAGS_HPP
|
||||
#define BOOST_INTERPROCESS_CREATION_TAGS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!Tag to indicate that the resource must
|
||||
//!be only created
|
||||
struct create_only_t {};
|
||||
|
||||
//!Tag to indicate that the resource must
|
||||
//!be only opened
|
||||
struct open_only_t {};
|
||||
|
||||
//!Tag to indicate that the resource must
|
||||
//!be only opened for reading
|
||||
struct open_read_only_t {};
|
||||
|
||||
//!Tag to indicate that the resource must
|
||||
//!be only opened privately for reading
|
||||
struct open_read_private_t {};
|
||||
|
||||
//!Tag to indicate that the resource must
|
||||
//!be only opened for reading
|
||||
struct open_copy_on_write_t {};
|
||||
|
||||
//!Tag to indicate that the resource must
|
||||
//!be created. If already created, it must be opened.
|
||||
struct open_or_create_t {};
|
||||
|
||||
//!Value to indicate that the resource must
|
||||
//!be only created
|
||||
static const create_only_t create_only = create_only_t();
|
||||
|
||||
//!Value to indicate that the resource must
|
||||
//!be only opened
|
||||
static const open_only_t open_only = open_only_t();
|
||||
|
||||
//!Value to indicate that the resource must
|
||||
//!be only opened for reading
|
||||
static const open_read_only_t open_read_only = open_read_only_t();
|
||||
|
||||
//!Value to indicate that the resource must
|
||||
//!be created. If already created, it must be opened.
|
||||
static const open_or_create_t open_or_create = open_or_create_t();
|
||||
|
||||
//!Value to indicate that the resource must
|
||||
//!be only opened for reading
|
||||
static const open_copy_on_write_t open_copy_on_write = open_copy_on_write_t();
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
enum create_enum_t
|
||||
{ DoCreate, DoOpen, DoOpenOrCreate };
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP
|
||||
|
562
cpp/BoostParts/boost/interprocess/detail/atomic.hpp
Normal file
562
cpp/BoostParts/boost/interprocess/detail/atomic.hpp
Normal file
@ -0,0 +1,562 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-2012
|
||||
// (C) Copyright Markus Schoepflin 2007
|
||||
// (C) Copyright Bryce Lelbach 2010
|
||||
//
|
||||
// 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_ATOMIC_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically increment an boost::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);
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem);
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val);
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with": what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp);
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return 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; }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val); }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with": what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{ return winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp); }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
boost::uint32_t prev = cmp;
|
||||
// This version by Mans Rullgard of Pathscale
|
||||
__asm__ __volatile__ ( "lock\n\t"
|
||||
"cmpxchg %2,%0"
|
||||
: "+m"(*mem), "+a"(prev)
|
||||
: "r"(with)
|
||||
: "cc");
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{
|
||||
// int r = *pw;
|
||||
// *mem += val;
|
||||
// return r;
|
||||
int r;
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"lock\n\t"
|
||||
"xadd %1, %0":
|
||||
"+m"( *mem ), "=r"( r ): // outputs (%0, %1)
|
||||
"1"( val ): // inputs (%2 == %1)
|
||||
"memory", "cc" // clobbers
|
||||
);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, (boost::uint32_t)-1); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{
|
||||
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");
|
||||
return prev;
|
||||
}
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
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"(cmp), "r" (with)
|
||||
: "cc", "memory");
|
||||
return prev;
|
||||
}
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, boost::uint32_t(-1u)); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif (defined(sun) || defined(__sun))
|
||||
|
||||
#include <atomic.h>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (int32_t)val) - val; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{ return atomic_cas_32(reinterpret_cast<volatile ::uint32_t*>(mem), cmp, with); }
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), 1) - 1; }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (boost::uint32_t)-1) + 1; }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__osf__) && defined(__DECCXX)
|
||||
|
||||
#include <machine/builtins.h>
|
||||
#include <c_asm.h>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically decrement a uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
//! Acquire, memory barrier after decrement.
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ boost::uint32_t old_val = __ATOMIC_DECREMENT_LONG(mem); __MB(); return old_val; }
|
||||
|
||||
//! Atomically increment a uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
//! Release, memory barrier before increment.
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ __MB(); return __ATOMIC_INCREMENT_LONG(mem); }
|
||||
|
||||
// Rational for the implementation of the atomic read and write functions.
|
||||
//
|
||||
// 1. The Alpha Architecture Handbook requires that access to a byte,
|
||||
// an aligned word, an aligned longword, or an aligned quadword is
|
||||
// atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.)
|
||||
//
|
||||
// 2. The CXX User's Guide states that volatile quantities are accessed
|
||||
// with single assembler instructions, and that a compilation error
|
||||
// occurs when declaring a quantity as volatile which is not properly
|
||||
// aligned.
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
//! Acquire, memory barrier after load.
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ boost::uint32_t old_val = *mem; __MB(); return old_val; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
//! Release, memory barrier before store.
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ __MB(); *mem = val; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
//! Memory barrier between load and store.
|
||||
inline boost::uint32_t atomic_cas32(
|
||||
volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
// Note:
|
||||
//
|
||||
// Branch prediction prefers backward branches, and the Alpha Architecture
|
||||
// Handbook explicitely states that the loop should not be implemented like
|
||||
// it is below. (See chapter 4.2.5.) Therefore the code should probably look
|
||||
// like this:
|
||||
//
|
||||
// return asm(
|
||||
// "10: ldl_l %v0,(%a0) ;"
|
||||
// " cmpeq %v0,%a2,%t0 ;"
|
||||
// " beq %t0,20f ;"
|
||||
// " mb ;"
|
||||
// " mov %a1,%t0 ;"
|
||||
// " stl_c %t0,(%a0) ;"
|
||||
// " beq %t0,30f ;"
|
||||
// "20: ret ;"
|
||||
// "30: br 10b;",
|
||||
// mem, with, cmp);
|
||||
//
|
||||
// But as the compiler always transforms this into the form where a backward
|
||||
// branch is taken on failure, we can as well implement it in the straight
|
||||
// forward form, as this is what it will end up in anyway.
|
||||
|
||||
return asm(
|
||||
"10: ldl_l %v0,(%a0) ;" // load prev value from mem and lock mem
|
||||
" cmpeq %v0,%a2,%t0 ;" // compare with given value
|
||||
" beq %t0,20f ;" // if not equal, we're done
|
||||
" mb ;" // memory barrier
|
||||
" mov %a1,%t0 ;" // load new value into scratch register
|
||||
" stl_c %t0,(%a0) ;" // store new value to locked mem (overwriting scratch)
|
||||
" beq %t0,10b ;" // store failed because lock has been stolen, retry
|
||||
"20: ",
|
||||
mem, with, cmp);
|
||||
}
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX)
|
||||
|
||||
#include <builtins.h>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting
|
||||
//all the functions with casts
|
||||
|
||||
//! From XLC documenation :
|
||||
//! This function can be used with a subsequent stwcxu call to implement a
|
||||
//! read-modify-write on a specified memory location. The two functions work
|
||||
//! together to ensure that if the store is successfully performed, no other
|
||||
//! processor or mechanism can modify the target doubleword between the time
|
||||
//! lwarxu function is executed and the time the stwcxu functio ncompletes.
|
||||
//! "mem" : pointer to the object
|
||||
//! Returns the value at pointed to by mem
|
||||
inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem)
|
||||
{
|
||||
return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem)));
|
||||
}
|
||||
|
||||
//! "mem" : pointer to the object
|
||||
//! "val" : the value to store
|
||||
//! Returns true if the update of mem is successful and false if it is
|
||||
//!unsuccessful
|
||||
inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val)
|
||||
{
|
||||
return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0);
|
||||
}
|
||||
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{
|
||||
boost::uint32_t oldValue;
|
||||
do
|
||||
{
|
||||
oldValue = lwarxu(mem);
|
||||
}while (!stwcxu(mem, oldValue+val));
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, (boost::uint32_t)-1); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
boost::uint32_t oldValue;
|
||||
boost::uint32_t valueToStore;
|
||||
do
|
||||
{
|
||||
oldValue = lwarxu(mem);
|
||||
} while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue));
|
||||
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); }
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, (boost::uint32_t)-1); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#else
|
||||
|
||||
#error No atomic operations implemented for this platform, sorry!
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
inline bool atomic_add_unless32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t value, boost::uint32_t unless_this)
|
||||
{
|
||||
boost::uint32_t old, c(atomic_read32(mem));
|
||||
while(c != unless_this && (old = atomic_cas32(mem, c + value, c)) != c){
|
||||
c = old;
|
||||
}
|
||||
return c != unless_this;
|
||||
}
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
|
29
cpp/BoostParts/boost/interprocess/detail/cast_tags.hpp
Normal file
29
cpp/BoostParts/boost/interprocess/detail/cast_tags.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_CAST_TAGS_HPP
|
||||
#define BOOST_INTERPROCESS_CAST_TAGS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
struct static_cast_tag {};
|
||||
struct const_cast_tag {};
|
||||
struct dynamic_cast_tag {};
|
||||
struct reinterpret_cast_tag {};
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
|
||||
|
48
cpp/BoostParts/boost/interprocess/detail/config_begin.hpp
Normal file
48
cpp/BoostParts/boost/interprocess/detail/config_begin.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_CONFIG_INCLUDED
|
||||
#define BOOST_INTERPROCESS_CONFIG_INCLUDED
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4702) // unreachable code
|
||||
#pragma warning (disable : 4706) // assignment within conditional expression
|
||||
#pragma warning (disable : 4127) // conditional expression is constant
|
||||
#pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning (disable : 4284) // odd return type for operator->
|
||||
#pragma warning (disable : 4244) // possible loss of data
|
||||
#pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
|
||||
#pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
|
||||
#pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
|
||||
#pragma warning (disable : 4355) // "this" : used in base member initializer list
|
||||
#pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
|
||||
#pragma warning (disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning (disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning (disable : 4514) // unreferenced inline removed
|
||||
#pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
|
||||
#pragma warning (disable : 4522) // "class" : multiple assignment operators specified
|
||||
#pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
|
||||
#pragma warning (disable : 4710) // function not inlined
|
||||
#pragma warning (disable : 4711) // function selected for automatic inline expansion
|
||||
#pragma warning (disable : 4786) // identifier truncated in debug info
|
||||
#pragma warning (disable : 4996) // "function": was declared deprecated
|
||||
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
|
||||
#pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
|
||||
// with /GR-; unpredictable behavior may result
|
||||
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
|
||||
#pragma warning (disable : 4671) // the copy constructor is inaccessible
|
||||
#pragma warning (disable : 4250) // inherits 'x' via dominance
|
||||
#endif
|
17
cpp/BoostParts/boost/interprocess/detail/config_end.hpp
Normal file
17
cpp/BoostParts/boost/interprocess/detail/config_end.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#if defined BOOST_MSVC
|
||||
#pragma warning (pop)
|
||||
#ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
|
||||
#undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
|
||||
#undef _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
#endif
|
||||
|
@ -0,0 +1,18 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-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_EXTERNAL_CONFIG_INCLUDED
|
||||
#define BOOST_INTERPROCESS_EXTERNAL_CONFIG_INCLUDED
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
@ -0,0 +1,12 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
@ -0,0 +1,73 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_IN_PLACE_INTERFACE_HPP
|
||||
#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <typeinfo> //typeid
|
||||
|
||||
//!\file
|
||||
//!Describes an abstract interface for placement construction and destruction.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
struct in_place_interface
|
||||
{
|
||||
in_place_interface(std::size_t alignm, std::size_t sz, const char *tname)
|
||||
: alignment(alignm), size(sz), type_name(tname)
|
||||
{}
|
||||
|
||||
std::size_t alignment;
|
||||
std::size_t size;
|
||||
const char *type_name;
|
||||
|
||||
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) = 0;
|
||||
virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) = 0;
|
||||
virtual ~in_place_interface(){}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct placement_destroy : public in_place_interface
|
||||
{
|
||||
placement_destroy()
|
||||
: in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name())
|
||||
{}
|
||||
|
||||
virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed)
|
||||
{
|
||||
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 &) {}
|
||||
|
||||
private:
|
||||
void destroy(void *mem)
|
||||
{ static_cast<T*>(mem)->~T(); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
|
@ -0,0 +1,496 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
|
||||
#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
namespace intermodule_singleton_helpers {
|
||||
|
||||
inline void get_pid_creation_time_str(std::string &s)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << get_current_process_id() << '_';
|
||||
stream.precision(6);
|
||||
stream << std::fixed << get_current_process_creation_time();
|
||||
s = stream.str();
|
||||
}
|
||||
|
||||
inline const char *get_map_base_name()
|
||||
{ return "bip.gmem.map."; }
|
||||
|
||||
inline void get_map_name(std::string &map_name)
|
||||
{
|
||||
get_pid_creation_time_str(map_name);
|
||||
map_name.insert(0, get_map_base_name());
|
||||
}
|
||||
|
||||
inline std::size_t get_map_size()
|
||||
{ return 65536; }
|
||||
|
||||
template<class ThreadSafeGlobalMap>
|
||||
struct thread_safe_global_map_dependant;
|
||||
|
||||
} //namespace intermodule_singleton_helpers {
|
||||
|
||||
//This class contains common code for all singleton types, so that we instantiate this
|
||||
//code just once per module. This class also holds a thread soafe global map
|
||||
//to be used by all instances protected with a reference count
|
||||
template<class ThreadSafeGlobalMap>
|
||||
class intermodule_singleton_common
|
||||
{
|
||||
public:
|
||||
typedef void*(singleton_constructor_t)(ThreadSafeGlobalMap &);
|
||||
typedef void (singleton_destructor_t)(void *, ThreadSafeGlobalMap &);
|
||||
|
||||
static const ::boost::uint32_t Uninitialized = 0u;
|
||||
static const ::boost::uint32_t Initializing = 1u;
|
||||
static const ::boost::uint32_t Initialized = 2u;
|
||||
static const ::boost::uint32_t Broken = 3u;
|
||||
static const ::boost::uint32_t Destroyed = 4u;
|
||||
|
||||
//Initialize this_module_singleton_ptr, creates the global map if needed and also creates an unique
|
||||
//opaque type in global map through a singleton_constructor_t function call,
|
||||
//initializing the passed pointer to that unique instance.
|
||||
//
|
||||
//We have two concurrency types here. a)the global map/singleton creation must
|
||||
//be safe between threads of this process but in different modules/dlls. b)
|
||||
//the pointer to the singleton is per-module, so we have to protect this
|
||||
//initization between threads of the same module.
|
||||
//
|
||||
//All static variables declared here are shared between inside a module
|
||||
//so atomic operations will synchronize only threads of the same module.
|
||||
static void initialize_singleton_logic
|
||||
(void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor, bool phoenix)
|
||||
{
|
||||
//If current module is not initialized enter to lock free logic
|
||||
if(atomic_read32(&this_module_singleton_initialized) != Initialized){
|
||||
//Now a single thread of the module will succeed in this CAS.
|
||||
//trying to pass from Uninitialized to Initializing
|
||||
::boost::uint32_t previous_module_singleton_initialized = atomic_cas32
|
||||
(&this_module_singleton_initialized, Initializing, Uninitialized);
|
||||
//If the thread succeeded the CAS (winner) it will compete with other
|
||||
//winner threads from other modules to create the global map
|
||||
if(previous_module_singleton_initialized == Destroyed){
|
||||
//Trying to resurrect a dead Phoenix singleton. Just try to
|
||||
//mark it as uninitialized and start again
|
||||
if(phoenix){
|
||||
atomic_cas32(&this_module_singleton_initialized, Uninitialized, Destroyed);
|
||||
previous_module_singleton_initialized = atomic_cas32
|
||||
(&this_module_singleton_initialized, Initializing, Uninitialized);
|
||||
}
|
||||
//Trying to resurrect a non-Phoenix dead singleton is an error
|
||||
else{
|
||||
throw interprocess_exception("Boost.Interprocess: Dead reference on non-Phoenix singleton of type");
|
||||
}
|
||||
}
|
||||
if(previous_module_singleton_initialized == Uninitialized){
|
||||
try{
|
||||
//Now initialize the global map, this function must solve concurrency
|
||||
//issues between threads of several modules
|
||||
initialize_global_map_handle();
|
||||
//Now try to create the singleton in global map.
|
||||
//This function solves concurrency issues
|
||||
//between threads of several modules
|
||||
void *tmp = constructor(get_map());
|
||||
//Increment the module reference count that reflects how many
|
||||
//singletons this module holds, so that we can safely destroy
|
||||
//module global map object when no singleton is left
|
||||
atomic_inc32(&this_module_singleton_count);
|
||||
//Insert a barrier before assigning the pointer to
|
||||
//make sure this assignment comes after the initialization
|
||||
atomic_write32(&this_module_singleton_initialized, Initializing);
|
||||
//Assign the singleton address to the module-local pointer
|
||||
ptr = tmp;
|
||||
//Memory barrier inserted, all previous operations should complete
|
||||
//before this one. Now marked as initialized
|
||||
atomic_write32(&this_module_singleton_initialized, Initialized);
|
||||
}
|
||||
catch(...){
|
||||
//Mark singleton failed to initialize
|
||||
atomic_write32(&this_module_singleton_initialized, Broken);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
//If previous state was initializing, this means that another winner thread is
|
||||
//trying to initialize the singleton. Just wait until completes its work.
|
||||
else if(previous_module_singleton_initialized == Initializing){
|
||||
while(1){
|
||||
previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
|
||||
if(previous_module_singleton_initialized >= Initialized){
|
||||
//Already initialized, or exception thrown by initializer thread
|
||||
break;
|
||||
}
|
||||
else if(previous_module_singleton_initialized == Initializing){
|
||||
thread_yield();
|
||||
}
|
||||
else{
|
||||
//This can't be happening!
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(previous_module_singleton_initialized == Initialized){
|
||||
//Nothing to do here, the singleton is ready
|
||||
}
|
||||
//If previous state was greater than initialized, then memory is broken
|
||||
//trying to initialize the singleton.
|
||||
else{//(previous_module_singleton_initialized > Initialized)
|
||||
throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed");
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(ptr != 0);
|
||||
}
|
||||
|
||||
static void finalize_singleton_logic(void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_destructor_t destructor)
|
||||
{
|
||||
//Protect destruction against lazy singletons not initialized in this execution
|
||||
if(ptr){
|
||||
//Note: this destructor might provoke a Phoenix singleton
|
||||
//resurrection. This means that this_module_singleton_count
|
||||
//might change after this call.
|
||||
destructor(ptr, get_map());
|
||||
ptr = 0;
|
||||
|
||||
//Memory barrier to make sure pointer is nulled.
|
||||
//Mark this singleton as destroyed.
|
||||
atomic_write32(&this_module_singleton_initialized, Destroyed);
|
||||
|
||||
//If this is the last singleton of this module
|
||||
//apply map destruction.
|
||||
//Note: singletons are destroyed when the module is unloaded
|
||||
//so no threads should be executing or holding references
|
||||
//to this module
|
||||
if(1 == atomic_dec32(&this_module_singleton_count)){
|
||||
destroy_global_map_handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static ThreadSafeGlobalMap &get_map()
|
||||
{
|
||||
return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem[0]));
|
||||
}
|
||||
|
||||
static void initialize_global_map_handle()
|
||||
{
|
||||
//Obtain unique map name and size
|
||||
while(1){
|
||||
//Try to pass map state to initializing
|
||||
::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
|
||||
if(tmp == Initialized || tmp == Broken){
|
||||
break;
|
||||
}
|
||||
else if(tmp == Destroyed){
|
||||
tmp = atomic_cas32(&this_module_map_initialized, Uninitialized, Destroyed);
|
||||
continue;
|
||||
}
|
||||
//If some other thread is doing the work wait
|
||||
else if(tmp == Initializing){
|
||||
thread_yield();
|
||||
}
|
||||
else{ //(tmp == Uninitialized)
|
||||
//If not initialized try it again?
|
||||
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
|
||||
intermodule_singleton_helpers::thread_safe_global_map_dependant
|
||||
<ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map()));
|
||||
//Use global map's internal lock to initialize the lock file
|
||||
//that will mark this gmem as "in use".
|
||||
typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
|
||||
lock_file_logic f(get_map());
|
||||
//If function failed (maybe a competing process has erased the shared
|
||||
//memory between creation and file locking), retry with a new instance.
|
||||
if(f.retry()){
|
||||
get_map().~ThreadSafeGlobalMap();
|
||||
atomic_write32(&this_module_map_initialized, Destroyed);
|
||||
}
|
||||
else{
|
||||
//Locking succeeded, so this global map module-instance is ready
|
||||
atomic_write32(&this_module_map_initialized, Initialized);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(...){
|
||||
//
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_global_map_handle()
|
||||
{
|
||||
if(!atomic_read32(&this_module_singleton_count)){
|
||||
//This module is being unloaded, so destroy
|
||||
//the global map object of this module
|
||||
//and unlink the global map if it's the last
|
||||
typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
|
||||
unlink_map_logic f(get_map());
|
||||
(get_map()).~ThreadSafeGlobalMap();
|
||||
atomic_write32(&this_module_map_initialized, Destroyed);
|
||||
//Do some cleanup for other processes old gmem instances
|
||||
intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
|
||||
}
|
||||
}
|
||||
|
||||
//Static data, zero-initalized without any dependencies
|
||||
//this_module_singleton_count is the number of singletons used by this module
|
||||
static volatile boost::uint32_t this_module_singleton_count;
|
||||
|
||||
//this_module_map_initialized is the state of this module's map class object.
|
||||
//Values: Uninitialized, Initializing, Initialized, Broken
|
||||
static volatile boost::uint32_t this_module_map_initialized;
|
||||
|
||||
//Raw memory to construct the global map manager
|
||||
static struct mem_holder_t
|
||||
{
|
||||
::boost::detail::max_align aligner;
|
||||
char map_mem [sizeof(ThreadSafeGlobalMap)];
|
||||
} mem_holder;
|
||||
};
|
||||
|
||||
template<class ThreadSafeGlobalMap>
|
||||
volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_singleton_count;
|
||||
|
||||
template<class ThreadSafeGlobalMap>
|
||||
volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_map_initialized;
|
||||
|
||||
template<class ThreadSafeGlobalMap>
|
||||
typename intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder_t
|
||||
intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder;
|
||||
|
||||
//A reference count to be stored in global map holding the number
|
||||
//of singletons (one per module) attached to the instance pointed by
|
||||
//the internal ptr.
|
||||
struct ref_count_ptr
|
||||
{
|
||||
ref_count_ptr(void *p, boost::uint32_t count)
|
||||
: ptr(p), singleton_ref_count(count)
|
||||
{}
|
||||
void *ptr;
|
||||
//This reference count serves to count the number of attached
|
||||
//modules to this singleton
|
||||
volatile boost::uint32_t singleton_ref_count;
|
||||
};
|
||||
|
||||
|
||||
//Now this class is a singleton, initializing the singleton in
|
||||
//the first get() function call if LazyInit is false. If true
|
||||
//then the singleton will be initialized when loading the module.
|
||||
template<typename C, bool LazyInit, bool Phoenix, class ThreadSafeGlobalMap>
|
||||
class intermodule_singleton_impl
|
||||
{
|
||||
public:
|
||||
|
||||
static C& get() //Let's make inlining easy
|
||||
{
|
||||
if(!this_module_singleton_ptr){
|
||||
if(lifetime.dummy_function()){ //This forces lifetime instantiation, for reference counted destruction
|
||||
atentry_work();
|
||||
}
|
||||
}
|
||||
return *static_cast<C*>(this_module_singleton_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void atentry_work()
|
||||
{
|
||||
intermodule_singleton_common<ThreadSafeGlobalMap>::initialize_singleton_logic
|
||||
(this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor, Phoenix);
|
||||
}
|
||||
|
||||
static void atexit_work()
|
||||
{
|
||||
intermodule_singleton_common<ThreadSafeGlobalMap>::finalize_singleton_logic
|
||||
(this_module_singleton_ptr, this_module_singleton_initialized, singleton_destructor);
|
||||
}
|
||||
|
||||
//These statics will be zero-initialized without any constructor call dependency
|
||||
//this_module_singleton_ptr will be a module-local pointer to the singleton
|
||||
static void* this_module_singleton_ptr;
|
||||
|
||||
//this_module_singleton_count will be used to synchronize threads of the same module
|
||||
//for access to a singleton instance, and to flag the state of the
|
||||
//singleton.
|
||||
static volatile boost::uint32_t this_module_singleton_initialized;
|
||||
|
||||
//This class destructor will trigger singleton destruction
|
||||
struct lifetime_type_lazy
|
||||
{
|
||||
bool dummy_function()
|
||||
{ return m_dummy == 0; }
|
||||
|
||||
~lifetime_type_lazy()
|
||||
{
|
||||
if(!Phoenix){
|
||||
atexit_work();
|
||||
}
|
||||
}
|
||||
|
||||
//Dummy volatile so that the compiler can't resolve its value at compile-time
|
||||
//and can't avoid lifetime_type instantiation if dummy_function() is called.
|
||||
static volatile int m_dummy;
|
||||
};
|
||||
|
||||
struct lifetime_type_static
|
||||
: public lifetime_type_lazy
|
||||
{
|
||||
lifetime_type_static()
|
||||
{ atentry_work(); }
|
||||
};
|
||||
|
||||
typedef typename if_c
|
||||
<LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type;
|
||||
|
||||
static lifetime_type lifetime;
|
||||
|
||||
//A functor to be executed inside global map lock that just
|
||||
//searches for the singleton in map and if not present creates a new one.
|
||||
//If singleton constructor throws, the exception is propagated
|
||||
struct init_atomic_func
|
||||
{
|
||||
init_atomic_func(ThreadSafeGlobalMap &m)
|
||||
: m_map(m)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
|
||||
<ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
|
||||
if(!rcount){
|
||||
C *p = new C;
|
||||
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(...){
|
||||
intermodule_singleton_helpers::thread_safe_global_map_dependant
|
||||
<ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
|
||||
delete p;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if(Phoenix){
|
||||
std::atexit(&atexit_work);
|
||||
}
|
||||
atomic_inc32(&rcount->singleton_ref_count);
|
||||
ret_ptr = rcount->ptr;
|
||||
}
|
||||
void *data() const
|
||||
{ return ret_ptr; }
|
||||
|
||||
private:
|
||||
ThreadSafeGlobalMap &m_map;
|
||||
void *ret_ptr;
|
||||
};
|
||||
|
||||
//A functor to be executed inside global map lock that just
|
||||
//deletes the singleton in map if the attached count reaches to zero
|
||||
struct fini_atomic_func
|
||||
{
|
||||
fini_atomic_func(ThreadSafeGlobalMap &m)
|
||||
: m_map(m)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
|
||||
<ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
|
||||
//The object must exist
|
||||
BOOST_ASSERT(rcount);
|
||||
BOOST_ASSERT(rcount->singleton_ref_count > 0);
|
||||
//Check if last reference
|
||||
if(atomic_dec32(&rcount->singleton_ref_count) == 1){
|
||||
//If last, destroy the object
|
||||
BOOST_ASSERT(rcount->ptr != 0);
|
||||
C *pc = static_cast<C*>(rcount->ptr);
|
||||
//Now destroy map entry
|
||||
bool destroyed = intermodule_singleton_helpers::thread_safe_global_map_dependant
|
||||
<ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
|
||||
(void)destroyed; BOOST_ASSERT(destroyed == true);
|
||||
delete pc;
|
||||
}
|
||||
}
|
||||
void *data() const
|
||||
{ return ret_ptr; }
|
||||
|
||||
private:
|
||||
ThreadSafeGlobalMap &m_map;
|
||||
void *ret_ptr;
|
||||
};
|
||||
|
||||
//A wrapper to execute init_atomic_func
|
||||
static void *singleton_constructor(ThreadSafeGlobalMap &map)
|
||||
{
|
||||
init_atomic_func f(map);
|
||||
intermodule_singleton_helpers::thread_safe_global_map_dependant
|
||||
<ThreadSafeGlobalMap>::atomic_func(map, f);
|
||||
return f.data();
|
||||
}
|
||||
|
||||
//A wrapper to execute fini_atomic_func
|
||||
static void singleton_destructor(void *p, ThreadSafeGlobalMap &map)
|
||||
{ (void)p;
|
||||
fini_atomic_func f(map);
|
||||
intermodule_singleton_helpers::thread_safe_global_map_dependant
|
||||
<ThreadSafeGlobalMap>::atomic_func(map, f);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
|
||||
volatile int intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type_lazy::m_dummy = 0;
|
||||
|
||||
//These will be zero-initialized by the loader
|
||||
template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
|
||||
void *intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_ptr = 0;
|
||||
|
||||
template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
|
||||
volatile boost::uint32_t intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_initialized = 0;
|
||||
|
||||
template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
|
||||
typename intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type
|
||||
intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime;
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
|
@ -0,0 +1,31 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-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_INTERPROCESS_TESTER_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
class interprocess_tester
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
static void dont_close_on_destruction(T &t)
|
||||
{ t.dont_close_on_destruction(); }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
|
||||
|
776
cpp/BoostParts/boost/interprocess/detail/managed_memory_impl.hpp
Normal file
776
cpp/BoostParts/boost/interprocess/detail/managed_memory_impl.hpp
Normal file
@ -0,0 +1,776 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_MANAGED_MEMORY_IMPL_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/segment_manager.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
//
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
//
|
||||
#include <utility>
|
||||
#include <fstream>
|
||||
#include <new>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named shared memory allocation user class.
|
||||
//!
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class BasicManagedMemoryImpl>
|
||||
class create_open_func;
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class MemoryAlgorithm,
|
||||
template<class IndexConfig> class IndexType
|
||||
>
|
||||
struct segment_manager_type
|
||||
{
|
||||
typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
|
||||
};
|
||||
|
||||
//!This class is designed to be a base class to classes that manage
|
||||
//!creation of objects in a fixed size memory buffer. Apart
|
||||
//!from allocating raw memory, the user can construct named objects. To
|
||||
//!achieve this, this class uses the reserved space provided by the allocation
|
||||
//!algorithm to place a named_allocator_algo, who takes care of name mappings.
|
||||
//!The class can be customized with the char type used for object names
|
||||
//!and the memory allocation algorithm to be used.*/
|
||||
template < class CharType
|
||||
, class MemoryAlgorithm
|
||||
, template<class IndexConfig> class IndexType
|
||||
, std::size_t Offset = 0
|
||||
>
|
||||
class basic_managed_memory_impl
|
||||
{
|
||||
//Non-copyable
|
||||
basic_managed_memory_impl(const basic_managed_memory_impl &);
|
||||
basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
|
||||
|
||||
template<class BasicManagedMemoryImpl>
|
||||
friend class create_open_func;
|
||||
|
||||
public:
|
||||
typedef typename segment_manager_type
|
||||
<CharType, MemoryAlgorithm, IndexType>::type segment_manager;
|
||||
typedef CharType char_type;
|
||||
typedef MemoryAlgorithm memory_algorithm;
|
||||
typedef typename MemoryAlgorithm::mutex_family mutex_family;
|
||||
typedef CharType char_t;
|
||||
typedef typename MemoryAlgorithm::size_type size_type;
|
||||
typedef typename MemoryAlgorithm::difference_type difference_type;
|
||||
typedef difference_type handle_t;
|
||||
typedef typename segment_manager::
|
||||
const_named_iterator const_named_iterator;
|
||||
typedef typename segment_manager::
|
||||
const_unique_iterator const_unique_iterator;
|
||||
|
||||
/// @cond
|
||||
|
||||
typedef typename
|
||||
segment_manager::char_ptr_holder_t char_ptr_holder_t;
|
||||
//Experimental. Don't use.
|
||||
|
||||
typedef typename segment_manager::multiallocation_chain multiallocation_chain;
|
||||
|
||||
/// @endcond
|
||||
|
||||
static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
|
||||
|
||||
private:
|
||||
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)
|
||||
{
|
||||
typedef typename ManagedMemory::device_type device_type;
|
||||
//Increase file size
|
||||
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);
|
||||
}
|
||||
ManagedMemory managed_memory(open_only, filename);
|
||||
//Grow always works
|
||||
managed_memory.self_t::grow(extra_bytes);
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class ManagedMemory>
|
||||
static bool shrink_to_fit(const char *filename)
|
||||
{
|
||||
typedef typename ManagedMemory::device_type device_type;
|
||||
size_type new_size;
|
||||
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(...){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Decrease file size
|
||||
{
|
||||
device_type f(open_or_create, filename, read_write);
|
||||
f.truncate(new_size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//!Constructor. Allocates basic resources. Never throws.
|
||||
basic_managed_memory_impl()
|
||||
: mp_header(0){}
|
||||
|
||||
//!Destructor. Calls close. Never throws.
|
||||
~basic_managed_memory_impl()
|
||||
{ this->close_impl(); }
|
||||
|
||||
//!Places segment manager in the reserved space. This can throw.
|
||||
bool create_impl (void *addr, size_type size)
|
||||
{
|
||||
if(mp_header) return false;
|
||||
|
||||
//Check if there is enough space
|
||||
if(size < segment_manager::get_min_size())
|
||||
return false;
|
||||
|
||||
//This function should not throw. The index construction can
|
||||
//throw if constructor allocates memory. So we must catch it.
|
||||
BOOST_TRY{
|
||||
//Let's construct the allocator in memory
|
||||
mp_header = new(addr) segment_manager(size);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
return false;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return true;
|
||||
}
|
||||
|
||||
//!Connects to a segment manager in the reserved buffer. Never throws.
|
||||
bool open_impl (void *addr, size_type)
|
||||
{
|
||||
if(mp_header) return false;
|
||||
mp_header = static_cast<segment_manager*>(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//!Frees resources. Never throws.
|
||||
bool close_impl()
|
||||
{
|
||||
bool ret = mp_header != 0;
|
||||
mp_header = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//!Frees resources and destroys common resources. Never throws.
|
||||
bool destroy_impl()
|
||||
{
|
||||
if(mp_header == 0)
|
||||
return false;
|
||||
mp_header->~segment_manager();
|
||||
this->close_impl();
|
||||
return true;
|
||||
}
|
||||
|
||||
//!
|
||||
void grow(size_type extra_bytes)
|
||||
{ mp_header->grow(extra_bytes); }
|
||||
|
||||
void shrink_to_fit()
|
||||
{ mp_header->shrink_to_fit(); }
|
||||
|
||||
public:
|
||||
|
||||
//!Returns segment manager. Never throws.
|
||||
segment_manager *get_segment_manager() const
|
||||
{ return mp_header; }
|
||||
|
||||
//!Returns the base address of the memory in this process. Never throws.
|
||||
void * get_address () const
|
||||
{ return reinterpret_cast<char*>(mp_header) - Offset; }
|
||||
|
||||
//!Returns the size of memory segment. Never throws.
|
||||
size_type get_size () const
|
||||
{ return mp_header->get_size() + Offset; }
|
||||
|
||||
//!Returns the number of free bytes of the memory
|
||||
//!segment
|
||||
size_type get_free_memory() const
|
||||
{ return mp_header->get_free_memory(); }
|
||||
|
||||
//!Returns the result of "all_memory_deallocated()" function
|
||||
//!of the used memory algorithm
|
||||
bool all_memory_deallocated()
|
||||
{ return mp_header->all_memory_deallocated(); }
|
||||
|
||||
//!Returns the result of "check_sanity()" function
|
||||
//!of the used memory algorithm
|
||||
bool check_sanity()
|
||||
{ return mp_header->check_sanity(); }
|
||||
|
||||
//!Writes to zero free memory (memory not yet allocated) of
|
||||
//!the memory algorithm
|
||||
void zero_free_memory()
|
||||
{ mp_header->zero_free_memory(); }
|
||||
|
||||
//!Transforms an absolute address into an offset from base address.
|
||||
//!The address must belong to the memory segment. Never throws.
|
||||
handle_t get_handle_from_address (const void *ptr) const
|
||||
{
|
||||
return (handle_t)(reinterpret_cast<const char*>(ptr) -
|
||||
reinterpret_cast<const char*>(this->get_address()));
|
||||
}
|
||||
|
||||
//!Returns true if the address belongs to the managed memory segment
|
||||
bool belongs_to_segment (const void *ptr) const
|
||||
{
|
||||
return ptr >= this->get_address() &&
|
||||
ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
|
||||
}
|
||||
|
||||
//!Transforms previously obtained offset into an absolute address in the
|
||||
//!process space of the current process. Never throws.*/
|
||||
void * get_address_from_handle (handle_t offset) const
|
||||
{ return reinterpret_cast<char*>(this->get_address()) + offset; }
|
||||
|
||||
//!Searches for nbytes of free memory in the segment, marks the
|
||||
//!memory as used and return the pointer to the memory. If no
|
||||
//!memory is available throws a boost::interprocess::bad_alloc exception
|
||||
void* allocate (size_type nbytes)
|
||||
{ return mp_header->allocate(nbytes); }
|
||||
|
||||
//!Searches for nbytes of free memory in the segment, marks the
|
||||
//!memory as used and return the pointer to the memory. If no memory
|
||||
//!is available returns 0. Never throws.
|
||||
void* allocate (size_type nbytes, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate(nbytes, nothrow); }
|
||||
|
||||
//!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
|
||||
//!must be power of two. If no memory
|
||||
//!is available returns 0. Never throws.
|
||||
void * allocate_aligned (size_type nbytes, size_type alignment, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate_aligned(nbytes, alignment, nothrow); }
|
||||
|
||||
template<class T>
|
||||
std::pair<T *, bool>
|
||||
allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
|
||||
size_type preferred_size,size_type &received_size,
|
||||
T *reuse_ptr = 0)
|
||||
{
|
||||
return mp_header->allocation_command
|
||||
(command, limit_size, preferred_size, received_size, reuse_ptr);
|
||||
}
|
||||
|
||||
//!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
|
||||
//!must be power of two. If no
|
||||
//!memory is available throws a boost::interprocess::bad_alloc exception
|
||||
void * allocate_aligned(size_type nbytes, size_type alignment)
|
||||
{ return mp_header->allocate_aligned(nbytes, alignment); }
|
||||
|
||||
/// @cond
|
||||
|
||||
//Experimental. Don't use.
|
||||
|
||||
//!Allocates n_elements of elem_bytes bytes.
|
||||
//!Throws bad_alloc on failure. chain.size() is not increased on failure.
|
||||
void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
|
||||
{ mp_header->allocate_many(elem_bytes, n_elements, chain); }
|
||||
|
||||
//!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
|
||||
//!Throws bad_alloc on failure. chain.size() is not increased on failure.
|
||||
void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
|
||||
{ mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); }
|
||||
|
||||
//!Allocates n_elements of elem_bytes bytes.
|
||||
//!Non-throwing version. chain.size() is not increased on failure.
|
||||
void allocate_many(std::nothrow_t, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
|
||||
{ mp_header->allocate_many(std::nothrow_t(), elem_bytes, n_elements, chain); }
|
||||
|
||||
//!Allocates n_elements, each one of
|
||||
//!element_lengths[i]*sizeof_element bytes.
|
||||
//!Non-throwing version. chain.size() is not increased on failure.
|
||||
void allocate_many(std::nothrow_t, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
|
||||
{ mp_header->allocate_many(std::nothrow_t(), elem_sizes, n_elements, sizeof_element, chain); }
|
||||
|
||||
//!Deallocates all elements contained in chain.
|
||||
//!Never throws.
|
||||
void deallocate_many(multiallocation_chain &chain)
|
||||
{ mp_header->deallocate_many(chain); }
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!Marks previously allocated memory as free. Never throws.
|
||||
void deallocate (void *addr)
|
||||
{ if (mp_header) mp_header->deallocate(addr); }
|
||||
|
||||
//!Tries to find a previous named allocation address. Returns a memory
|
||||
//!buffer and the object count. If not found returned pointer is 0.
|
||||
//!Never throws.
|
||||
template <class T>
|
||||
std::pair<T*, size_type> find (char_ptr_holder_t name)
|
||||
{ return mp_header->template find<T>(name); }
|
||||
|
||||
//!Creates a named object or array in memory
|
||||
//!
|
||||
//!Allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
construct(char_ptr_holder_t name)
|
||||
{ return mp_header->template construct<T>(name); }
|
||||
|
||||
//!Finds or creates a named object or array in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
find_or_construct(char_ptr_holder_t name)
|
||||
{ return mp_header->template find_or_construct<T>(name); }
|
||||
|
||||
//!Creates a named object or array in memory
|
||||
//!
|
||||
//!Allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Returns 0 if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
construct(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template construct<T>(name, nothrow); }
|
||||
|
||||
//!Finds or creates a named object or array in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> Returns 0 if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template find_or_construct<T>(name, nothrow); }
|
||||
|
||||
//!Creates a named array from iterators in memory
|
||||
//!
|
||||
//!Allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
construct_it(char_ptr_holder_t name)
|
||||
{ return mp_header->template construct_it<T>(name); }
|
||||
|
||||
//!Finds or creates a named array from iterators in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
find_or_construct_it(char_ptr_holder_t name)
|
||||
{ return mp_header->template find_or_construct_it<T>(name); }
|
||||
|
||||
//!Creates a named array from iterators in memory
|
||||
//!
|
||||
//!Allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> If there is no available memory, returns 0.
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.*/
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template construct_it<T>(name, nothrow); }
|
||||
|
||||
//!Finds or creates a named array from iterators in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> If there is no available memory, returns 0.
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.*/
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template find_or_construct_it<T>(name, nothrow); }
|
||||
|
||||
//!Calls a functor and guarantees that no new construction, search or
|
||||
//!destruction will be executed by any process while executing the object
|
||||
//!function call. If the functor throws, this function throws.
|
||||
template <class Func>
|
||||
void atomic_func(Func &f)
|
||||
{ mp_header->atomic_func(f); }
|
||||
|
||||
//!Tries to call a functor guaranteeing that no new construction, search or
|
||||
//!destruction will be executed by any process while executing the object
|
||||
//!function call. If the atomic function can't be immediatelly executed
|
||||
//!because the internal mutex is already locked, returns false.
|
||||
//!If the functor throws, this function throws.
|
||||
template <class Func>
|
||||
bool try_atomic_func(Func &f)
|
||||
{ return mp_header->try_atomic_func(f); }
|
||||
|
||||
//!Destroys a named memory object or array.
|
||||
//!
|
||||
//!Finds the object with the given name, calls its destructors,
|
||||
//!frees used memory and returns true.
|
||||
//!
|
||||
//!-> If the object is not found, it returns false.
|
||||
//!
|
||||
//!Exception Handling:
|
||||
//!
|
||||
//!When deleting a dynamically object or array, the Standard
|
||||
//!does not guarantee that dynamically allocated memory, will be released.
|
||||
//!Also, when deleting arrays, the Standard doesn't require calling
|
||||
//!destructors for the rest of the objects if for one of them the destructor
|
||||
//!terminated with an exception.
|
||||
//!
|
||||
//!Destroying an object:
|
||||
//!
|
||||
//!If the destructor throws, the memory will be freed and that exception
|
||||
//!will be thrown.
|
||||
//!
|
||||
//!Destroying an array:
|
||||
//!
|
||||
//!When destroying an array, if a destructor throws, the rest of
|
||||
//!destructors are called. If any of these throws, the exceptions are
|
||||
//!ignored. The name association will be erased, memory will be freed and
|
||||
//!the first exception will be thrown. This guarantees the unlocking of
|
||||
//!mutexes and other resources.
|
||||
//!
|
||||
//!For all theses reasons, classes with throwing destructors are not
|
||||
//!recommended.
|
||||
template <class T>
|
||||
bool destroy(const CharType *name)
|
||||
{ return mp_header->template destroy<T>(name); }
|
||||
|
||||
//!Destroys the unique instance of type T
|
||||
//!
|
||||
//!Calls the destructor, frees used memory and returns true.
|
||||
//!
|
||||
//!Exception Handling:
|
||||
//!
|
||||
//!When deleting a dynamically object, the Standard does not
|
||||
//!guarantee that dynamically allocated memory will be released.
|
||||
//!
|
||||
//!Destroying an object:
|
||||
//!
|
||||
//!If the destructor throws, the memory will be freed and that exception
|
||||
//!will be thrown.
|
||||
//!
|
||||
//!For all theses reasons, classes with throwing destructors are not
|
||||
//!recommended for memory.
|
||||
template <class T>
|
||||
bool destroy(const unique_instance_t *const )
|
||||
{ return mp_header->template destroy<T>(unique_instance); }
|
||||
|
||||
//!Destroys the object (named, unique, or anonymous)
|
||||
//!
|
||||
//!Calls the destructor, frees used memory and returns true.
|
||||
//!
|
||||
//!Exception Handling:
|
||||
//!
|
||||
//!When deleting a dynamically object, the Standard does not
|
||||
//!guarantee that dynamically allocated memory will be released.
|
||||
//!
|
||||
//!Destroying an object:
|
||||
//!
|
||||
//!If the destructor throws, the memory will be freed and that exception
|
||||
//!will be thrown.
|
||||
//!
|
||||
//!For all theses reasons, classes with throwing destructors are not
|
||||
//!recommended for memory.
|
||||
template <class T>
|
||||
void destroy_ptr(const T *ptr)
|
||||
{ mp_header->template destroy_ptr<T>(ptr); }
|
||||
|
||||
//!Returns the name of an object created with construct/find_or_construct
|
||||
//!functions. Does not throw
|
||||
template<class T>
|
||||
static const char_type *get_instance_name(const T *ptr)
|
||||
{ return segment_manager::get_instance_name(ptr); }
|
||||
|
||||
//!Returns is the type an object created with construct/find_or_construct
|
||||
//!functions. Does not throw.
|
||||
template<class T>
|
||||
static instance_type get_instance_type(const T *ptr)
|
||||
{ return segment_manager::get_instance_type(ptr); }
|
||||
|
||||
//!Returns the length of an object created with construct/find_or_construct
|
||||
//!functions (1 if is a single element, >=1 if it's an array). Does not throw.
|
||||
template<class T>
|
||||
static size_type get_instance_length(const T *ptr)
|
||||
{ return segment_manager::get_instance_length(ptr); }
|
||||
|
||||
//!Preallocates needed index resources to optimize the
|
||||
//!creation of "num" named objects in the memory segment.
|
||||
//!Can throw boost::interprocess::bad_alloc if there is no enough memory.
|
||||
void reserve_named_objects(size_type num)
|
||||
{ mp_header->reserve_named_objects(num); }
|
||||
|
||||
//!Preallocates needed index resources to optimize the
|
||||
//!creation of "num" unique objects in the memory segment.
|
||||
//!Can throw boost::interprocess::bad_alloc if there is no enough memory.
|
||||
void reserve_unique_objects(size_type num)
|
||||
{ mp_header->reserve_unique_objects(num); }
|
||||
|
||||
//!Calls shrink_to_fit in both named and unique object indexes
|
||||
//to try to free unused memory from those indexes.
|
||||
void shrink_to_fit_indexes()
|
||||
{ mp_header->shrink_to_fit_indexes(); }
|
||||
|
||||
//!Returns the number of named objects stored
|
||||
//!in the managed segment.
|
||||
size_type get_num_named_objects()
|
||||
{ return mp_header->get_num_named_objects(); }
|
||||
|
||||
//!Returns the number of unique objects stored
|
||||
//!in the managed segment.
|
||||
size_type get_num_unique_objects()
|
||||
{ return mp_header->get_num_unique_objects(); }
|
||||
|
||||
//!Returns a constant iterator to the index storing the
|
||||
//!named allocations. NOT thread-safe. Never throws.
|
||||
const_named_iterator named_begin() const
|
||||
{ return mp_header->named_begin(); }
|
||||
|
||||
//!Returns a constant iterator to the end of the index
|
||||
//!storing the named allocations. NOT thread-safe. Never throws.
|
||||
const_named_iterator named_end() const
|
||||
{ return mp_header->named_end(); }
|
||||
|
||||
//!Returns a constant iterator to the index storing the
|
||||
//!unique allocations. NOT thread-safe. Never throws.
|
||||
const_unique_iterator unique_begin() const
|
||||
{ return mp_header->unique_begin(); }
|
||||
|
||||
//!Returns a constant iterator to the end of the index
|
||||
//!storing the unique allocations. NOT thread-safe. Never throws.
|
||||
const_unique_iterator unique_end() const
|
||||
{ return mp_header->unique_end(); }
|
||||
|
||||
//!This is the default allocator to allocate types T
|
||||
//!from this managed segment
|
||||
template<class T>
|
||||
struct allocator
|
||||
{
|
||||
typedef typename segment_manager::template allocator<T>::type type;
|
||||
};
|
||||
|
||||
//!Returns an instance of the default allocator for type T
|
||||
//!initialized that allocates memory from this segment manager.
|
||||
template<class T>
|
||||
typename allocator<T>::type
|
||||
get_allocator()
|
||||
{ return mp_header->template get_allocator<T>(); }
|
||||
|
||||
//!This is the default deleter to delete types T
|
||||
//!from this managed segment.
|
||||
template<class T>
|
||||
struct deleter
|
||||
{
|
||||
typedef typename segment_manager::template deleter<T>::type type;
|
||||
};
|
||||
|
||||
//!Returns an instance of the default allocator for type T
|
||||
//!initialized that allocates memory from this segment manager.
|
||||
template<class T>
|
||||
typename deleter<T>::type
|
||||
get_deleter()
|
||||
{ return mp_header->template get_deleter<T>(); }
|
||||
|
||||
/// @cond
|
||||
//!Tries to find a previous named allocation address. Returns a memory
|
||||
//!buffer and the object count. If not found returned pointer is 0.
|
||||
//!Never throws.
|
||||
template <class T>
|
||||
std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
|
||||
{ return mp_header->template find_no_lock<T>(name); }
|
||||
/// @endcond
|
||||
|
||||
protected:
|
||||
//!Swaps the segment manager's managed by this managed memory segment.
|
||||
//!NOT thread-safe. Never throws.
|
||||
void swap(basic_managed_memory_impl &other)
|
||||
{ std::swap(mp_header, other.mp_header); }
|
||||
|
||||
private:
|
||||
segment_manager *mp_header;
|
||||
};
|
||||
|
||||
template<class BasicManagedMemoryImpl>
|
||||
class create_open_func
|
||||
{
|
||||
typedef typename BasicManagedMemoryImpl::size_type size_type;
|
||||
|
||||
public:
|
||||
|
||||
create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
|
||||
: m_frontend(frontend), m_type(type){}
|
||||
|
||||
bool operator()(void *addr, std::size_t size, bool created) const
|
||||
{
|
||||
if( ((m_type == DoOpen) && created) ||
|
||||
((m_type == DoCreate) && !created) ||
|
||||
//Check for overflow
|
||||
size_type(-1) < size ){
|
||||
return false;
|
||||
}
|
||||
else if(created){
|
||||
return m_frontend->create_impl(addr, static_cast<size_type>(size));
|
||||
}
|
||||
else{
|
||||
return m_frontend->open_impl (addr, static_cast<size_type>(size));
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t get_min_size() const
|
||||
{
|
||||
const size_type sz = m_frontend->get_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);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BasicManagedMemoryImpl *m_frontend;
|
||||
create_enum_t m_type;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
|
||||
|
@ -0,0 +1,489 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_MANAGED_OPEN_OR_CREATE_IMPL
|
||||
#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
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
|
||||
|
||||
/// @endcond
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
|
||||
template <bool StoreDevice, class DeviceAbstraction>
|
||||
class managed_open_or_create_impl_device_holder
|
||||
{
|
||||
public:
|
||||
DeviceAbstraction &get_device()
|
||||
{ static DeviceAbstraction dev; return dev; }
|
||||
|
||||
const DeviceAbstraction &get_device() const
|
||||
{ static DeviceAbstraction dev; return dev; }
|
||||
};
|
||||
|
||||
template <class DeviceAbstraction>
|
||||
class managed_open_or_create_impl_device_holder<true, DeviceAbstraction>
|
||||
{
|
||||
public:
|
||||
DeviceAbstraction &get_device()
|
||||
{ return dev; }
|
||||
|
||||
const DeviceAbstraction &get_device() const
|
||||
{ return dev; }
|
||||
|
||||
private:
|
||||
DeviceAbstraction dev;
|
||||
};
|
||||
|
||||
template<class DeviceAbstraction, std::size_t MemAlignment, bool FileBased, bool StoreDevice>
|
||||
class managed_open_or_create_impl
|
||||
: public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction>
|
||||
{
|
||||
//Non-copyable
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl)
|
||||
|
||||
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
|
||||
{
|
||||
UninitializedSegment,
|
||||
InitializingSegment,
|
||||
InitializedSegment,
|
||||
CorruptedSegment
|
||||
};
|
||||
|
||||
public:
|
||||
static const std::size_t
|
||||
ManagedOpenOrCreateUserOffset =
|
||||
ct_rounded_size
|
||||
< sizeof(boost::uint32_t)
|
||||
, MemAlignment ? (MemAlignment) :
|
||||
(::boost::alignment_of< ::boost::detail::max_align >::value)
|
||||
>::value;
|
||||
|
||||
managed_open_or_create_impl()
|
||||
{}
|
||||
|
||||
managed_open_or_create_impl(create_only_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
( DoCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
managed_open_or_create_impl(open_only_t,
|
||||
const device_id_t & id,
|
||||
mode_t mode,
|
||||
const void *addr)
|
||||
{
|
||||
priv_open_or_create
|
||||
( DoOpen
|
||||
, id
|
||||
, 0
|
||||
, mode
|
||||
, addr
|
||||
, permissions()
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
|
||||
managed_open_or_create_impl(open_or_create_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
( DoOpenOrCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(create_only_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
(DoCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(open_only_t,
|
||||
const device_id_t & id,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
priv_open_or_create
|
||||
( DoOpen
|
||||
, id
|
||||
, 0
|
||||
, mode
|
||||
, addr
|
||||
, permissions()
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(open_or_create_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
( DoOpenOrCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
managed_open_or_create_impl(BOOST_RV_REF(managed_open_or_create_impl) moved)
|
||||
{ this->swap(moved); }
|
||||
|
||||
managed_open_or_create_impl &operator=(BOOST_RV_REF(managed_open_or_create_impl) moved)
|
||||
{
|
||||
managed_open_or_create_impl tmp(boost::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~managed_open_or_create_impl()
|
||||
{}
|
||||
|
||||
std::size_t get_user_size() const
|
||||
{ return m_mapped_region.get_size() - ManagedOpenOrCreateUserOffset; }
|
||||
|
||||
void *get_user_address() const
|
||||
{ return static_cast<char*>(m_mapped_region.get_address()) + ManagedOpenOrCreateUserOffset; }
|
||||
|
||||
std::size_t get_real_size() const
|
||||
{ return m_mapped_region.get_size(); }
|
||||
|
||||
void *get_real_address() const
|
||||
{ return m_mapped_region.get_address(); }
|
||||
|
||||
void swap(managed_open_or_create_impl &other)
|
||||
{
|
||||
this->m_mapped_region.swap(other.m_mapped_region);
|
||||
}
|
||||
|
||||
bool flush()
|
||||
{ return m_mapped_region.flush(); }
|
||||
|
||||
const mapped_region &get_mapped_region() const
|
||||
{ return m_mapped_region; }
|
||||
|
||||
|
||||
DeviceAbstraction &get_device()
|
||||
{ return this->DevHolder::get_device(); }
|
||||
|
||||
const DeviceAbstraction &get_device() const
|
||||
{ return this->DevHolder::get_device(); }
|
||||
|
||||
private:
|
||||
|
||||
//These are templatized to allow explicit instantiations
|
||||
template<bool dummy>
|
||||
static void truncate_device(DeviceAbstraction &, offset_t, false_)
|
||||
{} //Empty
|
||||
|
||||
template<bool dummy>
|
||||
static void truncate_device(DeviceAbstraction &dev, offset_t size, true_)
|
||||
{ dev.truncate(size); }
|
||||
|
||||
|
||||
template<bool dummy>
|
||||
static bool check_offset_t_size(std::size_t , false_)
|
||||
{ return true; } //Empty
|
||||
|
||||
template<bool dummy>
|
||||
static bool check_offset_t_size(std::size_t size, true_)
|
||||
{ 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)
|
||||
{
|
||||
(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)
|
||||
{
|
||||
(void)file_like;
|
||||
DeviceAbstraction tmp(create_only, id, read_write, perm);
|
||||
tmp.swap(dev);
|
||||
}
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
void priv_open_or_create
|
||||
(create_enum_t type,
|
||||
const device_id_t & 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;
|
||||
error_info err;
|
||||
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();
|
||||
if( (std::size_t(-1) - ManagedOpenOrCreateUserOffset) < func_min_size ||
|
||||
size < (func_min_size + ManagedOpenOrCreateUserOffset) ){
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
thread_yield();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(FileBased){
|
||||
offset_t filesize = 0;
|
||||
while(filesize == 0){
|
||||
if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
thread_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);
|
||||
|
||||
while(value == InitializingSegment || value == UninitializedSegment){
|
||||
thread_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);
|
||||
}
|
||||
if(StoreDevice){
|
||||
this->DevHolder::get_device() = boost::move(dev);
|
||||
}
|
||||
}
|
||||
|
||||
friend void swap(managed_open_or_create_impl &left, managed_open_or_create_impl &right)
|
||||
{
|
||||
left.swap(right);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class interprocess_tester;
|
||||
void dont_close_on_destruction()
|
||||
{ interprocess_tester::dont_close_on_destruction(m_mapped_region); }
|
||||
|
||||
mapped_region m_mapped_region;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
|
110
cpp/BoostParts/boost/interprocess/detail/math_functions.hpp
Normal file
110
cpp/BoostParts/boost/interprocess/detail/math_functions.hpp
Normal file
@ -0,0 +1,110 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Stephen Cleary 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2007-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.
|
||||
//
|
||||
// This file is a slightly modified file from Boost.Pool
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
|
||||
|
||||
#include <climits>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
// Greatest common divisor and least common multiple
|
||||
|
||||
//
|
||||
// gcd is an algorithm that calculates the greatest common divisor of two
|
||||
// integers, using Euclid's algorithm.
|
||||
//
|
||||
// Pre: A > 0 && B > 0
|
||||
// Recommended: A > B
|
||||
template <typename Integer>
|
||||
inline Integer gcd(Integer A, Integer B)
|
||||
{
|
||||
do
|
||||
{
|
||||
const Integer tmp(B);
|
||||
B = A % B;
|
||||
A = tmp;
|
||||
} while (B != 0);
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
//
|
||||
// lcm is an algorithm that calculates the least common multiple of two
|
||||
// integers.
|
||||
//
|
||||
// Pre: A > 0 && B > 0
|
||||
// Recommended: A > B
|
||||
template <typename Integer>
|
||||
inline Integer lcm(const Integer & A, const Integer & B)
|
||||
{
|
||||
Integer ret = A;
|
||||
ret /= gcd(A, B);
|
||||
ret *= B;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Integer>
|
||||
inline Integer log2_ceil(const Integer & A)
|
||||
{
|
||||
Integer i = 0;
|
||||
Integer power_of_2 = 1;
|
||||
|
||||
while(power_of_2 < A){
|
||||
power_of_2 <<= 1;
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template <typename Integer>
|
||||
inline Integer upper_power_of_2(const Integer & A)
|
||||
{
|
||||
Integer power_of_2 = 1;
|
||||
|
||||
while(power_of_2 < A){
|
||||
power_of_2 <<= 1;
|
||||
}
|
||||
return power_of_2;
|
||||
}
|
||||
|
||||
//This function uses binary search to discover the
|
||||
//highest set bit of the integer
|
||||
inline std::size_t floor_log2 (std::size_t x)
|
||||
{
|
||||
const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
|
||||
const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
|
||||
BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true));
|
||||
|
||||
std::size_t n = x;
|
||||
std::size_t log2 = 0;
|
||||
|
||||
for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
|
||||
std::size_t tmp = n >> shift;
|
||||
if (tmp)
|
||||
log2 += shift, n = tmp;
|
||||
}
|
||||
|
||||
return log2;
|
||||
}
|
||||
|
||||
} // namespace ipcdetail
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
40
cpp/BoostParts/boost/interprocess/detail/min_max.hpp
Normal file
40
cpp/BoostParts/boost/interprocess/detail/min_max.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_MIN_MAX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
template<class T>
|
||||
const T &max_value(const T &a, const T &b)
|
||||
{ return a > b ? a : b; }
|
||||
|
||||
template<class T>
|
||||
const T &min_value(const T &a, const T &b)
|
||||
{ return a < b ? a : b; }
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
|
||||
|
152
cpp/BoostParts/boost/interprocess/detail/mpl.hpp
Normal file
152
cpp/BoostParts/boost/interprocess/detail/mpl.hpp
Normal file
@ -0,0 +1,152 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_MPL_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MPL_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template <class T, T val>
|
||||
struct integral_constant
|
||||
{
|
||||
static const T value = val;
|
||||
typedef integral_constant<T,val> type;
|
||||
};
|
||||
|
||||
template< bool C_ >
|
||||
struct bool_ : integral_constant<bool, C_>
|
||||
{
|
||||
static const bool value = C_;
|
||||
};
|
||||
|
||||
typedef bool_<true> true_;
|
||||
typedef bool_<false> false_;
|
||||
|
||||
typedef true_ true_type;
|
||||
typedef false_ false_type;
|
||||
|
||||
typedef char yes_type;
|
||||
struct no_type
|
||||
{
|
||||
char padding[8];
|
||||
};
|
||||
|
||||
template <bool B, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct disable_if : public enable_if_c<!Cond::value, T> {};
|
||||
|
||||
template <class T, class U>
|
||||
class is_convertible
|
||||
{
|
||||
typedef char true_t;
|
||||
class false_t { char dummy[2]; };
|
||||
static true_t dispatch(U);
|
||||
static false_t dispatch(...);
|
||||
static T trigger();
|
||||
public:
|
||||
static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
|
||||
};
|
||||
|
||||
template<
|
||||
bool C
|
||||
, typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct if_c
|
||||
{
|
||||
typedef T1 type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct if_c<false,T1,T2>
|
||||
{
|
||||
typedef T2 type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
>
|
||||
struct if_
|
||||
{
|
||||
typedef typename if_c<0 != T1::value, T2, T3>::type type;
|
||||
};
|
||||
|
||||
|
||||
template <class Pair>
|
||||
struct select1st
|
||||
// : public std::unary_function<Pair, typename Pair::first_type>
|
||||
{
|
||||
template<class OtherPair>
|
||||
const typename Pair::first_type& operator()(const OtherPair& x) const
|
||||
{ return x.first; }
|
||||
|
||||
const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
|
||||
{ return x; }
|
||||
};
|
||||
|
||||
// identity is an extension: it is not part of the standard.
|
||||
template <class T>
|
||||
struct identity
|
||||
// : public std::unary_function<T,T>
|
||||
{
|
||||
typedef T type;
|
||||
const T& operator()(const T& x) const
|
||||
{ return x; }
|
||||
};
|
||||
|
||||
template<std::size_t S>
|
||||
struct ls_zeros
|
||||
{
|
||||
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ls_zeros<0>
|
||||
{
|
||||
static const std::size_t value = 0;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ls_zeros<1>
|
||||
{
|
||||
static const std::size_t value = 0;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
|
||||
|
349
cpp/BoostParts/boost/interprocess/detail/named_proxy.hpp
Normal file
349
cpp/BoostParts/boost/interprocess/detail/named_proxy.hpp
Normal file
@ -0,0 +1,349 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_NAMED_PROXY_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <new>
|
||||
#include <iterator>
|
||||
#include <boost/interprocess/detail/in_place_interface.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#include <boost/interprocess/detail/preprocessor.hpp>
|
||||
#else
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/interprocess/detail/variadic_templates_tools.hpp>
|
||||
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
//!\file
|
||||
//!Describes a proxy class that implements named allocation syntax.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
template<class T, bool is_iterator, class ...Args>
|
||||
struct CtorNArg : public placement_destroy<T>
|
||||
{
|
||||
typedef bool_<is_iterator> IsIterator;
|
||||
typedef CtorNArg<T, is_iterator, Args...> self_t;
|
||||
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
self_t& operator++()
|
||||
{
|
||||
this->do_increment(IsIterator(), index_tuple_t());
|
||||
return *this;
|
||||
}
|
||||
|
||||
self_t operator++(int) { return ++*this; *this; }
|
||||
|
||||
CtorNArg(Args && ...args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
virtual void construct_n(void *mem
|
||||
, std::size_t num
|
||||
, std::size_t &constructed)
|
||||
{
|
||||
T* memory = static_cast<T*>(mem);
|
||||
for(constructed = 0; constructed < num; ++constructed){
|
||||
this->construct(memory++, IsIterator(), index_tuple_t());
|
||||
this->do_increment(IsIterator(), index_tuple_t());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<int ...IdxPack>
|
||||
void construct(void *mem, true_, const index_tuple<IdxPack...>&)
|
||||
{ new((void*)mem)T(*boost::forward<Args>(get<IdxPack>(args_))...); }
|
||||
|
||||
template<int ...IdxPack>
|
||||
void construct(void *mem, false_, const index_tuple<IdxPack...>&)
|
||||
{ new((void*)mem)T(boost::forward<Args>(get<IdxPack>(args_))...); }
|
||||
|
||||
template<int ...IdxPack>
|
||||
void do_increment(true_, const index_tuple<IdxPack...>&)
|
||||
{
|
||||
this->expansion_helper(++get<IdxPack>(args_)...);
|
||||
}
|
||||
|
||||
template<class ...ExpansionArgs>
|
||||
void expansion_helper(ExpansionArgs &&...)
|
||||
{}
|
||||
|
||||
template<int ...IdxPack>
|
||||
void do_increment(false_, const index_tuple<IdxPack...>&)
|
||||
{}
|
||||
|
||||
tuple<Args&...> args_;
|
||||
};
|
||||
|
||||
//!Describes a proxy class that implements named
|
||||
//!allocation syntax.
|
||||
template
|
||||
< class SegmentManager //segment manager to construct the object
|
||||
, class T //type of object to build
|
||||
, bool is_iterator //passing parameters are normal object or iterators?
|
||||
>
|
||||
class named_proxy
|
||||
{
|
||||
typedef typename SegmentManager::char_type char_type;
|
||||
const char_type * mp_name;
|
||||
SegmentManager * mp_mngr;
|
||||
mutable std::size_t m_num;
|
||||
const bool m_find;
|
||||
const bool m_dothrow;
|
||||
|
||||
public:
|
||||
named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
||||
: mp_name(name), mp_mngr(mngr), m_num(1)
|
||||
, m_find(find), m_dothrow(dothrow)
|
||||
{}
|
||||
|
||||
template<class ...Args>
|
||||
T *operator()(Args &&...args) const
|
||||
{
|
||||
CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...>
|
||||
(boost::forward<Args>(args)...);
|
||||
return mp_mngr->template
|
||||
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
||||
}
|
||||
|
||||
//This operator allows --> named_new("Name")[3]; <-- syntax
|
||||
const named_proxy &operator[](std::size_t num) const
|
||||
{ m_num *= num; return *this; }
|
||||
};
|
||||
|
||||
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
//!Function object that makes placement new
|
||||
//!without arguments
|
||||
template<class T>
|
||||
struct Ctor0Arg : public placement_destroy<T>
|
||||
{
|
||||
typedef Ctor0Arg self_t;
|
||||
|
||||
Ctor0Arg(){}
|
||||
|
||||
self_t& operator++() { return *this; }
|
||||
self_t operator++(int) { return *this; }
|
||||
|
||||
void construct(void *mem)
|
||||
{ new((void*)mem)T; }
|
||||
|
||||
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
|
||||
{
|
||||
T* memory = static_cast<T*>(mem);
|
||||
for(constructed = 0; constructed < num; ++constructed)
|
||||
new((void*)memory++)T;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// What the macro should generate (n == 2):
|
||||
//
|
||||
// template<class T, bool is_iterator, class P1, class P2>
|
||||
// struct Ctor2Arg
|
||||
// : public placement_destroy<T>
|
||||
// {
|
||||
// typedef bool_<is_iterator> IsIterator;
|
||||
// typedef Ctor2Arg self_t;
|
||||
//
|
||||
// void do_increment(false_)
|
||||
// { ++m_p1; ++m_p2; }
|
||||
//
|
||||
// void do_increment(true_){}
|
||||
//
|
||||
// self_t& operator++()
|
||||
// {
|
||||
// this->do_increment(IsIterator());
|
||||
// return *this;
|
||||
// }
|
||||
//
|
||||
// self_t operator++(int) { return ++*this; *this; }
|
||||
//
|
||||
// Ctor2Arg(const P1 &p1, const P2 &p2)
|
||||
// : p1((P1 &)p_1), p2((P2 &)p_2) {}
|
||||
//
|
||||
// void construct(void *mem)
|
||||
// { new((void*)object)T(m_p1, m_p2); }
|
||||
//
|
||||
// virtual void construct_n(void *mem
|
||||
// , std::size_t num
|
||||
// , std::size_t &constructed)
|
||||
// {
|
||||
// T* memory = static_cast<T*>(mem);
|
||||
// for(constructed = 0; constructed < num; ++constructed){
|
||||
// this->construct(memory++, IsIterator());
|
||||
// this->do_increment(IsIterator());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// void construct(void *mem, true_)
|
||||
// { new((void*)mem)T(*m_p1, *m_p2); }
|
||||
//
|
||||
// void construct(void *mem, false_)
|
||||
// { new((void*)mem)T(m_p1, m_p2); }
|
||||
//
|
||||
// P1 &m_p1; P2 &m_p2;
|
||||
// };
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//Note:
|
||||
//We define template parameters as const references to
|
||||
//be able to bind temporaries. After that we will un-const them.
|
||||
//This cast is ugly but it is necessary until "perfect forwarding"
|
||||
//is achieved in C++0x. Meanwhile, if we want to be able to
|
||||
//bind lvalues with non-const references, we have to be ugly
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
||||
: public placement_destroy<T> \
|
||||
{ \
|
||||
typedef bool_<is_iterator> IsIterator; \
|
||||
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \
|
||||
\
|
||||
void do_increment(true_) \
|
||||
{ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INC, _); } \
|
||||
\
|
||||
void do_increment(false_){} \
|
||||
\
|
||||
self_t& operator++() \
|
||||
{ \
|
||||
this->do_increment(IsIterator()); \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
self_t operator++(int) { return ++*this; *this; } \
|
||||
\
|
||||
BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
||||
( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
|
||||
: BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INIT, _) {} \
|
||||
\
|
||||
virtual void construct_n(void *mem \
|
||||
, std::size_t num \
|
||||
, std::size_t &constructed) \
|
||||
{ \
|
||||
T* memory = static_cast<T*>(mem); \
|
||||
for(constructed = 0; constructed < num; ++constructed){ \
|
||||
this->construct(memory++, IsIterator()); \
|
||||
this->do_increment(IsIterator()); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
void construct(void *mem, true_) \
|
||||
{ \
|
||||
new((void*)mem) T \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \
|
||||
} \
|
||||
\
|
||||
void construct(void *mem, false_) \
|
||||
{ \
|
||||
new((void*)mem) T \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_PP_PARAM_DEFINE, _) \
|
||||
}; \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
//!Describes a proxy class that implements named
|
||||
//!allocation syntax.
|
||||
template
|
||||
< class SegmentManager //segment manager to construct the object
|
||||
, class T //type of object to build
|
||||
, bool is_iterator //passing parameters are normal object or iterators?
|
||||
>
|
||||
class named_proxy
|
||||
{
|
||||
typedef typename SegmentManager::char_type char_type;
|
||||
const char_type * mp_name;
|
||||
SegmentManager * mp_mngr;
|
||||
mutable std::size_t m_num;
|
||||
const bool m_find;
|
||||
const bool m_dothrow;
|
||||
|
||||
public:
|
||||
named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
||||
: mp_name(name), mp_mngr(mngr), m_num(1)
|
||||
, m_find(find), m_dothrow(dothrow)
|
||||
{}
|
||||
|
||||
//!makes a named allocation and calls the
|
||||
//!default constructor
|
||||
T *operator()() const
|
||||
{
|
||||
Ctor0Arg<T> ctor_obj;
|
||||
return mp_mngr->template
|
||||
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
||||
}
|
||||
//!
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\
|
||||
{ \
|
||||
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
||||
<T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
|
||||
ctor_obj_t; \
|
||||
ctor_obj_t ctor_obj \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
|
||||
return mp_mngr->template generic_construct<T> \
|
||||
(mp_name, m_num, m_find, m_dothrow, ctor_obj); \
|
||||
} \
|
||||
//!
|
||||
|
||||
#define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS )
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// What the macro should generate (n == 2)
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// template <class P1, class P2>
|
||||
// T *operator()(P1 &p1, P2 &p2) const
|
||||
// {
|
||||
// typedef Ctor2Arg
|
||||
// <T, is_iterator, P1, P2>
|
||||
// ctor_obj_t;
|
||||
// ctor_obj_t ctor_obj(p1, p2);
|
||||
//
|
||||
// return mp_mngr->template generic_construct<T>
|
||||
// (mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
||||
// }
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//This operator allows --> named_new("Name")[3]; <-- syntax
|
||||
const named_proxy &operator[](std::size_t num) const
|
||||
{ m_num *= num; return *this; }
|
||||
};
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
696
cpp/BoostParts/boost/interprocess/detail/os_file_functions.hpp
Normal file
696
cpp/BoostParts/boost/interprocess/detail/os_file_functions.hpp
Normal file
@ -0,0 +1,696 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_OS_FILE_FUNCTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
# include <boost/interprocess/detail/win32_api.hpp>
|
||||
#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>
|
||||
# if 0
|
||||
# include <sys/file.h>
|
||||
# endif
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef void * file_handle_t;
|
||||
typedef long long offset_t;
|
||||
typedef struct mapping_handle_impl_t{
|
||||
void * handle;
|
||||
bool is_shm;
|
||||
} mapping_handle_t;
|
||||
|
||||
typedef enum { read_only = winapi::generic_read
|
||||
, read_write = winapi::generic_read | winapi::generic_write
|
||||
, copy_on_write
|
||||
, read_private
|
||||
, invalid_mode = 0xffff
|
||||
} mode_t;
|
||||
|
||||
typedef enum { file_begin = winapi::file_begin
|
||||
, file_end = winapi::file_end
|
||||
, file_current = winapi::file_current
|
||||
} file_pos_t;
|
||||
|
||||
namespace ipcdetail{
|
||||
|
||||
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
|
||||
{
|
||||
mapping_handle_t ret;
|
||||
ret.handle = hnd;
|
||||
ret.is_shm = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
|
||||
{
|
||||
mapping_handle_t ret;
|
||||
ret.handle = hnd;
|
||||
ret.is_shm = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
|
||||
{ return hnd.handle; }
|
||||
|
||||
inline bool create_directory(const char *path)
|
||||
{ return winapi::create_directory(path); }
|
||||
|
||||
inline const char *get_temporary_path()
|
||||
{ return std::getenv("TMP"); }
|
||||
|
||||
|
||||
inline file_handle_t create_new_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
( name, (unsigned int)mode, winapi::create_new, attr
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions());
|
||||
}
|
||||
|
||||
inline file_handle_t create_or_open_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
( name, (unsigned int)mode, winapi::open_always, attr
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions());
|
||||
}
|
||||
|
||||
inline file_handle_t open_existing_file
|
||||
(const char *name, mode_t mode, bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
(name, (unsigned int)mode, winapi::open_existing, attr, 0);
|
||||
}
|
||||
|
||||
inline bool delete_file(const char *name)
|
||||
{ return winapi::unlink_file(name); }
|
||||
|
||||
inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
||||
{
|
||||
offset_t filesize;
|
||||
if(!winapi::get_file_size(hnd, filesize))
|
||||
return false;
|
||||
|
||||
const offset_t max_filesize = (std::numeric_limits<offset_t>::max)();
|
||||
//Avoid unused variable warnings in 32 bit systems
|
||||
(void)max_filesize;
|
||||
if( sizeof(std::size_t) >= sizeof(offset_t) && size > std::size_t(max_filesize) ){
|
||||
winapi::set_last_error(winapi::error_file_too_large);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(offset_t(size) > filesize){
|
||||
if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
|
||||
return false;
|
||||
}
|
||||
//We will write zeros in the end of the file
|
||||
//since set_end_of_file does not guarantee this
|
||||
for(std::size_t remaining = size - filesize, write_size = 0
|
||||
;remaining > 0
|
||||
;remaining -= write_size){
|
||||
const std::size_t DataSize = 512;
|
||||
static char data [DataSize];
|
||||
write_size = DataSize < remaining ? DataSize : remaining;
|
||||
unsigned long written;
|
||||
winapi::write_file(hnd, data, (unsigned long)write_size, &written, 0);
|
||||
if(written != write_size){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
|
||||
return false;
|
||||
}
|
||||
if(!winapi::set_end_of_file(hnd)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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); }
|
||||
|
||||
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
|
||||
{ return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
|
||||
|
||||
inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
|
||||
{
|
||||
unsigned long written;
|
||||
return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0);
|
||||
}
|
||||
|
||||
inline file_handle_t invalid_file()
|
||||
{ return winapi::invalid_handle_value; }
|
||||
|
||||
inline bool close_file(file_handle_t hnd)
|
||||
{ return 0 != winapi::close_handle(hnd); }
|
||||
|
||||
inline bool acquire_file_lock(file_handle_t hnd)
|
||||
{
|
||||
static winapi::interprocess_overlapped overlapped;
|
||||
const unsigned long len = ((unsigned long)-1);
|
||||
// winapi::interprocess_overlapped overlapped;
|
||||
// std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return winapi::lock_file_ex
|
||||
(hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
const unsigned long len = ((unsigned long)-1);
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
if(!winapi::lock_file_ex
|
||||
(hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately,
|
||||
0, len, len, &overlapped)){
|
||||
return winapi::get_last_error() == winapi::error_lock_violation ?
|
||||
acquired = false, true : false;
|
||||
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock(file_handle_t hnd)
|
||||
{
|
||||
const unsigned long len = ((unsigned long)-1);
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped);
|
||||
}
|
||||
|
||||
inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
||||
{
|
||||
const unsigned long len = ((unsigned long)-1);
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
const unsigned long len = ((unsigned long)-1);
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
if(!winapi::lock_file_ex
|
||||
(hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){
|
||||
return winapi::get_last_error() == winapi::error_lock_violation ?
|
||||
acquired = false, true : false;
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock_sharable(file_handle_t hnd)
|
||||
{ return release_file_lock(hnd); }
|
||||
|
||||
inline bool delete_subdirectories_recursive
|
||||
(const std::string &refcstrRootDirectory, const char *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_t FileInformation; // File information
|
||||
|
||||
//Find all files and directories
|
||||
strPattern = refcstrRootDirectory + "\\*.*";
|
||||
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)){
|
||||
strFilePath.erase();
|
||||
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
|
||||
|
||||
//If it's a directory, go recursive
|
||||
if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
|
||||
// Delete subdirectory
|
||||
if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1))
|
||||
return false;
|
||||
}
|
||||
//If it's a file, just delete it
|
||||
else{
|
||||
// Set file attributes
|
||||
//if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
|
||||
//return winapi::get_last_error();
|
||||
// Delete file
|
||||
winapi::delete_file(strFilePath.c_str());
|
||||
}
|
||||
}
|
||||
//Go to the next file
|
||||
} while(winapi::find_next_file(hFile, &FileInformation) == 1);
|
||||
|
||||
// Close handle
|
||||
winapi::find_close(hFile);
|
||||
|
||||
//See if the loop has ended with an error or just because we've traversed all the files
|
||||
if(winapi::get_last_error() != winapi::error_no_more_files){
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Erase empty subdirectories or original refcstrRootDirectory
|
||||
if(!bSubdirectory && count)
|
||||
{
|
||||
// Set directory attributes
|
||||
//if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0)
|
||||
//return ::GetLastError();
|
||||
// Delete directory
|
||||
if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
|
||||
}
|
||||
|
||||
|
||||
template<class Function>
|
||||
inline bool for_each_file_in_dir(const char *dir, Function f)
|
||||
{
|
||||
void * hFile; // Handle to directory
|
||||
winapi::win32_find_data_t FileInformation; // File information
|
||||
|
||||
//Get base directory
|
||||
std::string str(dir);
|
||||
const std::size_t base_root_dir_len = str.size();
|
||||
|
||||
//Find all files and directories
|
||||
str += "\\*.*";
|
||||
hFile = winapi::find_first_file(str.c_str(), &FileInformation);
|
||||
if(hFile != winapi::invalid_handle_value){
|
||||
do{ //Now loop every file
|
||||
str.erase(base_root_dir_len);
|
||||
//If it's not "." or ".." skip it
|
||||
if(FileInformation.cFileName[0] != '.'){
|
||||
str += "\\"; str += FileInformation.cFileName;
|
||||
//If it's a file, apply erase logic
|
||||
if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){
|
||||
f(str.c_str(), FileInformation.cFileName);
|
||||
}
|
||||
}
|
||||
//Go to the next file
|
||||
} while(winapi::find_next_file(hFile, &FileInformation) == 1);
|
||||
|
||||
// Close handle and see if the loop has ended with an error
|
||||
winapi::find_close(hFile);
|
||||
if(winapi::get_last_error() != winapi::error_no_more_files){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef int file_handle_t;
|
||||
typedef off_t offset_t;
|
||||
|
||||
typedef struct mapping_handle_impl_t
|
||||
{
|
||||
file_handle_t handle;
|
||||
bool is_xsi;
|
||||
} mapping_handle_t;
|
||||
|
||||
typedef enum { read_only = O_RDONLY
|
||||
, read_write = O_RDWR
|
||||
, copy_on_write
|
||||
, read_private
|
||||
, invalid_mode = 0xffff
|
||||
} mode_t;
|
||||
|
||||
typedef enum { file_begin = SEEK_SET
|
||||
, file_end = SEEK_END
|
||||
, file_current = SEEK_CUR
|
||||
} file_pos_t;
|
||||
|
||||
namespace ipcdetail{
|
||||
|
||||
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
|
||||
{
|
||||
mapping_handle_t ret;
|
||||
ret.handle = hnd;
|
||||
ret.is_xsi = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
inline const char *get_temporary_path()
|
||||
{
|
||||
const char *names[] = {"/tmp", "TMPDIR", "TMP", "TEMP" };
|
||||
const int names_size = sizeof(names)/sizeof(names[0]);
|
||||
struct stat data;
|
||||
for(int i = 0; i != names_size; ++i){
|
||||
if(::stat(names[i], &data) == 0){
|
||||
return names[i];
|
||||
}
|
||||
}
|
||||
return "/tmp";
|
||||
}
|
||||
|
||||
inline file_handle_t create_new_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
|
||||
if(ret >= 0){
|
||||
::fchmod(ret, perm.get_permissions());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline file_handle_t create_or_open_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
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){
|
||||
ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
|
||||
if(ret >= 0){
|
||||
::fchmod(ret, perm.get_permissions());
|
||||
break;
|
||||
}
|
||||
else if(errno == EEXIST){
|
||||
if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline file_handle_t open_existing_file
|
||||
(const char *name, mode_t mode, bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
return ::open(name, (int)mode);
|
||||
}
|
||||
|
||||
inline bool delete_file(const char *name)
|
||||
{ return ::unlink(name) == 0; }
|
||||
|
||||
inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
||||
{
|
||||
if(sizeof(off_t) == sizeof(std::size_t)){
|
||||
if(size > ((~std::size_t(0)) >> 1)){
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return 0 == ::ftruncate(hnd, off_t(size));
|
||||
}
|
||||
|
||||
inline bool get_file_size(file_handle_t hnd, offset_t &size)
|
||||
{
|
||||
struct stat data;
|
||||
bool ret = 0 == ::fstat(hnd, &data);
|
||||
if(ret){
|
||||
size = data.st_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
|
||||
{ return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
|
||||
|
||||
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
|
||||
{
|
||||
off = ::lseek(hnd, 0, SEEK_CUR);
|
||||
return off != ((off_t)-1);
|
||||
}
|
||||
|
||||
inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
|
||||
{ return (ssize_t(numdata)) == ::write(hnd, data, numdata); }
|
||||
|
||||
inline file_handle_t invalid_file()
|
||||
{ return -1; }
|
||||
|
||||
inline bool close_file(file_handle_t hnd)
|
||||
{ return ::close(hnd) == 0; }
|
||||
|
||||
inline bool acquire_file_lock(file_handle_t hnd)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
return -1 != ::fcntl(hnd, F_SETLKW, &lock);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
int ret = ::fcntl(hnd, F_SETLK, &lock);
|
||||
if(ret == -1){
|
||||
return (errno == EAGAIN || errno == EACCES) ?
|
||||
acquired = false, true : false;
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock(file_handle_t hnd)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_UNLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
return -1 != ::fcntl(hnd, F_SETLK, &lock);
|
||||
}
|
||||
|
||||
inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_RDLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
return -1 != ::fcntl(hnd, F_SETLKW, &lock);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
struct flock lock;
|
||||
lock.l_type = F_RDLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
int ret = ::fcntl(hnd, F_SETLK, &lock);
|
||||
if(ret == -1){
|
||||
return (errno == EAGAIN || errno == EACCES) ?
|
||||
acquired = false, true : false;
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock_sharable(file_handle_t hnd)
|
||||
{ return release_file_lock(hnd); }
|
||||
|
||||
#if 0
|
||||
inline bool acquire_file_lock(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_EX); }
|
||||
|
||||
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
int ret = ::flock(hnd, LOCK_EX | LOCK_NB);
|
||||
acquired = ret == 0;
|
||||
return (acquired || errno == EWOULDBLOCK);
|
||||
}
|
||||
|
||||
inline bool release_file_lock(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_UN); }
|
||||
|
||||
inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_SH); }
|
||||
|
||||
inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
int ret = ::flock(hnd, LOCK_SH | LOCK_NB);
|
||||
acquired = ret == 0;
|
||||
return (acquired || errno == EWOULDBLOCK);
|
||||
}
|
||||
|
||||
inline bool release_file_lock_sharable(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_UN); }
|
||||
#endif
|
||||
|
||||
inline bool delete_subdirectories_recursive
|
||||
(const std::string &refcstrRootDirectory, const char *dont_delete_this)
|
||||
{
|
||||
DIR *d = opendir(refcstrRootDirectory.c_str());
|
||||
if(!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dir_close
|
||||
{
|
||||
DIR *d_;
|
||||
dir_close(DIR *d) : d_(d) {}
|
||||
~dir_close() { ::closedir(d_); }
|
||||
} dc(d); (void)dc;
|
||||
|
||||
struct ::dirent *de;
|
||||
struct ::stat st;
|
||||
std::string fn;
|
||||
|
||||
while((de=::readdir(d))) {
|
||||
if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
|
||||
|| (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
|
||||
continue;
|
||||
}
|
||||
if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
|
||||
continue;
|
||||
}
|
||||
fn = refcstrRootDirectory;
|
||||
fn += '/';
|
||||
fn += de->d_name;
|
||||
|
||||
if(std::remove(fn.c_str())) {
|
||||
if(::stat(fn.c_str(), & st)) {
|
||||
return false;
|
||||
}
|
||||
if(S_ISDIR(st.st_mode)) {
|
||||
if(!delete_subdirectories_recursive(fn, 0) ){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::remove(refcstrRootDirectory.c_str()) ? false : true;
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
inline bool for_each_file_in_dir(const char *dir, Function f)
|
||||
{
|
||||
std::string refcstrRootDirectory(dir);
|
||||
|
||||
DIR *d = opendir(refcstrRootDirectory.c_str());
|
||||
if(!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dir_close
|
||||
{
|
||||
DIR *d_;
|
||||
dir_close(DIR *d) : d_(d) {}
|
||||
~dir_close() { ::closedir(d_); }
|
||||
} dc(d); (void)dc;
|
||||
|
||||
struct ::dirent *de;
|
||||
struct ::stat st;
|
||||
std::string fn;
|
||||
|
||||
while((de=::readdir(d))) {
|
||||
if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
|
||||
|| (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
|
||||
continue;
|
||||
}
|
||||
fn = refcstrRootDirectory;
|
||||
fn += '/';
|
||||
fn += de->d_name;
|
||||
|
||||
if(::stat(fn.c_str(), & st)) {
|
||||
return false;
|
||||
}
|
||||
//If it's a file, apply erase logic
|
||||
if(!S_ISDIR(st.st_mode)) {
|
||||
f(fn.c_str(), de->d_name);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//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)
|
||||
{
|
||||
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this );
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
211
cpp/BoostParts/boost/interprocess/detail/os_thread_functions.hpp
Normal file
211
cpp/BoostParts/boost/interprocess/detail/os_thread_functions.hpp
Normal file
@ -0,0 +1,211 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_OS_THREAD_FUNCTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
||||
|
||||
#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>
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
# include <boost/interprocess/detail/win32_api.hpp>
|
||||
#else
|
||||
# ifdef BOOST_HAS_UNISTD_H
|
||||
# include <pthread.h>
|
||||
# include <unistd.h>
|
||||
# include <sched.h>
|
||||
# include <time.h>
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef unsigned long OS_process_id_t;
|
||||
typedef unsigned long OS_thread_id_t;
|
||||
typedef OS_thread_id_t OS_systemwide_thread_id_t;
|
||||
|
||||
//process
|
||||
inline OS_process_id_t get_current_process_id()
|
||||
{ return winapi::get_current_process_id(); }
|
||||
|
||||
inline OS_process_id_t get_invalid_process_id()
|
||||
{ return OS_process_id_t(0); }
|
||||
|
||||
//thread
|
||||
inline OS_thread_id_t get_current_thread_id()
|
||||
{ return winapi::get_current_thread_id(); }
|
||||
|
||||
inline OS_thread_id_t get_invalid_thread_id()
|
||||
{ return OS_thread_id_t(0xffffffff); }
|
||||
|
||||
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
||||
{ return id1 == id2; }
|
||||
|
||||
inline void thread_yield()
|
||||
{ winapi::sched_yield(); }
|
||||
|
||||
inline void thread_sleep(unsigned int ms)
|
||||
{ winapi::Sleep(ms); }
|
||||
|
||||
//systemwide thread
|
||||
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
|
||||
{
|
||||
return get_current_thread_id();
|
||||
}
|
||||
|
||||
inline void systemwide_thread_id_copy
|
||||
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
|
||||
{
|
||||
to = from;
|
||||
}
|
||||
|
||||
inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
|
||||
{
|
||||
return equal_thread_id(id1, id2);
|
||||
}
|
||||
|
||||
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
|
||||
{
|
||||
return get_invalid_thread_id();
|
||||
}
|
||||
|
||||
inline long double get_current_process_creation_time()
|
||||
{
|
||||
winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
|
||||
|
||||
get_process_times
|
||||
( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
|
||||
|
||||
typedef long double ldouble_t;
|
||||
const ldouble_t resolution = (100.0l/1000000000.0l);
|
||||
return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
|
||||
CreationTime.dwLowDateTime*resolution;
|
||||
}
|
||||
|
||||
|
||||
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef pthread_t OS_thread_id_t;
|
||||
typedef pid_t OS_process_id_t;
|
||||
|
||||
struct OS_systemwide_thread_id_t
|
||||
{
|
||||
OS_systemwide_thread_id_t()
|
||||
: pid(), tid()
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t(pid_t p, pthread_t t)
|
||||
: pid(p), tid(t)
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
|
||||
: pid(x.pid), tid(x.tid)
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
|
||||
: pid(x.pid), tid(x.tid)
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
|
||||
{ pid = x.pid; tid = x.tid; return *this; }
|
||||
|
||||
OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
|
||||
{ pid = x.pid; tid = x.tid; return *this; }
|
||||
|
||||
void operator=(const OS_systemwide_thread_id_t &x) volatile
|
||||
{ pid = x.pid; tid = x.tid; }
|
||||
|
||||
pid_t pid;
|
||||
pthread_t tid;
|
||||
};
|
||||
|
||||
inline void systemwide_thread_id_copy
|
||||
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
|
||||
{
|
||||
to.pid = from.pid;
|
||||
to.tid = from.tid;
|
||||
}
|
||||
|
||||
//process
|
||||
inline OS_process_id_t get_current_process_id()
|
||||
{ return ::getpid(); }
|
||||
|
||||
inline OS_process_id_t get_invalid_process_id()
|
||||
{ return pid_t(0); }
|
||||
|
||||
//thread
|
||||
inline OS_thread_id_t get_current_thread_id()
|
||||
{ return ::pthread_self(); }
|
||||
|
||||
inline OS_thread_id_t get_invalid_thread_id()
|
||||
{
|
||||
static pthread_t invalid_id;
|
||||
return invalid_id;
|
||||
}
|
||||
|
||||
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
||||
{ return 0 != pthread_equal(id1, id2); }
|
||||
|
||||
inline void thread_yield()
|
||||
{ ::sched_yield(); }
|
||||
|
||||
inline void thread_sleep(unsigned int ms)
|
||||
{
|
||||
const struct timespec rqt = { ms/1000u, (ms%1000u)*1000000u };
|
||||
::nanosleep(&rqt, 0);
|
||||
}
|
||||
|
||||
//systemwide thread
|
||||
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
|
||||
{
|
||||
return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
|
||||
}
|
||||
|
||||
inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
|
||||
{
|
||||
return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
|
||||
}
|
||||
|
||||
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
|
||||
{
|
||||
return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
|
||||
}
|
||||
|
||||
inline long double get_current_process_creation_time()
|
||||
{ return 0.0L; }
|
||||
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
|
||||
|
||||
inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
|
||||
{
|
||||
bufferstream bstream(pid_str, sizeof(pid_str));
|
||||
bstream << pid << std::ends;
|
||||
}
|
||||
|
||||
inline void get_pid_str(pid_str_t &pid_str)
|
||||
{ get_pid_str(pid_str, get_current_process_id()); }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
@ -0,0 +1,42 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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
|
||||
|
||||
//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/posix_time_types.hpp>
|
||||
#include <boost/date_time/posix_time/conversion.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
|
||||
|
203
cpp/BoostParts/boost/interprocess/detail/preprocessor.hpp
Normal file
203
cpp/BoostParts/boost/interprocess/detail/preprocessor.hpp
Normal file
@ -0,0 +1,203 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-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_PREPROCESSOR_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#error "This file is not needed when perfect forwarding is available"
|
||||
#endif
|
||||
|
||||
#include <boost/preprocessor/iteration/local.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
|
||||
#define BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS 10
|
||||
|
||||
//Note:
|
||||
//We define template parameters as const references to
|
||||
//be able to bind temporaries. After that we will un-const them.
|
||||
//This cast is ugly but it is necessary until "perfect forwarding"
|
||||
//is achieved in C++0x. Meanwhile, if we want to be able to
|
||||
//bind rvalues with non-const references, we have to be ugly
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
|
||||
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
#define BOOST_INTERPROCESS_PP_PARAM(U, u) \
|
||||
U && u \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_PP_PARAM(U, u) \
|
||||
const U & u \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
|
||||
//!
|
||||
|
||||
#else //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
template<class T>
|
||||
struct ref_holder;
|
||||
|
||||
template<class T>
|
||||
struct ref_holder<T &>
|
||||
{
|
||||
ref_holder(T &t)
|
||||
: t_(t)
|
||||
{}
|
||||
T &t_;
|
||||
T & get() { return t_; }
|
||||
T & get_lvalue() { return t_; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ref_holder<const T>
|
||||
{
|
||||
ref_holder(const T &t)
|
||||
: t_(t)
|
||||
{}
|
||||
const T &t_;
|
||||
const T & get() { return t_; }
|
||||
const T & get_lvalue() { return t_; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ref_holder<const T &&>
|
||||
{
|
||||
ref_holder(const T &t)
|
||||
: t_(t)
|
||||
{}
|
||||
const T &t_;
|
||||
const T & get() { return t_; }
|
||||
const T & get_lvalue() { return t_; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ref_holder
|
||||
{
|
||||
ref_holder(T &&t)
|
||||
: t_(t)
|
||||
{}
|
||||
T &t_;
|
||||
T && get() { return ::boost::move(t_); }
|
||||
T & get_lvalue() { return t_; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ref_holder<T &&>
|
||||
{
|
||||
ref_holder(T &&t)
|
||||
: t(t)
|
||||
{}
|
||||
T &t;
|
||||
T && get() { return ::boost::move(t_); }
|
||||
T & get_lvalue() { return t_; }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \
|
||||
::boost::interprocess::ipcdetail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
|
||||
BOOST_PP_CAT(++m_p, n).get_lvalue() \
|
||||
//!
|
||||
|
||||
#else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data)\
|
||||
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
|
||||
BOOST_PP_CAT(++m_p, n) \
|
||||
//!
|
||||
|
||||
#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \
|
||||
BOOST_PP_CAT(++m_p, n) \
|
||||
//!
|
||||
|
||||
#endif
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
|
||||
::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
|
||||
//!
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \
|
||||
//!
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
|
||||
BOOST_PP_CAT(*m_p, n).get_lvalue() \
|
||||
//!
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
|
||||
::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
|
||||
//!
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
|
||||
BOOST_PP_CAT(*m_p, n) \
|
||||
//!
|
||||
|
||||
|
||||
#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#else
|
||||
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#error "This file is not needed when perfect forwarding is available"
|
||||
#endif
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
|
@ -0,0 +1,511 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_SEGMENT_MANAGER_BASE_HPP
|
||||
#define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/in_place_interface.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <cstddef> //std::size_t
|
||||
#include <string> //char_traits
|
||||
#include <new> //std::nothrow
|
||||
#include <utility> //std::pair
|
||||
#include <boost/assert.hpp> //BOOST_ASSERT
|
||||
#include <functional> //unary_function
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include <exception>
|
||||
#endif
|
||||
|
||||
//!\file
|
||||
//!Describes the object placed in a memory segment that provides
|
||||
//!named object allocation capabilities.
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
|
||||
template<class MemoryManager>
|
||||
class segment_manager_base;
|
||||
|
||||
//!An integer that describes the type of the
|
||||
//!instance constructed in memory
|
||||
enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type };
|
||||
|
||||
namespace ipcdetail{
|
||||
|
||||
template<class MemoryAlgorithm>
|
||||
class mem_algo_deallocator
|
||||
{
|
||||
void * m_ptr;
|
||||
MemoryAlgorithm & m_algo;
|
||||
|
||||
public:
|
||||
mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo)
|
||||
: m_ptr(ptr), m_algo(algo)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
~mem_algo_deallocator()
|
||||
{ if(m_ptr) m_algo.deallocate(m_ptr); }
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template<class size_type>
|
||||
struct block_header
|
||||
{
|
||||
size_type m_value_bytes;
|
||||
unsigned short m_num_char;
|
||||
unsigned char m_value_alignment;
|
||||
unsigned char m_alloc_type_sizeof_char;
|
||||
|
||||
block_header(size_type val_bytes
|
||||
,size_type val_alignment
|
||||
,unsigned char al_type
|
||||
,std::size_t szof_char
|
||||
,std::size_t num_char
|
||||
)
|
||||
: 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) )
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
block_header &operator= (const T& )
|
||||
{ return *this; }
|
||||
|
||||
size_type total_size() const
|
||||
{
|
||||
if(alloc_type() != anonymous_type){
|
||||
return name_offset() + (m_num_char+1)*sizeof_char();
|
||||
}
|
||||
else{
|
||||
return this->value_offset() + m_value_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
size_type value_bytes() const
|
||||
{ return m_value_bytes; }
|
||||
|
||||
template<class Header>
|
||||
size_type total_size_with_header() const
|
||||
{
|
||||
return get_rounded_size
|
||||
( size_type(sizeof(Header))
|
||||
, size_type(::boost::alignment_of<block_header<size_type> >::value))
|
||||
+ total_size();
|
||||
}
|
||||
|
||||
unsigned char alloc_type() const
|
||||
{ return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; }
|
||||
|
||||
unsigned char sizeof_char() const
|
||||
{ return m_alloc_type_sizeof_char & (unsigned char)0x1F; }
|
||||
|
||||
template<class CharType>
|
||||
CharType *name() const
|
||||
{
|
||||
return const_cast<CharType*>(reinterpret_cast<const CharType*>
|
||||
(reinterpret_cast<const char*>(this) + name_offset()));
|
||||
}
|
||||
|
||||
unsigned short name_length() const
|
||||
{ return m_num_char; }
|
||||
|
||||
size_type name_offset() const
|
||||
{
|
||||
return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char()));
|
||||
}
|
||||
|
||||
void *value() const
|
||||
{
|
||||
return const_cast<char*>((reinterpret_cast<const char*>(this) + this->value_offset()));
|
||||
}
|
||||
|
||||
size_type value_offset() const
|
||||
{
|
||||
return get_rounded_size(size_type(sizeof(block_header<size_type>)), size_type(m_value_alignment));
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool less_comp(const block_header<size_type> &b) const
|
||||
{
|
||||
return m_num_char < b.m_num_char ||
|
||||
(m_num_char < b.m_num_char &&
|
||||
std::char_traits<CharType>::compare
|
||||
(name<CharType>(), b.name<CharType>(), m_num_char) < 0);
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool equal_comp(const block_header<size_type> &b) const
|
||||
{
|
||||
return m_num_char == b.m_num_char &&
|
||||
std::char_traits<CharType>::compare
|
||||
(name<CharType>(), b.name<CharType>(), m_num_char) == 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static block_header<size_type> *block_header_from_value(T *value)
|
||||
{ return block_header_from_value(value, sizeof(T), ::boost::alignment_of<T>::value); }
|
||||
|
||||
static block_header<size_type> *block_header_from_value(const void *value, std::size_t sz, std::size_t algn)
|
||||
{
|
||||
block_header * hdr =
|
||||
const_cast<block_header*>
|
||||
(reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) -
|
||||
get_rounded_size(sizeof(block_header), algn)));
|
||||
(void)sz;
|
||||
//Some sanity checks
|
||||
BOOST_ASSERT(hdr->m_value_alignment == algn);
|
||||
BOOST_ASSERT(hdr->m_value_bytes % sz == 0);
|
||||
return hdr;
|
||||
}
|
||||
|
||||
template<class 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) +
|
||||
get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
|
||||
//Some sanity checks
|
||||
return hdr;
|
||||
}
|
||||
|
||||
template<class Header>
|
||||
static Header *to_first_header(block_header<size_type> *bheader)
|
||||
{
|
||||
Header * hdr =
|
||||
reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
|
||||
get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
|
||||
//Some sanity checks
|
||||
return hdr;
|
||||
}
|
||||
};
|
||||
|
||||
inline void array_construct(void *mem, std::size_t num, in_place_interface &table)
|
||||
{
|
||||
//Try constructors
|
||||
std::size_t constructed = 0;
|
||||
BOOST_TRY{
|
||||
table.construct_n(mem, num, constructed);
|
||||
}
|
||||
//If there is an exception call destructors and erase index node
|
||||
BOOST_CATCH(...){
|
||||
std::size_t destroyed = 0;
|
||||
table.destroy_n(mem, constructed, destroyed);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template<class CharT>
|
||||
struct intrusive_compare_key
|
||||
{
|
||||
typedef CharT char_type;
|
||||
|
||||
intrusive_compare_key(const CharT *str, std::size_t len)
|
||||
: mp_str(str), m_len(len)
|
||||
{}
|
||||
|
||||
const CharT * mp_str;
|
||||
std::size_t m_len;
|
||||
};
|
||||
|
||||
//!This struct indicates an anonymous object creation
|
||||
//!allocation
|
||||
template<instance_type type>
|
||||
class instance_t
|
||||
{
|
||||
instance_t(){}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct char_if_void
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct char_if_void<void>
|
||||
{
|
||||
typedef char type;
|
||||
};
|
||||
|
||||
typedef instance_t<anonymous_type> anonymous_instance_t;
|
||||
typedef instance_t<unique_type> unique_instance_t;
|
||||
|
||||
|
||||
template<class Hook, class CharType, class SizeType>
|
||||
struct intrusive_value_type_impl
|
||||
: public Hook
|
||||
{
|
||||
private:
|
||||
//Non-copyable
|
||||
intrusive_value_type_impl(const intrusive_value_type_impl &);
|
||||
intrusive_value_type_impl& operator=(const intrusive_value_type_impl &);
|
||||
|
||||
public:
|
||||
typedef CharType char_type;
|
||||
typedef SizeType size_type;
|
||||
|
||||
intrusive_value_type_impl(){}
|
||||
|
||||
enum { BlockHdrAlignment = ::boost::alignment_of<block_header<size_type> >::value };
|
||||
|
||||
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) +
|
||||
get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
|
||||
}
|
||||
|
||||
bool operator <(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
|
||||
{ return (this->get_block_header())->template less_comp<CharType>(*other.get_block_header()); }
|
||||
|
||||
bool operator ==(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
|
||||
{ return (this->get_block_header())->template equal_comp<CharType>(*other.get_block_header()); }
|
||||
|
||||
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) -
|
||||
get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
|
||||
}
|
||||
|
||||
CharType *name() const
|
||||
{ return get_block_header()->template name<CharType>(); }
|
||||
|
||||
unsigned short name_length() const
|
||||
{ return get_block_header()->name_length(); }
|
||||
|
||||
void *value() const
|
||||
{ return get_block_header()->value(); }
|
||||
};
|
||||
|
||||
template<class CharType>
|
||||
class char_ptr_holder
|
||||
{
|
||||
public:
|
||||
char_ptr_holder(const CharType *name)
|
||||
: m_name(name)
|
||||
{}
|
||||
|
||||
char_ptr_holder(const anonymous_instance_t *)
|
||||
: m_name(static_cast<CharType*>(0))
|
||||
{}
|
||||
|
||||
char_ptr_holder(const unique_instance_t *)
|
||||
: m_name(reinterpret_cast<CharType*>(-1))
|
||||
{}
|
||||
|
||||
operator const CharType *()
|
||||
{ return m_name; }
|
||||
|
||||
private:
|
||||
const CharType *m_name;
|
||||
};
|
||||
|
||||
//!The key of the the named allocation information index. Stores an offset pointer
|
||||
//!to a null terminated string and the length of the string to speed up sorting
|
||||
template<class CharT, class VoidPointer>
|
||||
struct index_key
|
||||
{
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<VoidPointer>::template
|
||||
rebind_pointer<const CharT>::type const_char_ptr_t;
|
||||
typedef CharT char_type;
|
||||
typedef typename boost::intrusive::pointer_traits<const_char_ptr_t>::difference_type difference_type;
|
||||
typedef typename boost::make_unsigned<difference_type>::type size_type;
|
||||
|
||||
private:
|
||||
//Offset pointer to the object's name
|
||||
const_char_ptr_t mp_str;
|
||||
//Length of the name buffer (null NOT included)
|
||||
size_type m_len;
|
||||
public:
|
||||
|
||||
//!Constructor of the key
|
||||
index_key (const char_type *nm, size_type length)
|
||||
: mp_str(nm), m_len(length)
|
||||
{}
|
||||
|
||||
//!Less than function for index ordering
|
||||
bool operator < (const index_key & right) const
|
||||
{
|
||||
return (m_len < right.m_len) ||
|
||||
(m_len == right.m_len &&
|
||||
std::char_traits<char_type>::compare
|
||||
(to_raw_pointer(mp_str)
|
||||
,to_raw_pointer(right.mp_str), m_len) < 0);
|
||||
}
|
||||
|
||||
//!Equal to function for index ordering
|
||||
bool operator == (const index_key & right) const
|
||||
{
|
||||
return m_len == right.m_len &&
|
||||
std::char_traits<char_type>::compare
|
||||
(to_raw_pointer(mp_str),
|
||||
to_raw_pointer(right.mp_str), m_len) == 0;
|
||||
}
|
||||
|
||||
void name(const CharT *nm)
|
||||
{ mp_str = nm; }
|
||||
|
||||
void name_length(size_type len)
|
||||
{ m_len = len; }
|
||||
|
||||
const CharT *name() const
|
||||
{ return to_raw_pointer(mp_str); }
|
||||
|
||||
size_type name_length() const
|
||||
{ return m_len; }
|
||||
};
|
||||
|
||||
//!The index_data stores a pointer to a buffer and the element count needed
|
||||
//!to know how many destructors must be called when calling destroy
|
||||
template<class VoidPointer>
|
||||
struct index_data
|
||||
{
|
||||
typedef VoidPointer void_pointer;
|
||||
void_pointer m_ptr;
|
||||
index_data(void *ptr) : m_ptr(ptr){}
|
||||
|
||||
void *value() const
|
||||
{ return static_cast<void*>(to_raw_pointer(m_ptr)); }
|
||||
};
|
||||
|
||||
template<class MemoryAlgorithm>
|
||||
struct segment_manager_base_type
|
||||
{ typedef segment_manager_base<MemoryAlgorithm> type; };
|
||||
|
||||
template<class CharT, class MemoryAlgorithm>
|
||||
struct index_config
|
||||
{
|
||||
typedef typename MemoryAlgorithm::void_pointer void_pointer;
|
||||
typedef CharT char_type;
|
||||
typedef index_key<CharT, void_pointer> key_type;
|
||||
typedef index_data<void_pointer> mapped_type;
|
||||
typedef typename segment_manager_base_type
|
||||
<MemoryAlgorithm>::type segment_manager_base;
|
||||
|
||||
template<class HeaderBase>
|
||||
struct intrusive_value_type
|
||||
{ typedef intrusive_value_type_impl<HeaderBase, CharT, typename segment_manager_base::size_type> type; };
|
||||
|
||||
typedef intrusive_compare_key<CharT> intrusive_compare_key_type;
|
||||
};
|
||||
|
||||
template<class Iterator, bool intrusive>
|
||||
class segment_manager_iterator_value_adaptor
|
||||
{
|
||||
typedef typename Iterator::value_type iterator_val_t;
|
||||
typedef typename iterator_val_t::char_type char_type;
|
||||
|
||||
public:
|
||||
segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
|
||||
: m_val(&val)
|
||||
{}
|
||||
|
||||
const char_type *name() const
|
||||
{ return m_val->name(); }
|
||||
|
||||
unsigned short name_length() const
|
||||
{ return m_val->name_length(); }
|
||||
|
||||
const void *value() const
|
||||
{ return m_val->value(); }
|
||||
|
||||
const typename Iterator::value_type *m_val;
|
||||
};
|
||||
|
||||
|
||||
template<class Iterator>
|
||||
class segment_manager_iterator_value_adaptor<Iterator, false>
|
||||
{
|
||||
typedef typename Iterator::value_type iterator_val_t;
|
||||
typedef typename iterator_val_t::first_type first_type;
|
||||
typedef typename iterator_val_t::second_type second_type;
|
||||
typedef typename first_type::char_type char_type;
|
||||
typedef typename first_type::size_type size_type;
|
||||
|
||||
public:
|
||||
segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
|
||||
: m_val(&val)
|
||||
{}
|
||||
|
||||
const char_type *name() const
|
||||
{ return m_val->first.name(); }
|
||||
|
||||
size_type name_length() const
|
||||
{ return m_val->first.name_length(); }
|
||||
|
||||
const void *value() const
|
||||
{
|
||||
return reinterpret_cast<block_header<size_type>*>
|
||||
(to_raw_pointer(m_val->second.m_ptr))->value();
|
||||
}
|
||||
|
||||
const typename Iterator::value_type *m_val;
|
||||
};
|
||||
|
||||
template<class Iterator, bool intrusive>
|
||||
struct segment_manager_iterator_transform
|
||||
: std::unary_function< typename Iterator::value_type
|
||||
, segment_manager_iterator_value_adaptor<Iterator, intrusive> >
|
||||
{
|
||||
typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type;
|
||||
|
||||
result_type operator()(const typename Iterator::value_type &arg) const
|
||||
{ return result_type(arg); }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
//These pointers are the ones the user will use to
|
||||
//indicate previous allocation types
|
||||
static const ipcdetail::anonymous_instance_t * anonymous_instance = 0;
|
||||
static const ipcdetail::unique_instance_t * unique_instance = 0;
|
||||
|
||||
namespace ipcdetail_really_deep_namespace {
|
||||
|
||||
//Otherwise, gcc issues a warning of previously defined
|
||||
//anonymous_instance and unique_instance
|
||||
struct dummy
|
||||
{
|
||||
dummy()
|
||||
{
|
||||
(void)anonymous_instance;
|
||||
(void)unique_instance;
|
||||
}
|
||||
};
|
||||
|
||||
} //detail_really_deep_namespace
|
||||
|
||||
}} //namespace boost { namespace interprocess
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
|
||||
|
181
cpp/BoostParts/boost/interprocess/detail/tmp_dir_helpers.hpp
Normal file
181
cpp/BoostParts/boost/interprocess/detail/tmp_dir_helpers.hpp
Normal file
@ -0,0 +1,181 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-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_TMP_DIR_HELPERS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <string>
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
#include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
//This type will initialize the stamp
|
||||
struct windows_bootstamp
|
||||
{
|
||||
windows_bootstamp()
|
||||
{
|
||||
winapi::get_last_bootup_time(stamp);
|
||||
}
|
||||
//Use std::string. Even if this will be constructed in shared memory, all
|
||||
//modules/dlls are from this process so internal raw pointers to heap are always valid
|
||||
std::string stamp;
|
||||
};
|
||||
|
||||
inline void get_bootstamp(std::string &s, bool add = false)
|
||||
{
|
||||
const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
|
||||
if(add){
|
||||
s += bootstamp.stamp;
|
||||
}
|
||||
else{
|
||||
s = bootstamp.stamp;
|
||||
}
|
||||
}
|
||||
#elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
|
||||
inline void get_bootstamp(std::string &s, bool add = false)
|
||||
{
|
||||
// FreeBSD specific: sysctl "kern.boottime"
|
||||
int request[2] = { CTL_KERN, KERN_BOOTTIME };
|
||||
struct ::timeval result;
|
||||
std::size_t result_len = sizeof result;
|
||||
|
||||
if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
|
||||
return;
|
||||
|
||||
char bootstamp_str[256];
|
||||
|
||||
const char Characters [] =
|
||||
{ '0', '1', '2', '3', '4', '5', '6', '7'
|
||||
, '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
std::size_t char_counter = 0;
|
||||
//32 bit values to allow 32 and 64 bit process IPC
|
||||
boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) };
|
||||
for(std::size_t field = 0; field != 2; ++field){
|
||||
for(std::size_t i = 0; i != sizeof(fields[0]); ++i){
|
||||
const char *ptr = (const char *)&fields[field];
|
||||
bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
|
||||
bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
|
||||
}
|
||||
}
|
||||
bootstamp_str[char_counter] = 0;
|
||||
if(add){
|
||||
s += bootstamp_str;
|
||||
}
|
||||
else{
|
||||
s = bootstamp_str;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error "BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME defined with no known implementation"
|
||||
#endif
|
||||
#endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
|
||||
|
||||
inline void get_tmp_base_dir(std::string &tmp_name)
|
||||
{
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
winapi::get_shared_documents_folder(tmp_name);
|
||||
if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){
|
||||
tmp_name = get_temporary_path();
|
||||
}
|
||||
#else
|
||||
tmp_name = get_temporary_path();
|
||||
#endif
|
||||
if(tmp_name.empty()){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//Remove final null.
|
||||
tmp_name += "/boost_interprocess";
|
||||
}
|
||||
|
||||
inline void tmp_folder(std::string &tmp_name)
|
||||
{
|
||||
get_tmp_base_dir(tmp_name);
|
||||
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
|
||||
tmp_name += "/";
|
||||
get_bootstamp(tmp_name, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void tmp_filename(const char *filename, std::string &tmp_name)
|
||||
{
|
||||
tmp_folder(tmp_name);
|
||||
tmp_name += "/";
|
||||
tmp_name += filename;
|
||||
}
|
||||
|
||||
inline void create_tmp_and_clean_old(std::string &tmp_name)
|
||||
{
|
||||
//First get the temp directory
|
||||
std::string root_tmp_name;
|
||||
get_tmp_base_dir(root_tmp_name);
|
||||
|
||||
//If fails, check that it's because already exists
|
||||
if(!create_directory(root_tmp_name.c_str())){
|
||||
error_info info(system_error_code());
|
||||
if(info.get_error_code() != already_exists_error){
|
||||
throw interprocess_exception(info);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
|
||||
tmp_folder(tmp_name);
|
||||
|
||||
//If fails, check that it's because already exists
|
||||
if(!create_directory(tmp_name.c_str())){
|
||||
error_info info(system_error_code());
|
||||
if(info.get_error_code() != already_exists_error){
|
||||
throw interprocess_exception(info);
|
||||
}
|
||||
}
|
||||
//Now erase all old directories created in the previous boot sessions
|
||||
std::string subdir = tmp_name;
|
||||
subdir.erase(0, root_tmp_name.size()+1);
|
||||
delete_subdirectories(root_tmp_name, subdir.c_str());
|
||||
#else
|
||||
tmp_name = root_tmp_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name)
|
||||
{
|
||||
create_tmp_and_clean_old(tmp_name);
|
||||
tmp_name += "/";
|
||||
tmp_name += filename;
|
||||
}
|
||||
|
||||
inline void add_leading_slash(const char *name, std::string &new_name)
|
||||
{
|
||||
if(name[0] != '/'){
|
||||
new_name = '/';
|
||||
}
|
||||
new_name += name;
|
||||
}
|
||||
|
||||
} //namespace boost{
|
||||
} //namespace interprocess {
|
||||
} //namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
|
195
cpp/BoostParts/boost/interprocess/detail/transform_iterator.hpp
Normal file
195
cpp/BoostParts/boost/interprocess/detail/transform_iterator.hpp
Normal file
@ -0,0 +1,195 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2012.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// 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_TRANSFORM_ITERATORS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
template <class PseudoReference>
|
||||
struct operator_arrow_proxy
|
||||
{
|
||||
operator_arrow_proxy(const PseudoReference &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
PseudoReference* operator->() const { return &m_value; }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
mutable PseudoReference m_value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct operator_arrow_proxy<T&>
|
||||
{
|
||||
operator_arrow_proxy(T &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
T* operator->() const { return const_cast<T*>(&m_value); }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
T &m_value;
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunction>
|
||||
class transform_iterator
|
||||
: public UnaryFunction
|
||||
, public std::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, typename ipcdetail::remove_reference<typename UnaryFunction::result_type>::type
|
||||
, typename Iterator::difference_type
|
||||
, operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
, typename UnaryFunction::result_type>
|
||||
{
|
||||
public:
|
||||
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
|
||||
: UnaryFunction(f), m_it(it)
|
||||
{}
|
||||
|
||||
explicit transform_iterator()
|
||||
: UnaryFunction(), m_it()
|
||||
{}
|
||||
|
||||
//Constructors
|
||||
transform_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
transform_iterator operator++(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
transform_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
transform_iterator operator--(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i < i2; }
|
||||
|
||||
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
transform_iterator& operator+=(typename Iterator::difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
transform_iterator operator+(typename Iterator::difference_type off) const
|
||||
{
|
||||
transform_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
transform_iterator& operator-=(typename Iterator::difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
transform_iterator operator-(typename Iterator::difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
typename UnaryFunction::result_type operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
typename UnaryFunction::result_type operator[](typename Iterator::difference_type off) const
|
||||
{ return UnaryFunction::operator()(m_it[off]); }
|
||||
|
||||
operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
operator->() const
|
||||
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
|
||||
|
||||
Iterator & base()
|
||||
{ return m_it; }
|
||||
|
||||
const Iterator & base() const
|
||||
{ return m_it; }
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
|
||||
void increment()
|
||||
{ ++m_it; }
|
||||
|
||||
void decrement()
|
||||
{ --m_it; }
|
||||
|
||||
bool equal(const transform_iterator &other) const
|
||||
{ return m_it == other.m_it; }
|
||||
|
||||
bool less(const transform_iterator &other) const
|
||||
{ return other.m_it < m_it; }
|
||||
|
||||
typename UnaryFunction::result_type dereference() const
|
||||
{ return UnaryFunction::operator()(*m_it); }
|
||||
|
||||
void advance(typename Iterator::difference_type n)
|
||||
{ std::advance(m_it, n); }
|
||||
|
||||
typename Iterator::difference_type distance_to(const transform_iterator &other)const
|
||||
{ return std::distance(other.m_it, m_it); }
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunc>
|
||||
transform_iterator<Iterator, UnaryFunc>
|
||||
make_transform_iterator(Iterator it, UnaryFunc fun)
|
||||
{
|
||||
return transform_iterator<Iterator, UnaryFunc>(it, fun);
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
158
cpp/BoostParts/boost/interprocess/detail/type_traits.hpp
Normal file
158
cpp/BoostParts/boost/interprocess/detail/type_traits.hpp
Normal file
@ -0,0 +1,158 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// (C) Copyright John Maddock 2000.
|
||||
// (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_TYPE_TRAITS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
struct nat{};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_reference
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_reference<T&>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer<T*>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct add_reference
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct add_reference<T&>
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_reference<void>
|
||||
{
|
||||
typedef nat &type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_reference<const void>
|
||||
{
|
||||
typedef const nat &type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct add_const_reference
|
||||
{ typedef const T &type; };
|
||||
|
||||
template <class T>
|
||||
struct add_const_reference<T&>
|
||||
{ typedef T& type; };
|
||||
|
||||
template<class T>
|
||||
struct remove_const
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_const<const T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_volatile
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_volatile<volatile T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_const_volatile
|
||||
{
|
||||
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same
|
||||
{
|
||||
typedef char yes_type;
|
||||
struct no_type
|
||||
{
|
||||
char padding[8];
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
static yes_type is_same_tester(V*, V*);
|
||||
static no_type is_same_tester(...);
|
||||
|
||||
static T *t;
|
||||
static U *u;
|
||||
|
||||
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct is_cv_same
|
||||
{
|
||||
static const bool value = is_same< typename remove_const_volatile<T>::type
|
||||
, typename remove_const_volatile<U>::type >::value;
|
||||
};
|
||||
|
||||
} // namespace ipcdetail
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
|
218
cpp/BoostParts/boost/interprocess/detail/utilities.hpp
Normal file
218
cpp/BoostParts/boost/interprocess/detail/utilities.hpp
Normal file
@ -0,0 +1,218 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2012.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// 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_UTILITIES_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/type_traits/has_trivial_destructor.hpp>
|
||||
#include <boost/interprocess/detail/min_max.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/transform_iterator.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/containers/version_type.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template <class T>
|
||||
inline T* to_raw_pointer(T* p)
|
||||
{ return p; }
|
||||
|
||||
template <class Pointer>
|
||||
inline typename boost::intrusive::pointer_traits<Pointer>::element_type*
|
||||
to_raw_pointer(const Pointer &p)
|
||||
{ return boost::interprocess::ipcdetail::to_raw_pointer(p.operator->()); }
|
||||
|
||||
//!To avoid ADL problems with swap
|
||||
template <class T>
|
||||
inline void do_swap(T& x, T& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
}
|
||||
|
||||
//Rounds "orig_size" by excess to round_to bytes
|
||||
template<class SizeType>
|
||||
inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to)
|
||||
{
|
||||
return ((orig_size-1)/round_to+1)*round_to;
|
||||
}
|
||||
|
||||
//Truncates "orig_size" to a multiple of "multiple" bytes.
|
||||
template<class SizeType>
|
||||
inline SizeType get_truncated_size(SizeType orig_size, SizeType multiple)
|
||||
{
|
||||
return orig_size/multiple*multiple;
|
||||
}
|
||||
|
||||
//Rounds "orig_size" by excess to round_to bytes. round_to must be power of two
|
||||
template<class SizeType>
|
||||
inline SizeType get_rounded_size_po2(SizeType orig_size, SizeType round_to)
|
||||
{
|
||||
return ((orig_size-1)&(~(round_to-1))) + round_to;
|
||||
}
|
||||
|
||||
//Truncates "orig_size" to a multiple of "multiple" bytes. multiple must be power of two
|
||||
template<class SizeType>
|
||||
inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple)
|
||||
{
|
||||
return (orig_size & (~(multiple-1)));
|
||||
}
|
||||
|
||||
template <std::size_t OrigSize, std::size_t RoundTo>
|
||||
struct ct_rounded_size
|
||||
{
|
||||
BOOST_STATIC_ASSERT((RoundTo != 0));
|
||||
static const std::size_t intermediate_value = (OrigSize-1)/RoundTo+1;
|
||||
BOOST_STATIC_ASSERT(intermediate_value <= std::size_t(-1)/RoundTo);
|
||||
static const std::size_t value = intermediate_value*RoundTo;
|
||||
};
|
||||
|
||||
// Gennaro Prota wrote this. Thanks!
|
||||
template <int p, int n = 4>
|
||||
struct ct_max_pow2_less
|
||||
{
|
||||
static const std::size_t c = 2*n < p;
|
||||
|
||||
static const std::size_t value =
|
||||
c ? (ct_max_pow2_less< c*p, 2*c*n>::value) : n;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ct_max_pow2_less<0, 0>
|
||||
{
|
||||
static const std::size_t value = 0;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
//!Trait class to detect if an index is a node
|
||||
//!index. This allows more efficient operations
|
||||
//!when deallocating named objects.
|
||||
template <class Index>
|
||||
struct is_node_index
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
//!Trait class to detect if an index is an intrusive
|
||||
//!index. This will embed the derivation hook in each
|
||||
//!allocation header, to provide memory for the intrusive
|
||||
//!container.
|
||||
template <class Index>
|
||||
struct is_intrusive_index
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename T> T*
|
||||
addressof(T& v)
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
||||
}
|
||||
|
||||
template<class SizeType>
|
||||
struct sqrt_size_type_max
|
||||
{
|
||||
static const SizeType value = (SizeType(1) << (sizeof(SizeType)*(CHAR_BIT/2)))-1;
|
||||
};
|
||||
|
||||
template<class SizeType>
|
||||
inline bool multiplication_overflows(SizeType a, SizeType b)
|
||||
{
|
||||
const SizeType sqrt_size_max = sqrt_size_type_max<SizeType>::value;
|
||||
return //Fast runtime check
|
||||
( (a | b) > sqrt_size_max &&
|
||||
//Slow division check
|
||||
b && a > SizeType(-1)/b
|
||||
);
|
||||
}
|
||||
|
||||
template<std::size_t SztSizeOfType, class SizeType>
|
||||
inline bool size_overflows(SizeType count)
|
||||
{
|
||||
//Compile time-check
|
||||
BOOST_STATIC_ASSERT(SztSizeOfType <= SizeType(-1));
|
||||
//Runtime check
|
||||
return multiplication_overflows(SizeType(SztSizeOfType), count);
|
||||
}
|
||||
|
||||
template<class RawPointer>
|
||||
class pointer_size_t_caster
|
||||
{
|
||||
public:
|
||||
explicit pointer_size_t_caster(std::size_t sz)
|
||||
: m_ptr(reinterpret_cast<RawPointer>(sz))
|
||||
{}
|
||||
|
||||
explicit pointer_size_t_caster(RawPointer p)
|
||||
: m_ptr(p)
|
||||
{}
|
||||
|
||||
std::size_t size() const
|
||||
{ return reinterpret_cast<std::size_t>(m_ptr); }
|
||||
|
||||
RawPointer pointer() const
|
||||
{ return m_ptr; }
|
||||
|
||||
private:
|
||||
RawPointer m_ptr;
|
||||
};
|
||||
|
||||
|
||||
template<class SizeType>
|
||||
inline bool sum_overflows(SizeType a, SizeType b)
|
||||
{ return SizeType(-1) - a < b; }
|
||||
|
||||
//Anti-exception node eraser
|
||||
template<class Cont>
|
||||
class value_eraser
|
||||
{
|
||||
public:
|
||||
value_eraser(Cont & cont, typename Cont::iterator it)
|
||||
: m_cont(cont), m_index_it(it), m_erase(true){}
|
||||
~value_eraser()
|
||||
{ if(m_erase) m_cont.erase(m_index_it); }
|
||||
|
||||
void release() { m_erase = false; }
|
||||
|
||||
private:
|
||||
Cont &m_cont;
|
||||
typename Cont::iterator m_index_it;
|
||||
bool m_erase;
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
|
||||
|
@ -0,0 +1,153 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-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_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <cstddef> //std::size_t
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<typename... Values>
|
||||
class tuple;
|
||||
|
||||
template<> class tuple<>
|
||||
{};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
class tuple<Head, Tail...>
|
||||
: private tuple<Tail...>
|
||||
{
|
||||
typedef tuple<Tail...> inherited;
|
||||
|
||||
public:
|
||||
tuple() { }
|
||||
|
||||
// implicit copy-constructor is okay
|
||||
// Construct tuple from separate arguments.
|
||||
tuple(typename add_const_reference<Head>::type v,
|
||||
typename add_const_reference<Tail>::type... vtail)
|
||||
: inherited(vtail...), m_head(v)
|
||||
{}
|
||||
|
||||
// Construct tuple from another tuple.
|
||||
template<typename... VValues>
|
||||
tuple(const tuple<VValues...>& other)
|
||||
: m_head(other.head()), inherited(other.tail())
|
||||
{}
|
||||
|
||||
template<typename... VValues>
|
||||
tuple& operator=(const tuple<VValues...>& other)
|
||||
{
|
||||
m_head = other.head();
|
||||
tail() = other.tail();
|
||||
return this;
|
||||
}
|
||||
|
||||
typename add_reference<Head>::type head() { return m_head; }
|
||||
typename add_reference<const Head>::type head() const { return m_head; }
|
||||
|
||||
inherited& tail() { return *this; }
|
||||
const inherited& tail() const { return *this; }
|
||||
|
||||
protected:
|
||||
Head m_head;
|
||||
};
|
||||
|
||||
|
||||
template<typename... Values>
|
||||
tuple<Values&&...> tie_forward(Values&&... values)
|
||||
{ return tuple<Values&&...>(values...); }
|
||||
|
||||
template<int I, typename Tuple>
|
||||
struct tuple_element;
|
||||
|
||||
template<int I, typename Head, typename... Tail>
|
||||
struct tuple_element<I, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
|
||||
};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
struct tuple_element<0, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef Head type;
|
||||
};
|
||||
|
||||
template<int I, typename Tuple>
|
||||
class get_impl;
|
||||
|
||||
template<int I, typename Head, typename... Values>
|
||||
class get_impl<I, tuple<Head, Values...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
|
||||
typedef get_impl<I-1, tuple<Values...> > Next;
|
||||
|
||||
public:
|
||||
typedef typename add_reference<Element>::type type;
|
||||
typedef typename add_const_reference<Element>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
};
|
||||
|
||||
template<typename Head, typename... Values>
|
||||
class get_impl<0, tuple<Head, Values...> >
|
||||
{
|
||||
public:
|
||||
typedef typename add_reference<Head>::type type;
|
||||
typedef typename add_const_reference<Head>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return t.head(); }
|
||||
static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
|
||||
};
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
|
||||
// be used to "unpack" into comma-separated values
|
||||
// in a function call.
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
template<int... Indexes>
|
||||
struct index_tuple{};
|
||||
|
||||
template<std::size_t Num, typename Tuple = index_tuple<> >
|
||||
struct build_number_seq;
|
||||
|
||||
template<std::size_t Num, int... Indexes>
|
||||
struct build_number_seq<Num, index_tuple<Indexes...> >
|
||||
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
|
||||
{};
|
||||
|
||||
template<int... Indexes>
|
||||
struct build_number_seq<0, index_tuple<Indexes...> >
|
||||
{ typedef index_tuple<Indexes...> type; };
|
||||
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
1852
cpp/BoostParts/boost/interprocess/detail/win32_api.hpp
Normal file
1852
cpp/BoostParts/boost/interprocess/detail/win32_api.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,306 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
|
||||
#define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
#error "This header can't be included from non-windows operating systems"
|
||||
#endif
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/interprocess/detail/intermodule_singleton_common.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
namespace intermodule_singleton_helpers {
|
||||
|
||||
//This global map will be implemented using 3 sync primitives:
|
||||
//
|
||||
//1) A named mutex that will implement global mutual exclusion between
|
||||
// threads from different modules/dlls
|
||||
//
|
||||
//2) A semaphore that will act as a global counter for modules attached to the global map
|
||||
// so that the global map can be destroyed when the last module is detached.
|
||||
//
|
||||
//3) A semaphore that will be hacked to hold the address of a heap-allocated map in the
|
||||
// max and current semaphore count.
|
||||
class windows_semaphore_based_map
|
||||
{
|
||||
typedef std::map<std::string, ref_count_ptr> map_type;
|
||||
|
||||
public:
|
||||
windows_semaphore_based_map()
|
||||
{
|
||||
map_type *m = new map_type;
|
||||
boost::uint32_t initial_count = 0;
|
||||
boost::uint32_t max_count = 0;
|
||||
|
||||
//Windows user address space sizes:
|
||||
//32 bit windows: [32 bit processes] 2GB or 3GB (31/32 bits)
|
||||
//64 bit windows: [32 bit processes] 2GB or 4GB (31/32 bits)
|
||||
// [64 bit processes] 2GB or 8TB (31/43 bits)
|
||||
//
|
||||
//Windows semaphores use 'long' parameters (32 bits in LLP64 data model) and
|
||||
//those values can't be negative, so we have 31 bits to store something
|
||||
//in max_count and initial count parameters.
|
||||
//Also, max count must be bigger than 0 and bigger or equal than initial count.
|
||||
if(sizeof(void*) == sizeof(boost::uint32_t)){
|
||||
//This means that for 32 bit processes, a semaphore count (31 usable bits) is
|
||||
//enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits).
|
||||
//The max count will hold the pointer value and current semaphore count
|
||||
//will be zero.
|
||||
//
|
||||
//Relying in UB with a cast through union, but all known windows compilers
|
||||
//accept this (C11 also accepts this).
|
||||
union caster_union
|
||||
{
|
||||
void *addr;
|
||||
boost::uint32_t addr_uint32;
|
||||
} caster;
|
||||
caster.addr = m;
|
||||
//memory is at least 4 byte aligned in windows
|
||||
BOOST_ASSERT((caster.addr_uint32 & boost::uint32_t(3)) == 0);
|
||||
max_count = caster.addr_uint32 >> 2;
|
||||
}
|
||||
else if(sizeof(void*) == sizeof(boost::uint64_t)){
|
||||
//Relying in UB with a cast through union, but all known windows compilers
|
||||
//accept this (C11 accepts this).
|
||||
union caster_union
|
||||
{
|
||||
void *addr;
|
||||
boost::uint64_t addr_uint64;
|
||||
} caster;
|
||||
caster.addr = m;
|
||||
//We'll encode the address using 30 bits in each 32 bit high and low parts.
|
||||
//High part will be the sem max count, low part will be the sem initial count.
|
||||
//(restrictions: max count > 0, initial count >= 0 and max count >= initial count):
|
||||
//
|
||||
// - Low part will be shifted two times (4 byte alignment) so that top
|
||||
// two bits are cleared (the top one for sign, the next one to
|
||||
// assure low part value is always less than the high part value.
|
||||
// - The top bit of the high part will be cleared and the next bit will be 1
|
||||
// (so high part is always bigger than low part due to the quasi-top bit).
|
||||
//
|
||||
// This means that the addresses we can store must be 4 byte aligned
|
||||
// and less than 1 ExbiBytes ( 2^60 bytes, ~1 ExaByte). User-level address space in Windows 64
|
||||
// is much less than this (8TB, 2^43 bytes): "1 EByte (or it was 640K?) ought to be enough for anybody" ;-).
|
||||
caster.addr = m;
|
||||
BOOST_ASSERT((caster.addr_uint64 & boost::uint64_t(3)) == 0);
|
||||
max_count = boost::uint32_t(caster.addr_uint64 >> 32);
|
||||
initial_count = boost::uint32_t(caster.addr_uint64);
|
||||
initial_count = initial_count/4;
|
||||
//Make sure top two bits are zero
|
||||
BOOST_ASSERT((max_count & boost::uint32_t(0xC0000000)) == 0);
|
||||
//Set quasi-top bit
|
||||
max_count |= boost::uint32_t(0x40000000);
|
||||
}
|
||||
bool created = false;
|
||||
const permissions & perm = permissions();
|
||||
std::string pid_creation_time, name;
|
||||
get_pid_creation_time_str(pid_creation_time);
|
||||
name = "bipc_gmap_sem_lock_";
|
||||
name += pid_creation_time;
|
||||
bool success = m_mtx_lock.open_or_create(name.c_str(), perm);
|
||||
name = "bipc_gmap_sem_count_";
|
||||
name += pid_creation_time;
|
||||
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
|
||||
{
|
||||
success = success && m_sem_count.open_or_create
|
||||
( name.c_str(), static_cast<long>(0), winapi_semaphore_wrapper::MaxCount, perm, created);
|
||||
name = "bipc_gmap_sem_map_";
|
||||
name += pid_creation_time;
|
||||
success = success && m_sem_map.open_or_create
|
||||
(name.c_str(), initial_count, max_count, perm, created);
|
||||
if(!success){
|
||||
//winapi_xxx wrappers do the cleanup...
|
||||
throw int(0);
|
||||
}
|
||||
if(!created){
|
||||
delete m;
|
||||
}
|
||||
else{
|
||||
BOOST_ASSERT(&get_map_unlocked() == m);
|
||||
}
|
||||
m_sem_count.post();
|
||||
}
|
||||
}
|
||||
|
||||
map_type &get_map_unlocked()
|
||||
{
|
||||
if(sizeof(void*) == sizeof(boost::uint32_t)){
|
||||
union caster_union
|
||||
{
|
||||
void *addr;
|
||||
boost::uint32_t addr_uint32;
|
||||
} caster;
|
||||
caster.addr = 0;
|
||||
caster.addr_uint32 = m_sem_map.limit();
|
||||
caster.addr_uint32 = caster.addr_uint32 << 2;
|
||||
return *static_cast<map_type*>(caster.addr);
|
||||
}
|
||||
else{
|
||||
union caster_union
|
||||
{
|
||||
void *addr;
|
||||
boost::uint64_t addr_uint64;
|
||||
} caster;
|
||||
boost::uint32_t max_count(m_sem_map.limit()), initial_count(m_sem_map.value());
|
||||
//Clear quasi-top bit
|
||||
max_count &= boost::uint32_t(0xBFFFFFFF);
|
||||
caster.addr_uint64 = max_count;
|
||||
caster.addr_uint64 = caster.addr_uint64 << 32;
|
||||
caster.addr_uint64 |= boost::uint64_t(initial_count) << 2;
|
||||
return *static_cast<map_type*>(caster.addr);
|
||||
}
|
||||
}
|
||||
|
||||
ref_count_ptr *find(const char *name)
|
||||
{
|
||||
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
|
||||
map_type &map = this->get_map_unlocked();
|
||||
map_type::iterator it = map.find(std::string(name));
|
||||
if(it != map.end()){
|
||||
return &it->second;
|
||||
}
|
||||
else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ref_count_ptr * insert(const char *name, const ref_count_ptr &ref)
|
||||
{
|
||||
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
|
||||
map_type &map = this->get_map_unlocked();
|
||||
map_type::iterator it = map.insert(map_type::value_type(std::string(name), ref)).first;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
bool erase(const char *name)
|
||||
{
|
||||
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
|
||||
map_type &map = this->get_map_unlocked();
|
||||
return map.erase(std::string(name)) != 0;
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void atomic_func(F &f)
|
||||
{
|
||||
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
|
||||
f();
|
||||
}
|
||||
|
||||
~windows_semaphore_based_map()
|
||||
{
|
||||
scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
|
||||
m_sem_count.wait();
|
||||
if(0 == m_sem_count.value()){
|
||||
delete &this->get_map_unlocked();
|
||||
}
|
||||
//First close sems to protect this with the external mutex
|
||||
m_sem_map.close();
|
||||
m_sem_count.close();
|
||||
//Once scoped_lock unlocks the mutex, the destructor will close the handle...
|
||||
}
|
||||
|
||||
private:
|
||||
winapi_mutex_wrapper m_mtx_lock;
|
||||
winapi_semaphore_wrapper m_sem_map;
|
||||
winapi_semaphore_wrapper m_sem_count;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct thread_safe_global_map_dependant<windows_semaphore_based_map>
|
||||
{
|
||||
static void apply_gmem_erase_logic(const char *, const char *){}
|
||||
|
||||
static bool remove_old_gmem()
|
||||
{ return true; }
|
||||
|
||||
struct lock_file_logic
|
||||
{
|
||||
lock_file_logic(windows_semaphore_based_map &)
|
||||
: retry_with_new_map(false)
|
||||
{}
|
||||
|
||||
void operator()(void){}
|
||||
bool retry() const { return retry_with_new_map; }
|
||||
private:
|
||||
const bool retry_with_new_map;
|
||||
};
|
||||
|
||||
static void construct_map(void *addr)
|
||||
{
|
||||
::new (addr)windows_semaphore_based_map;
|
||||
}
|
||||
|
||||
struct unlink_map_logic
|
||||
{
|
||||
unlink_map_logic(windows_semaphore_based_map &)
|
||||
{}
|
||||
void operator()(){}
|
||||
};
|
||||
|
||||
static ref_count_ptr *find(windows_semaphore_based_map &map, const char *name)
|
||||
{
|
||||
return map.find(name);
|
||||
}
|
||||
|
||||
static ref_count_ptr * insert(windows_semaphore_based_map &map, const char *name, const ref_count_ptr &ref)
|
||||
{
|
||||
return map.insert(name, ref);
|
||||
}
|
||||
|
||||
static bool erase(windows_semaphore_based_map &map, const char *name)
|
||||
{
|
||||
return map.erase(name);
|
||||
}
|
||||
|
||||
template<class F>
|
||||
static void atomic_func(windows_semaphore_based_map &map, F &f)
|
||||
{
|
||||
map.atomic_func(f);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intermodule_singleton_helpers {
|
||||
|
||||
template<typename C, bool LazyInit = true, bool Phoenix = true>
|
||||
class windows_intermodule_singleton
|
||||
: public intermodule_singleton_impl
|
||||
< C
|
||||
, LazyInit
|
||||
, Phoenix
|
||||
, intermodule_singleton_helpers::windows_semaphore_based_map
|
||||
>
|
||||
{};
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
|
171
cpp/BoostParts/boost/interprocess/detail/workaround.hpp
Normal file
171
cpp/BoostParts/boost/interprocess/detail/workaround.hpp
Normal file
@ -0,0 +1,171 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_WORKAROUND_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||
#define BOOST_INTERPROCESS_WINDOWS
|
||||
#define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
|
||||
#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
#else
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
|
||||
//Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
|
||||
//Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seem to work.
|
||||
#if !defined(__CYGWIN__) && !defined(__APPLE__)
|
||||
#define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0)
|
||||
#define BOOST_INTERPROCESS_POSIX_BARRIERS
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_SEMAPHORES) && ((_POSIX_SEMAPHORES - 0) > 0)
|
||||
#define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
#if defined(__CYGWIN__)
|
||||
#define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
|
||||
#endif
|
||||
//Some platforms have a limited (name length) named semaphore support
|
||||
#elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__)
|
||||
#define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
#endif
|
||||
|
||||
#if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\
|
||||
((defined _V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\
|
||||
((defined _V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\
|
||||
((defined _XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\
|
||||
((defined _XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\
|
||||
((defined _XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\
|
||||
((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\
|
||||
((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))
|
||||
#define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T
|
||||
#endif
|
||||
|
||||
//Check for XSI shared memory objects. They are available in nearly all UNIX platforms
|
||||
#if !defined(__QNXNTO__)
|
||||
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_SHARED_MEMORY_OBJECTS) && ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
|
||||
#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
#else
|
||||
//VMS and MACOS don't define it but they have shm_open/close interface
|
||||
#if defined(__vms)
|
||||
#if __CRTL_VER >= 70200000
|
||||
#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
#endif
|
||||
//Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
|
||||
#elif defined (__APPLE__)
|
||||
//#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
//#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Now check if we have only XSI shared memory
|
||||
#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) &&\
|
||||
!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
|
||||
//#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_TIMEOUTS) && ((_POSIX_TIMEOUTS - 0) > 0)
|
||||
#define BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
//Some systems have filesystem-based resources, so the
|
||||
//portable "/shmname" format does not work due to permission issues
|
||||
//For those systems we need to form a path to a temporary directory:
|
||||
// hp-ux tru64 vms freebsd
|
||||
#if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7))
|
||||
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
|
||||
//Some systems have "jailed" environments where shm usage is restricted at runtime
|
||||
//and temporary file file based shm is possible in those executions.
|
||||
#elif defined(__FreeBSD__)
|
||||
#define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
#if defined(__osf__) || defined(__vms)
|
||||
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_VERSION) && defined(_XOPEN_VERSION) && \
|
||||
(((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500))
|
||||
#define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
|
||||
#define BOOST_INTERPROCESS_BSD_DERIVATIVE
|
||||
#include <sys/sysctl.h>
|
||||
#if defined(CTL_KERN) && defined (KERN_BOOTTIME)
|
||||
//#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
#endif
|
||||
#endif
|
||||
#endif //!defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
#define BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#endif
|
||||
|
||||
//Now declare some Boost.Interprocess features depending on the implementation
|
||||
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
|
||||
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
|
||||
#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
|
||||
#endif
|
||||
|
||||
// Timeout duration use if BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING is set
|
||||
#ifndef BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS
|
||||
#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
|
||||
#endif
|
||||
|
||||
//Other switches
|
||||
//BOOST_INTERPROCESS_MSG_QUEUE_USES_CIRC_INDEX
|
||||
//message queue uses a circular queue as index instead of an array (better performance)
|
||||
//Boost version < 1.52 uses an array, so undef this if you want to communicate
|
||||
//with processes compiled with those versions.
|
||||
#define BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
|
||||
|
||||
//Inline attributes
|
||||
#if defined(_MSC_VER)
|
||||
#define BOOST_INTERPROCESS_ALWAYS_INLINE __forceinline
|
||||
#elif defined (__GNUC__)
|
||||
#define BOOST_INTERPROCESS_ALWAYS_INLINE __attribute__((__always_inline__))
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_ALWAYS_INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BOOST_INTERPROCESS_NEVER_INLINE __declspec(noinline)
|
||||
#elif defined (__GNUC__)
|
||||
#define BOOST_INTERPROCESS_NEVER_INLINE __attribute__((__noinline__))
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_NOEXCEPT)
|
||||
#if defined(BOOST_MSVC)
|
||||
#define BOOST_INTERPROCESS_NOEXCEPT throw()
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_NOEXCEPT
|
||||
#endif
|
||||
#define BOOST_INTERPROCESS_NOEXCEPT_IF(x)
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_NOEXCEPT noexcept
|
||||
#define BOOST_INTERPROCESS_NOEXCEPT_IF(x) noexcept(x)
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
|
236
cpp/BoostParts/boost/interprocess/errors.hpp
Normal file
236
cpp/BoostParts/boost/interprocess/errors.hpp
Normal file
@ -0,0 +1,236 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
// Parts of this code are taken from boost::filesystem library
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 Beman Dawes
|
||||
// Copyright (C) 2001 Dietmar Kuehl
|
||||
// Use, modification, and distribution is subject to 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 library home page at http://www.boost.org/libs/filesystem
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_ERRORS_HPP
|
||||
#define BOOST_INTERPROCESS_ERRORS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <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 <cstring> //strerror
|
||||
# else //ifdef BOOST_HAS_UNISTD_H
|
||||
# error Unknown platform
|
||||
# endif //ifdef BOOST_HAS_UNISTD_H
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
//!\file
|
||||
//!Describes the error numbering of interprocess classes
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
/// @cond
|
||||
inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
|
||||
{
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
return winapi::get_last_error();
|
||||
#else
|
||||
return errno; // GCC 3.1 won't accept ::errno
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
inline void fill_system_message(int sys_err_code, std::string &str)
|
||||
{
|
||||
void *lpMsgBuf;
|
||||
winapi::format_message(
|
||||
winapi::format_message_allocate_buffer |
|
||||
winapi::format_message_from_system |
|
||||
winapi::format_message_ignore_inserts,
|
||||
0,
|
||||
sys_err_code,
|
||||
winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language
|
||||
reinterpret_cast<char *>(&lpMsgBuf),
|
||||
0,
|
||||
0
|
||||
);
|
||||
str += static_cast<const char*>(lpMsgBuf);
|
||||
winapi::local_free( lpMsgBuf ); // free the buffer
|
||||
while ( str.size()
|
||||
&& (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
|
||||
str.erase( str.size()-1 );
|
||||
}
|
||||
# else
|
||||
inline void fill_system_message( int system_error, std::string &str)
|
||||
{ str = std::strerror(system_error); }
|
||||
# endif
|
||||
/// @endcond
|
||||
|
||||
enum error_code_t
|
||||
{
|
||||
no_error = 0,
|
||||
system_error, // system generated error; if possible, is translated
|
||||
// to one of the more specific errors below.
|
||||
other_error, // library generated error
|
||||
security_error, // includes access rights, permissions failures
|
||||
read_only_error,
|
||||
io_error,
|
||||
path_error,
|
||||
not_found_error,
|
||||
// not_directory_error,
|
||||
busy_error, // implies trying again might succeed
|
||||
already_exists_error,
|
||||
not_empty_error,
|
||||
is_directory_error,
|
||||
out_of_space_error,
|
||||
out_of_memory_error,
|
||||
out_of_resource_error,
|
||||
lock_error,
|
||||
sem_error,
|
||||
mode_error,
|
||||
size_error,
|
||||
corrupted_error,
|
||||
not_such_file_or_directory,
|
||||
invalid_argument,
|
||||
timeout_when_locking_error,
|
||||
timeout_when_waiting_error,
|
||||
};
|
||||
|
||||
typedef int native_error_t;
|
||||
|
||||
/// @cond
|
||||
struct ec_xlate
|
||||
{
|
||||
native_error_t sys_ec;
|
||||
error_code_t ec;
|
||||
};
|
||||
|
||||
static const ec_xlate ec_table[] =
|
||||
{
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
{ /*ERROR_ACCESS_DENIED*/5L, security_error },
|
||||
{ /*ERROR_INVALID_ACCESS*/12L, security_error },
|
||||
{ /*ERROR_SHARING_VIOLATION*/32L, security_error },
|
||||
{ /*ERROR_LOCK_VIOLATION*/33L, security_error },
|
||||
{ /*ERROR_LOCKED*/212L, security_error },
|
||||
{ /*ERROR_NOACCESS*/998L, security_error },
|
||||
{ /*ERROR_WRITE_PROTECT*/19L, read_only_error },
|
||||
{ /*ERROR_NOT_READY*/21L, io_error },
|
||||
{ /*ERROR_SEEK*/25L, io_error },
|
||||
{ /*ERROR_READ_FAULT*/30L, io_error },
|
||||
{ /*ERROR_WRITE_FAULT*/29L, io_error },
|
||||
{ /*ERROR_CANTOPEN*/1011L, io_error },
|
||||
{ /*ERROR_CANTREAD*/1012L, io_error },
|
||||
{ /*ERROR_CANTWRITE*/1013L, io_error },
|
||||
{ /*ERROR_DIRECTORY*/267L, path_error },
|
||||
{ /*ERROR_INVALID_NAME*/123L, path_error },
|
||||
{ /*ERROR_FILE_NOT_FOUND*/2L, not_found_error },
|
||||
{ /*ERROR_PATH_NOT_FOUND*/3L, not_found_error },
|
||||
{ /*ERROR_DEV_NOT_EXIST*/55L, not_found_error },
|
||||
{ /*ERROR_DEVICE_IN_USE*/2404L, busy_error },
|
||||
{ /*ERROR_OPEN_FILES*/2401L, busy_error },
|
||||
{ /*ERROR_BUSY_DRIVE*/142L, busy_error },
|
||||
{ /*ERROR_BUSY*/170L, busy_error },
|
||||
{ /*ERROR_FILE_EXISTS*/80L, already_exists_error },
|
||||
{ /*ERROR_ALREADY_EXISTS*/183L, already_exists_error },
|
||||
{ /*ERROR_DIR_NOT_EMPTY*/145L, not_empty_error },
|
||||
{ /*ERROR_HANDLE_DISK_FULL*/39L, out_of_space_error },
|
||||
{ /*ERROR_DISK_FULL*/112L, out_of_space_error },
|
||||
{ /*ERROR_OUTOFMEMORY*/14L, out_of_memory_error },
|
||||
{ /*ERROR_NOT_ENOUGH_MEMORY*/8L, out_of_memory_error },
|
||||
{ /*ERROR_TOO_MANY_OPEN_FILES*/4L, out_of_resource_error },
|
||||
{ /*ERROR_INVALID_ADDRESS*/487L, busy_error }
|
||||
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
{ EACCES, security_error },
|
||||
{ EROFS, read_only_error },
|
||||
{ EIO, io_error },
|
||||
{ ENAMETOOLONG, path_error },
|
||||
{ ENOENT, not_found_error },
|
||||
// { ENOTDIR, not_directory_error },
|
||||
{ EAGAIN, busy_error },
|
||||
{ EBUSY, busy_error },
|
||||
{ ETXTBSY, busy_error },
|
||||
{ EEXIST, already_exists_error },
|
||||
{ ENOTEMPTY, not_empty_error },
|
||||
{ EISDIR, is_directory_error },
|
||||
{ ENOSPC, out_of_space_error },
|
||||
{ ENOMEM, out_of_memory_error },
|
||||
{ EMFILE, out_of_resource_error },
|
||||
{ ENOENT, not_such_file_or_directory },
|
||||
{ EINVAL, invalid_argument }
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
};
|
||||
|
||||
inline error_code_t lookup_error(native_error_t err)
|
||||
{
|
||||
const ec_xlate *cur = &ec_table[0],
|
||||
*end = cur + sizeof(ec_table)/sizeof(ec_xlate);
|
||||
for (;cur != end; ++cur ){
|
||||
if ( err == cur->sys_ec ) return cur->ec;
|
||||
}
|
||||
return system_error; // general system error code
|
||||
}
|
||||
|
||||
struct error_info
|
||||
{
|
||||
error_info(error_code_t ec = other_error )
|
||||
: m_nat(0), m_ec(ec)
|
||||
{}
|
||||
|
||||
error_info(native_error_t sys_err_code)
|
||||
: m_nat(sys_err_code), m_ec(lookup_error(sys_err_code))
|
||||
{}
|
||||
|
||||
error_info & operator =(error_code_t ec)
|
||||
{
|
||||
m_nat = 0;
|
||||
m_ec = ec;
|
||||
return *this;
|
||||
}
|
||||
|
||||
error_info & operator =(native_error_t sys_err_code)
|
||||
{
|
||||
m_nat = sys_err_code;
|
||||
m_ec = lookup_error(sys_err_code);
|
||||
return *this;
|
||||
}
|
||||
|
||||
native_error_t get_native_error()const
|
||||
{ return m_nat; }
|
||||
|
||||
error_code_t get_error_code()const
|
||||
{ return m_ec; }
|
||||
|
||||
private:
|
||||
native_error_t m_nat;
|
||||
error_code_t m_ec;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} // namespace interprocess {
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_ERRORS_HPP
|
150
cpp/BoostParts/boost/interprocess/exceptions.hpp
Normal file
150
cpp/BoostParts/boost/interprocess/exceptions.hpp
Normal file
@ -0,0 +1,150 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_EXCEPTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_EXCEPTIONS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <stdexcept>
|
||||
#include <new>
|
||||
|
||||
//!\file
|
||||
//!Describes exceptions thrown by interprocess classes
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!This class is the base class of all exceptions
|
||||
//!thrown by boost::interprocess
|
||||
class interprocess_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
interprocess_exception(const char *err/*error_code_t ec = other_error*/)
|
||||
: m_err(other_error)
|
||||
{
|
||||
// try { m_str = "boost::interprocess_exception::library_error"; }
|
||||
try { m_str = err; }
|
||||
catch (...) {}
|
||||
}
|
||||
/*
|
||||
interprocess_exception(native_error_t sys_err_code)
|
||||
: m_err(sys_err_code)
|
||||
{
|
||||
try { fill_system_message(m_err.get_native_error(), m_str); }
|
||||
catch (...) {}
|
||||
}*/
|
||||
|
||||
interprocess_exception(const error_info &err_info, const char *str = 0)
|
||||
: m_err(err_info)
|
||||
{
|
||||
try{
|
||||
if(m_err.get_native_error() != 0){
|
||||
fill_system_message(m_err.get_native_error(), m_str);
|
||||
}
|
||||
else if(str){
|
||||
m_str = str;
|
||||
}
|
||||
else{
|
||||
m_str = "boost::interprocess_exception::library_error";
|
||||
}
|
||||
}
|
||||
catch(...){}
|
||||
}
|
||||
|
||||
virtual ~interprocess_exception() throw(){}
|
||||
|
||||
virtual const char * what() const throw()
|
||||
{ return m_str.c_str(); }
|
||||
|
||||
native_error_t get_native_error()const { 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(); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
error_info m_err;
|
||||
std::string m_str;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!This is the exception thrown by shared interprocess_mutex family when a deadlock situation
|
||||
//!is detected or when using a interprocess_condition the interprocess_mutex is not locked
|
||||
class lock_exception : public interprocess_exception
|
||||
{
|
||||
public:
|
||||
lock_exception()
|
||||
: interprocess_exception(lock_error)
|
||||
{}
|
||||
|
||||
virtual const char* what() const throw()
|
||||
{ return "boost::interprocess::lock_exception"; }
|
||||
};
|
||||
|
||||
//!This is the exception thrown by named interprocess_semaphore when a deadlock situation
|
||||
//!is detected or when an error is detected in the post/wait operation
|
||||
/*
|
||||
class sem_exception : public interprocess_exception
|
||||
{
|
||||
public:
|
||||
sem_exception()
|
||||
: interprocess_exception(lock_error)
|
||||
{}
|
||||
|
||||
virtual const char* what() const throw()
|
||||
{ return "boost::interprocess::sem_exception"; }
|
||||
};
|
||||
*/
|
||||
//!This is the exception thrown by synchronization objects when there is
|
||||
//!an error in a wait() function
|
||||
/*
|
||||
class wait_exception : public interprocess_exception
|
||||
{
|
||||
public:
|
||||
virtual const char* what() const throw()
|
||||
{ return "boost::interprocess::wait_exception"; }
|
||||
};
|
||||
*/
|
||||
|
||||
//!This exception is thrown when a named object is created
|
||||
//!in "open_only" mode and the resource was not already created
|
||||
/*
|
||||
class not_previously_created : public interprocess_exception
|
||||
{
|
||||
public:
|
||||
virtual const char* what() const throw()
|
||||
{ return "boost::interprocess::not_previously_created"; }
|
||||
};
|
||||
*/
|
||||
|
||||
//!This exception is thrown when a memory request can't be
|
||||
//!fulfilled.
|
||||
class bad_alloc : public interprocess_exception
|
||||
{
|
||||
public:
|
||||
bad_alloc() : interprocess_exception("::boost::interprocess::bad_alloc"){}
|
||||
virtual const char* what() const throw()
|
||||
{ return "boost::interprocess::bad_alloc"; }
|
||||
};
|
||||
|
||||
} // namespace interprocess {
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_INTERPROCESS_EXCEPTIONS_HPP
|
150
cpp/BoostParts/boost/interprocess/indexes/iset_index.hpp
Normal file
150
cpp/BoostParts/boost/interprocess/indexes/iset_index.hpp
Normal file
@ -0,0 +1,150 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_ISET_INDEX_HPP
|
||||
#define BOOST_INTERPROCESS_ISET_INDEX_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
|
||||
|
||||
//!\file
|
||||
//!Describes index adaptor of boost::intrusive::set container, to use it
|
||||
//!as name/shared memory index
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
//!Helper class to define typedefs from IndexTraits
|
||||
template <class MapConfig>
|
||||
struct iset_index_aux
|
||||
{
|
||||
typedef typename
|
||||
MapConfig::segment_manager_base segment_manager_base;
|
||||
|
||||
typedef typename
|
||||
segment_manager_base::void_pointer void_pointer;
|
||||
typedef typename bi::make_set_base_hook
|
||||
< bi::void_pointer<void_pointer>
|
||||
, bi::optimize_size<true>
|
||||
>::type derivation_hook;
|
||||
|
||||
typedef typename MapConfig::template
|
||||
intrusive_value_type<derivation_hook>::type value_type;
|
||||
typedef std::less<value_type> value_compare;
|
||||
typedef typename bi::make_set
|
||||
< value_type
|
||||
, bi::base_hook<derivation_hook>
|
||||
>::type index_t;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
//!Index type based in boost::intrusive::set.
|
||||
//!Just derives from boost::intrusive::set
|
||||
//!and defines the interface needed by managed memory segments*/
|
||||
template <class MapConfig>
|
||||
class iset_index
|
||||
//Derive class from map specialization
|
||||
: public iset_index_aux<MapConfig>::index_t
|
||||
{
|
||||
/// @cond
|
||||
typedef iset_index_aux<MapConfig> index_aux;
|
||||
typedef typename index_aux::index_t index_type;
|
||||
typedef typename MapConfig::
|
||||
intrusive_compare_key_type intrusive_compare_key_type;
|
||||
typedef typename MapConfig::char_type char_type;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename index_type::iterator iterator;
|
||||
typedef typename index_type::const_iterator const_iterator;
|
||||
typedef typename index_type::insert_commit_data insert_commit_data;
|
||||
typedef typename index_type::value_type value_type;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
|
||||
struct intrusive_key_value_less
|
||||
{
|
||||
bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
|
||||
{
|
||||
std::size_t blen = b.name_length();
|
||||
return (i.m_len < blen) ||
|
||||
(i.m_len == blen &&
|
||||
std::char_traits<char_type>::compare
|
||||
(i.mp_str, b.name(), i.m_len) < 0);
|
||||
}
|
||||
|
||||
bool operator()(const value_type &b, const intrusive_compare_key_type &i) const
|
||||
{
|
||||
std::size_t blen = b.name_length();
|
||||
return (blen < i.m_len) ||
|
||||
(blen == i.m_len &&
|
||||
std::char_traits<char_type>::compare
|
||||
(b.name(), i.mp_str, i.m_len) < 0);
|
||||
}
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
//!Constructor. Takes a pointer to the
|
||||
//!segment manager. Can throw
|
||||
iset_index(typename MapConfig::segment_manager_base *)
|
||||
: index_type(/*typename index_aux::value_compare()*/)
|
||||
{}
|
||||
|
||||
//!This reserves memory to optimize the insertion of n
|
||||
//!elements in the index
|
||||
void reserve(typename MapConfig::segment_manager_base::size_type)
|
||||
{ /*Does nothing, map has not reserve or rehash*/ }
|
||||
|
||||
//!This frees all unnecessary memory
|
||||
void shrink_to_fit()
|
||||
{ /*Does nothing, this intrusive index does not allocate memory;*/ }
|
||||
|
||||
iterator find(const intrusive_compare_key_type &key)
|
||||
{ return index_type::find(key, intrusive_key_value_less()); }
|
||||
|
||||
const_iterator find(const intrusive_compare_key_type &key) const
|
||||
{ return index_type::find(key, intrusive_key_value_less()); }
|
||||
|
||||
std::pair<iterator, bool>insert_check
|
||||
(const intrusive_compare_key_type &key, insert_commit_data &commit_data)
|
||||
{ return index_type::insert_check(key, intrusive_key_value_less(), commit_data); }
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
//!Trait class to detect if an index is an intrusive
|
||||
//!index.
|
||||
template<class MapConfig>
|
||||
struct is_intrusive_index
|
||||
<boost::interprocess::iset_index<MapConfig> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP
|
418
cpp/BoostParts/boost/interprocess/interprocess_fwd.hpp
Normal file
418
cpp/BoostParts/boost/interprocess/interprocess_fwd.hpp
Normal file
@ -0,0 +1,418 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_FWD_HPP
|
||||
#define BOOST_INTERPROCESS_FWD_HPP
|
||||
|
||||
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Standard predeclarations
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
}}
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace bi = boost::intrusive;
|
||||
}}
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
/// @endcond
|
||||
|
||||
namespace boost { namespace interprocess {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// permissions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class permissions;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// shared_memory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class shared_memory_object;
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
class windows_shared_memory;
|
||||
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// mapped file/mapped region/mapped_file
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class file_mapping;
|
||||
class mapped_region;
|
||||
class mapped_file;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Mutexes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class null_mutex;
|
||||
|
||||
class interprocess_mutex;
|
||||
class interprocess_recursive_mutex;
|
||||
|
||||
class named_mutex;
|
||||
class named_recursive_mutex;
|
||||
|
||||
class interprocess_semaphore;
|
||||
class named_semaphore;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Mutex families
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct mutex_family;
|
||||
struct null_mutex_family;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Other synchronization classes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class barrier;
|
||||
class interprocess_sharable_mutex;
|
||||
class interprocess_condition;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Locks
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class Mutex>
|
||||
class scoped_lock;
|
||||
|
||||
template <class SharableMutex>
|
||||
class sharable_lock;
|
||||
|
||||
template <class UpgradableMutex>
|
||||
class upgradable_lock;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// STL compatible allocators
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T, class SegmentManager>
|
||||
class allocator;
|
||||
|
||||
template<class T, class SegmentManager, std::size_t NodesPerBlock = 64>
|
||||
class node_allocator;
|
||||
|
||||
template<class T, class SegmentManager, std::size_t NodesPerBlock = 64>
|
||||
class private_node_allocator;
|
||||
|
||||
template<class T, class SegmentManager, std::size_t NodesPerBlock = 64>
|
||||
class cached_node_allocator;
|
||||
|
||||
template<class T, class SegmentManager, std::size_t NodesPerBlock = 64, std::size_t MaxFreeBlocks = 2
|
||||
, unsigned char OverheadPercent = 5
|
||||
>
|
||||
class adaptive_pool;
|
||||
|
||||
template<class T, class SegmentManager, std::size_t NodesPerBlock = 64, std::size_t MaxFreeBlocks = 2
|
||||
, unsigned char OverheadPercent = 5
|
||||
>
|
||||
class private_adaptive_pool;
|
||||
|
||||
template<class T, class SegmentManager, std::size_t NodesPerBlock = 64, std::size_t MaxFreeBlocks = 2
|
||||
, unsigned char OverheadPercent = 5
|
||||
>
|
||||
class cached_adaptive_pool;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// offset_ptr
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const std::size_t offset_type_alignment = 0;
|
||||
|
||||
template <class T, class DifferenceType = std::ptrdiff_t, class OffsetType = std::size_t, std::size_t Alignment = offset_type_alignment>
|
||||
class offset_ptr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Memory allocation algorithms
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Single segment memory allocation algorithms
|
||||
template<class MutexFamily, class VoidMutex = offset_ptr<void> >
|
||||
class simple_seq_fit;
|
||||
|
||||
template<class MutexFamily, class VoidMutex = offset_ptr<void>, std::size_t MemAlignment = 0>
|
||||
class rbtree_best_fit;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Index Types
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class IndexConfig> class flat_map_index;
|
||||
template<class IndexConfig> class iset_index;
|
||||
template<class IndexConfig> class iunordered_set_index;
|
||||
template<class IndexConfig> class map_index;
|
||||
template<class IndexConfig> class null_index;
|
||||
template<class IndexConfig> class unordered_map_index;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Segment manager
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class CharType
|
||||
,class MemoryAlgorithm
|
||||
,template<class IndexConfig> class IndexType>
|
||||
class segment_manager;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// External buffer managed memory classes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class CharType
|
||||
,class MemoryAlgorithm
|
||||
,template<class IndexConfig> class IndexType>
|
||||
class basic_managed_external_buffer;
|
||||
|
||||
typedef basic_managed_external_buffer
|
||||
<char
|
||||
,rbtree_best_fit<null_mutex_family>
|
||||
,iset_index>
|
||||
managed_external_buffer;
|
||||
|
||||
typedef basic_managed_external_buffer
|
||||
<wchar_t
|
||||
,rbtree_best_fit<null_mutex_family>
|
||||
,iset_index>
|
||||
wmanaged_external_buffer;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// managed memory classes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class CharType
|
||||
,class MemoryAlgorithm
|
||||
,template<class IndexConfig> class IndexType>
|
||||
class basic_managed_shared_memory;
|
||||
|
||||
typedef basic_managed_shared_memory
|
||||
<char
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
managed_shared_memory;
|
||||
|
||||
typedef basic_managed_shared_memory
|
||||
<wchar_t
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
wmanaged_shared_memory;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Windows shared memory managed memory classes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
template <class CharType
|
||||
,class MemoryAlgorithm
|
||||
,template<class IndexConfig> class IndexType>
|
||||
class basic_managed_windows_shared_memory;
|
||||
|
||||
typedef basic_managed_windows_shared_memory
|
||||
<char
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
managed_windows_shared_memory;
|
||||
|
||||
typedef basic_managed_windows_shared_memory
|
||||
<wchar_t
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
wmanaged_windows_shared_memory;
|
||||
|
||||
#endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
template <class CharType
|
||||
,class MemoryAlgorithm
|
||||
,template<class IndexConfig> class IndexType>
|
||||
class basic_managed_xsi_shared_memory;
|
||||
|
||||
typedef basic_managed_xsi_shared_memory
|
||||
<char
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
managed_xsi_shared_memory;
|
||||
|
||||
typedef basic_managed_xsi_shared_memory
|
||||
<wchar_t
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
wmanaged_xsi_shared_memory;
|
||||
|
||||
#endif //#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Fixed address shared memory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef basic_managed_shared_memory
|
||||
<char
|
||||
,rbtree_best_fit<mutex_family, void*>
|
||||
,iset_index>
|
||||
fixed_managed_shared_memory;
|
||||
|
||||
typedef basic_managed_shared_memory
|
||||
<wchar_t
|
||||
,rbtree_best_fit<mutex_family, void*>
|
||||
,iset_index>
|
||||
wfixed_managed_shared_memory;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Heap memory managed memory classes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<class CharType
|
||||
,class MemoryAlgorithm
|
||||
,template<class IndexConfig> class IndexType>
|
||||
class basic_managed_heap_memory;
|
||||
|
||||
typedef basic_managed_heap_memory
|
||||
<char
|
||||
,rbtree_best_fit<null_mutex_family>
|
||||
,iset_index>
|
||||
managed_heap_memory;
|
||||
|
||||
typedef basic_managed_heap_memory
|
||||
<wchar_t
|
||||
,rbtree_best_fit<null_mutex_family>
|
||||
,iset_index>
|
||||
wmanaged_heap_memory;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Mapped file managed memory classes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<class CharType
|
||||
,class MemoryAlgorithm
|
||||
,template<class IndexConfig> class IndexType>
|
||||
class basic_managed_mapped_file;
|
||||
|
||||
typedef basic_managed_mapped_file
|
||||
<char
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
managed_mapped_file;
|
||||
|
||||
typedef basic_managed_mapped_file
|
||||
<wchar_t
|
||||
,rbtree_best_fit<mutex_family>
|
||||
,iset_index>
|
||||
wmanaged_mapped_file;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Exceptions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class interprocess_exception;
|
||||
class lock_exception;
|
||||
class bad_alloc;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Bufferstream
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//bufferstream
|
||||
template <class CharT
|
||||
,class CharTraits = std::char_traits<CharT> >
|
||||
class basic_bufferbuf;
|
||||
|
||||
template <class CharT
|
||||
,class CharTraits = std::char_traits<CharT> >
|
||||
class basic_ibufferstream;
|
||||
|
||||
template <class CharT
|
||||
,class CharTraits = std::char_traits<CharT> >
|
||||
class basic_obufferstream;
|
||||
|
||||
template <class CharT
|
||||
,class CharTraits = std::char_traits<CharT> >
|
||||
class basic_bufferstream;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Vectorstream
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class CharVector
|
||||
,class CharTraits = std::char_traits<typename CharVector::value_type> >
|
||||
class basic_vectorbuf;
|
||||
|
||||
template <class CharVector
|
||||
,class CharTraits = std::char_traits<typename CharVector::value_type> >
|
||||
class basic_ivectorstream;
|
||||
|
||||
template <class CharVector
|
||||
,class CharTraits = std::char_traits<typename CharVector::value_type> >
|
||||
class basic_ovectorstream;
|
||||
|
||||
template <class CharVector
|
||||
,class CharTraits = std::char_traits<typename CharVector::value_type> >
|
||||
class basic_vectorstream;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Smart pointers
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T, class Deleter>
|
||||
class scoped_ptr;
|
||||
|
||||
template<class T, class VoidPointer>
|
||||
class intrusive_ptr;
|
||||
|
||||
template<class T, class VoidAllocator, class Deleter>
|
||||
class shared_ptr;
|
||||
|
||||
template<class T, class VoidAllocator, class Deleter>
|
||||
class weak_ptr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// IPC
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class VoidPointer>
|
||||
class message_queue_t;
|
||||
|
||||
typedef message_queue_t<offset_ptr<void> > message_queue;
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// CONTAINERS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_FWD_HPP
|
221
cpp/BoostParts/boost/interprocess/managed_shared_memory.hpp
Normal file
221
cpp/BoostParts/boost/interprocess/managed_shared_memory.hpp
Normal file
@ -0,0 +1,221 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_SHARED_MEMORY_HPP
|
||||
#define BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/managed_memory_impl.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/permissions.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>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class AllocationAlgorithm>
|
||||
struct shmem_open_or_create
|
||||
{
|
||||
typedef ipcdetail::managed_open_or_create_impl
|
||||
< shared_memory_object, AllocationAlgorithm::Alignment, true, false> type;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
//!A basic shared memory named object creation class. Initializes the
|
||||
//!shared memory segment. Inherits all basic functionality from
|
||||
//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
|
||||
template
|
||||
<
|
||||
class CharType,
|
||||
class AllocationAlgorithm,
|
||||
template<class IndexConfig> class IndexType
|
||||
>
|
||||
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
|
||||
{
|
||||
/// @cond
|
||||
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;
|
||||
|
||||
typedef ipcdetail::create_open_func<base_t> create_open_func_t;
|
||||
|
||||
basic_managed_shared_memory *get_this_pointer()
|
||||
{ return this; }
|
||||
|
||||
public:
|
||||
typedef shared_memory_object device_type;
|
||||
typedef typename base_t::size_type size_type;
|
||||
|
||||
private:
|
||||
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_shared_memory)
|
||||
/// @endcond
|
||||
|
||||
public: //functions
|
||||
|
||||
//!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
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~basic_managed_shared_memory()
|
||||
{}
|
||||
|
||||
//!Default constructor. Does nothing.
|
||||
//!Useful in combination with move semantics
|
||||
basic_managed_shared_memory()
|
||||
{}
|
||||
|
||||
//!Creates shared memory and creates and places the segment manager.
|
||||
//!This can throw.
|
||||
basic_managed_shared_memory(create_only_t, const char *name,
|
||||
size_type size, const void *addr = 0, const permissions& perm = permissions())
|
||||
: base_t()
|
||||
, base2_t(create_only, name, size, read_write, addr,
|
||||
create_open_func_t(get_this_pointer(), 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.
|
||||
basic_managed_shared_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,
|
||||
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.
|
||||
basic_managed_shared_memory (open_copy_on_write_t, const char* name,
|
||||
const void *addr = 0)
|
||||
: base_t()
|
||||
, base2_t(open_only, name, copy_on_write, addr,
|
||||
create_open_func_t(get_this_pointer(),
|
||||
ipcdetail::DoOpen))
|
||||
{}
|
||||
|
||||
//!Connects to a created shared memory and its segment manager.
|
||||
//!in read-only mode.
|
||||
//!This can throw.
|
||||
basic_managed_shared_memory (open_read_only_t, const char* name,
|
||||
const void *addr = 0)
|
||||
: base_t()
|
||||
, base2_t(open_only, name, read_only, addr,
|
||||
create_open_func_t(get_this_pointer(),
|
||||
ipcdetail::DoOpen))
|
||||
{}
|
||||
|
||||
//!Connects to a created shared memory and its segment manager.
|
||||
//!This can throw.
|
||||
basic_managed_shared_memory (open_only_t, const char* name,
|
||||
const void *addr = 0)
|
||||
: base_t()
|
||||
, base2_t(open_only, name, read_write, 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_shared_memory(BOOST_RV_REF(basic_managed_shared_memory) moved)
|
||||
{
|
||||
basic_managed_shared_memory tmp;
|
||||
this->swap(moved);
|
||||
tmp.swap(moved);
|
||||
}
|
||||
|
||||
//!Moves the ownership of "moved"'s managed memory to *this.
|
||||
//!Does not throw
|
||||
basic_managed_shared_memory &operator=(BOOST_RV_REF(basic_managed_shared_memory) moved)
|
||||
{
|
||||
basic_managed_shared_memory tmp(boost::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps the ownership of the managed shared memories managed by *this and other.
|
||||
//!Never throws.
|
||||
void swap(basic_managed_shared_memory &other)
|
||||
{
|
||||
base_t::swap(other);
|
||||
base2_t::swap(other);
|
||||
}
|
||||
|
||||
//!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
|
||||
static bool grow(const char *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
|
||||
static bool shrink_to_fit(const char *shmname)
|
||||
{
|
||||
return base_t::template shrink_to_fit
|
||||
<basic_managed_shared_memory>(shmname);
|
||||
}
|
||||
/// @cond
|
||||
|
||||
//!Tries to find a previous named allocation address. Returns a memory
|
||||
//!buffer and the object count. If not found returned pointer is 0.
|
||||
//!Never throws.
|
||||
template <class T>
|
||||
std::pair<T*, size_type> find (char_ptr_holder_t name)
|
||||
{
|
||||
if(base2_t::get_mapped_region().get_mode() == read_only){
|
||||
return base_t::template find_no_lock<T>(name);
|
||||
}
|
||||
else{
|
||||
return base_t::template find<T>(name);
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP
|
||||
|
886
cpp/BoostParts/boost/interprocess/mapped_region.hpp
Normal file
886
cpp/BoostParts/boost/interprocess/mapped_region.hpp
Normal file
@ -0,0 +1,886 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_MAPPED_REGION_HPP
|
||||
#define BOOST_INTERPROCESS_MAPPED_REGION_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <string>
|
||||
#include <boost/cstdint.hpp>
|
||||
//Some Unixes use caddr_t instead of void * in madvise
|
||||
// SunOS Tru64 HP-UX AIX
|
||||
#if defined(sun) || defined(__sun) || defined(__osf__) || defined(__osf) || defined(_hpux) || defined(hpux) || defined(_AIX)
|
||||
#define BOOST_INTERPROCESS_MADVISE_USES_CADDR_T
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
//A lot of UNIXes have destructive semantics for MADV_DONTNEED, so
|
||||
//we need to be careful to allow it.
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
|
||||
#define BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS
|
||||
#endif
|
||||
|
||||
#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>
|
||||
# include <sys/mman.h> //mmap
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
# if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
|
||||
# include <sys/shm.h> //System V shared memory...
|
||||
# endif
|
||||
# include <boost/assert.hpp>
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
//!\file
|
||||
//!Describes mapped region class
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
//Solaris declares madvise only in some configurations but defines MADV_XXX, a bit confusing.
|
||||
//Predeclare it here to avoid any compilation error
|
||||
#if (defined(sun) || defined(__sun)) && defined(MADV_NORMAL)
|
||||
extern "C" int madvise(caddr_t, size_t, int);
|
||||
#endif
|
||||
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
namespace ipcdetail{ class raw_mapped_region_creator; }
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!The mapped_region class represents a portion or region created from a
|
||||
//!memory_mappable object.
|
||||
//!
|
||||
//!The OS can map a region bigger than the requested one, as region must
|
||||
//!be multiple of the page size, but mapped_region will always refer to
|
||||
//!the region specified by the user.
|
||||
class mapped_region
|
||||
{
|
||||
/// @cond
|
||||
//Non-copyable
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(mapped_region)
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
//!Creates a mapping region of the mapped memory "mapping", starting in
|
||||
//!offset "offset", and the mapping's size will be "size". The mapping
|
||||
//!can be opened for read only, read-write or copy-on-write.
|
||||
//!
|
||||
//!If an address is specified, both the offset and the address must be
|
||||
//!multiples of the page size.
|
||||
//!
|
||||
//!The OS could allocate more pages than size/page_size(), but get_address()
|
||||
//!will always return the address passed in this function (if not null) and
|
||||
//!get_size() will return the specified size.
|
||||
template<class MemoryMappable>
|
||||
mapped_region(const MemoryMappable& mapping
|
||||
,mode_t mode
|
||||
,offset_t offset = 0
|
||||
,std::size_t size = 0
|
||||
,const void *address = 0);
|
||||
|
||||
//!Default constructor. Address will be 0 (nullptr).
|
||||
//!Size will be 0.
|
||||
//!Does not throw
|
||||
mapped_region();
|
||||
|
||||
//!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)
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
: m_base(0), m_size(0)
|
||||
, m_page_offset(0)
|
||||
, m_mode(read_only)
|
||||
, m_file_or_mapping_hnd(ipcdetail::invalid_file())
|
||||
#else
|
||||
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
|
||||
#endif
|
||||
{ this->swap(other); }
|
||||
|
||||
//!Destroys the mapped region.
|
||||
//!Does not throw
|
||||
~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 tmp(boost::move(other));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps the mapped_region with another
|
||||
//!mapped region
|
||||
void swap(mapped_region &other);
|
||||
|
||||
//!Returns the size of the mapping. Never throws.
|
||||
std::size_t get_size() const;
|
||||
|
||||
//!Returns the base address of the mapping.
|
||||
//!Never throws.
|
||||
void* get_address() const;
|
||||
|
||||
//!Returns the mode of the mapping used to construct the mapped region.
|
||||
//!Never throws.
|
||||
mode_t get_mode() const;
|
||||
|
||||
//!Flushes to the disk a byte range within the mapped memory.
|
||||
//!If 'async' is true, the function will return before flushing operation is completed
|
||||
//!If 'async' is false, function will return once data has been written into the underlying
|
||||
//!device (i.e., in mapped files OS cached information is written to disk).
|
||||
//!Never throws. Returns false if operation could not be performed.
|
||||
bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0, bool async = true);
|
||||
|
||||
//!Shrinks current mapped region. If after shrinking there is no longer need for a previously
|
||||
//!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).
|
||||
//!Returns true on success. Never throws.
|
||||
bool shrink_by(std::size_t bytes, bool from_back = true);
|
||||
|
||||
//!This enum specifies region usage behaviors that an application can specify
|
||||
//!to the mapped region implementation.
|
||||
enum advice_types{
|
||||
//!Specifies that the application has no advice to give on its behavior with respect to
|
||||
//!the region. It is the default characteristic if no advice is given for a range of memory.
|
||||
advice_normal,
|
||||
//!Specifies that the application expects to access the region sequentially from
|
||||
//!lower addresses to higher addresses. The implementation can lower the priority of
|
||||
//!preceding pages within the region once a page have been accessed.
|
||||
advice_sequential,
|
||||
//!Specifies that the application expects to access the region in a random order,
|
||||
//!and prefetching is likely not advantageous.
|
||||
advice_random,
|
||||
//!Specifies that the application expects to access the region in the near future.
|
||||
//!The implementation can prefetch pages of the region.
|
||||
advice_willneed,
|
||||
//!Specifies that the application expects that it will not access the region in the near future.
|
||||
//!The implementation can unload pages within the range to save system resources.
|
||||
advice_dontneed
|
||||
};
|
||||
|
||||
//!Advises the implementation on the expected behavior of the application with respect to the data
|
||||
//!in the region. The implementation may use this information to optimize handling of the region data.
|
||||
//!This function has no effect on the semantics of access to memory in the region, although it may affect
|
||||
//!the performance of access.
|
||||
//!If the advise type is not known to the implementation, the function returns false. True otherwise.
|
||||
bool advise(advice_types advise);
|
||||
|
||||
//!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();
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
//!Closes a previously opened memory mapping. Never throws
|
||||
void priv_close();
|
||||
|
||||
void* priv_map_address() const;
|
||||
std::size_t priv_map_size() const;
|
||||
bool priv_flush_param_check(std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const;
|
||||
bool priv_shrink_param_check(std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes);
|
||||
static void priv_size_from_mapping_size
|
||||
(offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size);
|
||||
static offset_t priv_page_offset_addr_fixup(offset_t page_offset, const void *&addr);
|
||||
|
||||
template<int dummy>
|
||||
struct page_size_holder
|
||||
{
|
||||
static const std::size_t PageSize;
|
||||
static std::size_t get_page_size();
|
||||
};
|
||||
|
||||
void* m_base;
|
||||
std::size_t m_size;
|
||||
std::size_t m_page_offset;
|
||||
mode_t m_mode;
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
file_handle_t m_file_or_mapping_hnd;
|
||||
#else
|
||||
bool m_is_xsi;
|
||||
#endif
|
||||
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
friend class ipcdetail::raw_mapped_region_creator;
|
||||
void dont_close_on_destruction();
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
|
||||
template<int Dummy>
|
||||
static void destroy_syncs_in_range(const void *addr, std::size_t size);
|
||||
#endif
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
///@cond
|
||||
|
||||
inline void swap(mapped_region &x, mapped_region &y)
|
||||
{ x.swap(y); }
|
||||
|
||||
inline mapped_region::~mapped_region()
|
||||
{ this->priv_close(); }
|
||||
|
||||
inline std::size_t mapped_region::get_size() const
|
||||
{ return m_size; }
|
||||
|
||||
inline mode_t mapped_region::get_mode() const
|
||||
{ return m_mode; }
|
||||
|
||||
inline void* mapped_region::get_address() const
|
||||
{ return m_base; }
|
||||
|
||||
inline void* mapped_region::priv_map_address() const
|
||||
{ return static_cast<char*>(m_base) - m_page_offset; }
|
||||
|
||||
inline std::size_t mapped_region::priv_map_size() const
|
||||
{ return m_size + m_page_offset; }
|
||||
|
||||
inline bool mapped_region::priv_flush_param_check
|
||||
(std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const
|
||||
{
|
||||
//Check some errors
|
||||
if(m_base == 0)
|
||||
return false;
|
||||
|
||||
if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Update flush size if the user does not provide it
|
||||
if(numbytes == 0){
|
||||
numbytes = m_size - mapping_offset;
|
||||
}
|
||||
addr = (char*)this->priv_map_address() + mapping_offset;
|
||||
numbytes += m_page_offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool mapped_region::priv_shrink_param_check
|
||||
(std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes)
|
||||
{
|
||||
//Check some errors
|
||||
if(m_base == 0 || bytes > m_size){
|
||||
return false;
|
||||
}
|
||||
else if(bytes == m_size){
|
||||
this->priv_close();
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
const std::size_t page_size = mapped_region::get_page_size();
|
||||
if(from_back){
|
||||
const std::size_t new_pages = (m_size + m_page_offset - bytes - 1)/page_size + 1;
|
||||
shrink_page_start = static_cast<char*>(this->priv_map_address()) + new_pages*page_size;
|
||||
shrink_page_bytes = m_page_offset + m_size - new_pages*page_size;
|
||||
m_size -= bytes;
|
||||
}
|
||||
else{
|
||||
shrink_page_start = this->priv_map_address();
|
||||
m_page_offset += bytes;
|
||||
shrink_page_bytes = (m_page_offset/page_size)*page_size;
|
||||
m_page_offset = m_page_offset % page_size;
|
||||
m_size -= bytes;
|
||||
m_base = static_cast<char *>(m_base) + bytes;
|
||||
assert(shrink_page_bytes%page_size == 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void mapped_region::priv_size_from_mapping_size
|
||||
(offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size)
|
||||
{
|
||||
//Check if mapping size fits in the user address space
|
||||
//as offset_t is the maximum file size and its signed.
|
||||
if(mapping_size < offset ||
|
||||
boost::uintmax_t(mapping_size - (offset - page_offset)) >
|
||||
boost::uintmax_t(std::size_t(-1))){
|
||||
error_info err(size_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
size = static_cast<std::size_t>(mapping_size - (offset - page_offset));
|
||||
}
|
||||
|
||||
inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, const void *&address)
|
||||
{
|
||||
//We can't map any offset so we have to obtain system's
|
||||
//memory granularity
|
||||
const std::size_t page_size = mapped_region::get_page_size();
|
||||
|
||||
//We calculate the difference between demanded and valid offset
|
||||
//(always less than a page in std::size_t, thus, representable by std::size_t)
|
||||
const std::size_t page_offset =
|
||||
static_cast<std::size_t>(offset - (offset / page_size) * page_size);
|
||||
//Update the mapping address
|
||||
if(address){
|
||||
address = static_cast<const char*>(address) - page_offset;
|
||||
}
|
||||
return page_offset;
|
||||
}
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
inline mapped_region::mapped_region()
|
||||
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only)
|
||||
, m_file_or_mapping_hnd(ipcdetail::invalid_file())
|
||||
{}
|
||||
|
||||
template<int dummy>
|
||||
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
|
||||
{
|
||||
winapi::system_info info;
|
||||
get_system_info(&info);
|
||||
return std::size_t(info.dwAllocationGranularity);
|
||||
}
|
||||
|
||||
template<class MemoryMappable>
|
||||
inline mapped_region::mapped_region
|
||||
(const MemoryMappable &mapping
|
||||
,mode_t mode
|
||||
,offset_t offset
|
||||
,std::size_t size
|
||||
,const void *address)
|
||||
: m_base(0), m_size(0), m_page_offset(0), m_mode(mode)
|
||||
, m_file_or_mapping_hnd(ipcdetail::invalid_file())
|
||||
{
|
||||
mapping_handle_t mhandle = mapping.get_mapping_handle();
|
||||
{
|
||||
file_handle_t native_mapping_handle = 0;
|
||||
|
||||
//Set accesses
|
||||
//For "create_file_mapping"
|
||||
unsigned long protection = 0;
|
||||
//For "mapviewoffile"
|
||||
unsigned long map_access = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case read_only:
|
||||
case read_private:
|
||||
protection |= winapi::page_readonly;
|
||||
map_access |= winapi::file_map_read;
|
||||
break;
|
||||
case read_write:
|
||||
protection |= winapi::page_readwrite;
|
||||
map_access |= winapi::file_map_write;
|
||||
break;
|
||||
case copy_on_write:
|
||||
protection |= winapi::page_writecopy;
|
||||
map_access |= winapi::file_map_copy;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//For file mapping (including emulated shared memory through temporary files),
|
||||
//the device is a file handle so we need to obtain file's size and call create_file_mapping
|
||||
//to obtain the mapping handle.
|
||||
//For files we don't need the file mapping after mapping the memory, as the file is there
|
||||
//so we'll program the handle close
|
||||
void * handle_to_close = winapi::invalid_handle_value;
|
||||
if(!mhandle.is_shm){
|
||||
//Create mapping handle
|
||||
native_mapping_handle = winapi::create_file_mapping
|
||||
( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle())
|
||||
, protection, 0, 0, 0);
|
||||
|
||||
//Check if all is correct
|
||||
if(!native_mapping_handle){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
handle_to_close = native_mapping_handle;
|
||||
}
|
||||
else{
|
||||
//For windows_shared_memory the device handle is already a mapping handle
|
||||
//and we need to maintain it
|
||||
native_mapping_handle = mhandle.handle;
|
||||
}
|
||||
//RAII handle close on scope exit
|
||||
const winapi::handle_closer close_handle(handle_to_close);
|
||||
(void)close_handle;
|
||||
|
||||
const offset_t page_offset = priv_page_offset_addr_fixup(offset, address);
|
||||
|
||||
//Obtain mapping size if user provides 0 size
|
||||
if(size == 0){
|
||||
offset_t mapping_size;
|
||||
if(!winapi::get_file_mapping_size(native_mapping_handle, mapping_size)){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//This can throw
|
||||
priv_size_from_mapping_size(mapping_size, offset, page_offset, size);
|
||||
}
|
||||
|
||||
|
||||
//Map with new offsets and size
|
||||
void *base = winapi::map_view_of_file_ex
|
||||
(native_mapping_handle,
|
||||
map_access,
|
||||
offset - page_offset,
|
||||
static_cast<std::size_t>(page_offset + size),
|
||||
const_cast<void*>(address));
|
||||
//Check error
|
||||
if(!base){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Calculate new base for the user
|
||||
m_base = static_cast<char*>(base) + page_offset;
|
||||
m_page_offset = page_offset;
|
||||
m_size = size;
|
||||
}
|
||||
//Windows shared memory needs the duplication of the handle if we want to
|
||||
//make mapped_region independent from the mappable device
|
||||
//
|
||||
//For mapped files, we duplicate the file handle to be able to FlushFileBuffers
|
||||
if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_or_mapping_hnd)){
|
||||
error_info err = winapi::get_last_error();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async)
|
||||
{
|
||||
void *addr;
|
||||
if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){
|
||||
return false;
|
||||
}
|
||||
//Flush it all
|
||||
if(!winapi::flush_view_of_file(addr, numbytes)){
|
||||
return false;
|
||||
}
|
||||
//m_file_or_mapping_hnd can be a file handle or a mapping handle.
|
||||
//so flushing file buffers has only sense for files...
|
||||
else if(async && m_file_or_mapping_hnd != winapi::invalid_handle_value &&
|
||||
winapi::get_file_type(m_file_or_mapping_hnd) == winapi::file_type_disk){
|
||||
return winapi::flush_file_buffers(m_file_or_mapping_hnd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back)
|
||||
{
|
||||
void *shrink_page_start;
|
||||
std::size_t shrink_page_bytes;
|
||||
if(!this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){
|
||||
return false;
|
||||
}
|
||||
else if(shrink_page_bytes){
|
||||
//In Windows, we can't decommit the storage or release the virtual address space,
|
||||
//the best we can do is try to remove some memory from the process working set.
|
||||
//With a bit of luck we can free some physical memory.
|
||||
unsigned long old_protect_ignored;
|
||||
bool b_ret = winapi::virtual_unlock(shrink_page_start, shrink_page_bytes)
|
||||
|| (winapi::get_last_error() == winapi::error_not_locked);
|
||||
(void)old_protect_ignored;
|
||||
//Change page protection to forbid any further access
|
||||
b_ret = b_ret && winapi::virtual_protect
|
||||
(shrink_page_start, shrink_page_bytes, winapi::page_noaccess, old_protect_ignored);
|
||||
return b_ret;
|
||||
}
|
||||
else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool mapped_region::advise(advice_types)
|
||||
{
|
||||
//Windows has no madvise/posix_madvise equivalent
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void mapped_region::priv_close()
|
||||
{
|
||||
if(m_base){
|
||||
void *addr = this->priv_map_address();
|
||||
#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
|
||||
mapped_region::destroy_syncs_in_range<0>(addr, m_size);
|
||||
#endif
|
||||
winapi::unmap_view_of_file(addr);
|
||||
m_base = 0;
|
||||
}
|
||||
if(m_file_or_mapping_hnd != ipcdetail::invalid_file()){
|
||||
winapi::close_handle(m_file_or_mapping_hnd);
|
||||
m_file_or_mapping_hnd = ipcdetail::invalid_file();
|
||||
}
|
||||
}
|
||||
|
||||
inline void mapped_region::dont_close_on_destruction()
|
||||
{}
|
||||
|
||||
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
inline mapped_region::mapped_region()
|
||||
: m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
|
||||
{}
|
||||
|
||||
template<int dummy>
|
||||
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
|
||||
{ return std::size_t(sysconf(_SC_PAGESIZE)); }
|
||||
|
||||
template<class MemoryMappable>
|
||||
inline mapped_region::mapped_region
|
||||
( const MemoryMappable &mapping
|
||||
, mode_t mode
|
||||
, offset_t offset
|
||||
, std::size_t size
|
||||
, const void *address)
|
||||
: m_base(0), m_size(0), m_page_offset(0), m_mode(mode), m_is_xsi(false)
|
||||
{
|
||||
mapping_handle_t map_hnd = mapping.get_mapping_handle();
|
||||
|
||||
//Some systems dont' support XSI shared memory
|
||||
#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
if(map_hnd.is_xsi){
|
||||
//Get the size
|
||||
::shmid_ds xsi_ds;
|
||||
int ret = ::shmctl(map_hnd.handle, IPC_STAT, &xsi_ds);
|
||||
if(ret == -1){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//Compare sizess
|
||||
if(size == 0){
|
||||
size = (std::size_t)xsi_ds.shm_segsz;
|
||||
}
|
||||
else if(size != (std::size_t)xsi_ds.shm_segsz){
|
||||
error_info err(size_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//Calculate flag
|
||||
int flag = 0;
|
||||
if(m_mode == read_only){
|
||||
flag |= SHM_RDONLY;
|
||||
}
|
||||
else if(m_mode != read_write){
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//Attach memory
|
||||
void *base = ::shmat(map_hnd.handle, (void*)address, flag);
|
||||
if(base == (void*)-1){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//Update members
|
||||
m_base = base;
|
||||
m_size = size;
|
||||
m_mode = mode;
|
||||
m_page_offset = 0;
|
||||
m_is_xsi = true;
|
||||
return;
|
||||
}
|
||||
#endif //ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
|
||||
//We calculate the difference between demanded and valid offset
|
||||
const offset_t page_offset = priv_page_offset_addr_fixup(offset, address);
|
||||
|
||||
if(size == 0){
|
||||
struct ::stat buf;
|
||||
if(0 != fstat(map_hnd.handle, &buf)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//This can throw
|
||||
priv_size_from_mapping_size(buf.st_size, offset, page_offset, size);
|
||||
}
|
||||
|
||||
//Create new mapping
|
||||
int prot = 0;
|
||||
int flags =
|
||||
#ifdef MAP_NOSYNC
|
||||
//Avoid excessive syncing in BSD systems
|
||||
MAP_NOSYNC;
|
||||
#else
|
||||
0;
|
||||
#endif
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case read_only:
|
||||
prot |= PROT_READ;
|
||||
flags |= MAP_SHARED;
|
||||
break;
|
||||
|
||||
case read_private:
|
||||
prot |= (PROT_READ);
|
||||
flags |= MAP_PRIVATE;
|
||||
break;
|
||||
|
||||
case read_write:
|
||||
prot |= (PROT_WRITE | PROT_READ);
|
||||
flags |= MAP_SHARED;
|
||||
break;
|
||||
|
||||
case copy_on_write:
|
||||
prot |= (PROT_WRITE | PROT_READ);
|
||||
flags |= MAP_PRIVATE;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//Map it to the address space
|
||||
void* base = mmap ( const_cast<void*>(address)
|
||||
, static_cast<std::size_t>(page_offset + size)
|
||||
, prot
|
||||
, flags
|
||||
, mapping.get_mapping_handle().handle
|
||||
, offset - page_offset);
|
||||
|
||||
//Check if mapping was successful
|
||||
if(base == MAP_FAILED){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Calculate new base for the user
|
||||
m_base = static_cast<char*>(base) + page_offset;
|
||||
m_page_offset = page_offset;
|
||||
m_size = size;
|
||||
|
||||
//Check for fixed mapping error
|
||||
if(address && (base != address)){
|
||||
error_info err(busy_error);
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back)
|
||||
{
|
||||
void *shrink_page_start = 0;
|
||||
std::size_t shrink_page_bytes = 0;
|
||||
if(m_is_xsi || !this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){
|
||||
return false;
|
||||
}
|
||||
else if(shrink_page_bytes){
|
||||
//In UNIX we can decommit and free virtual address space.
|
||||
return 0 == munmap(shrink_page_start, shrink_page_bytes);
|
||||
}
|
||||
else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async)
|
||||
{
|
||||
void *addr;
|
||||
if(m_is_xsi || !this->priv_flush_param_check(mapping_offset, addr, numbytes)){
|
||||
return false;
|
||||
}
|
||||
//Flush it all
|
||||
return msync(addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0;
|
||||
}
|
||||
|
||||
inline bool mapped_region::advise(advice_types advice)
|
||||
{
|
||||
int unix_advice = 0;
|
||||
//Modes; 0: none, 2: posix, 1: madvise
|
||||
const unsigned int mode_none = 0;
|
||||
const unsigned int mode_padv = 1;
|
||||
const unsigned int mode_madv = 2;
|
||||
unsigned int mode = mode_none;
|
||||
//Choose advice either from POSIX (preferred) or native Unix
|
||||
switch(advice){
|
||||
case advice_normal:
|
||||
#if defined(POSIX_MADV_NORMAL)
|
||||
unix_advice = POSIX_MADV_NORMAL;
|
||||
mode = mode_padv;
|
||||
#elif defined(MADV_NORMAL)
|
||||
unix_advice = MADV_NORMAL;
|
||||
mode = mode_madv;
|
||||
#endif
|
||||
break;
|
||||
case advice_sequential:
|
||||
#if defined(POSIX_MADV_SEQUENTIAL)
|
||||
unix_advice = POSIX_MADV_SEQUENTIAL;
|
||||
mode = mode_padv;
|
||||
#elif defined(MADV_SEQUENTIAL)
|
||||
unix_advice = MADV_SEQUENTIAL;
|
||||
mode = mode_madv;
|
||||
#endif
|
||||
break;
|
||||
case advice_random:
|
||||
#if defined(POSIX_MADV_RANDOM)
|
||||
unix_advice = POSIX_MADV_RANDOM;
|
||||
mode = mode_padv;
|
||||
#elif defined(MADV_RANDOM)
|
||||
unix_advice = MADV_RANDOM;
|
||||
mode = mode_madv;
|
||||
#endif
|
||||
break;
|
||||
case advice_willneed:
|
||||
#if defined(POSIX_MADV_WILLNEED)
|
||||
unix_advice = POSIX_MADV_WILLNEED;
|
||||
mode = mode_padv;
|
||||
#elif defined(MADV_WILLNEED)
|
||||
unix_advice = MADV_WILLNEED;
|
||||
mode = mode_madv;
|
||||
#endif
|
||||
break;
|
||||
case advice_dontneed:
|
||||
#if defined(POSIX_MADV_DONTNEED)
|
||||
unix_advice = POSIX_MADV_DONTNEED;
|
||||
mode = mode_padv;
|
||||
#elif defined(MADV_DONTNEED) && defined(BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS)
|
||||
unix_advice = MADV_DONTNEED;
|
||||
mode = mode_madv;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch(mode){
|
||||
#if defined(POSIX_MADV_NORMAL)
|
||||
case mode_padv:
|
||||
return 0 == posix_madvise(this->priv_map_address(), this->priv_map_size(), unix_advice);
|
||||
#endif
|
||||
#if defined(MADV_NORMAL)
|
||||
case mode_madv:
|
||||
return 0 == madvise(
|
||||
#if defined(BOOST_INTERPROCESS_MADVISE_USES_CADDR_T)
|
||||
(caddr_t)
|
||||
#endif
|
||||
this->priv_map_address(), this->priv_map_size(), unix_advice);
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline void mapped_region::priv_close()
|
||||
{
|
||||
if(m_base != 0){
|
||||
#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
if(m_is_xsi){
|
||||
int ret = ::shmdt(m_base);
|
||||
BOOST_ASSERT(ret == 0);
|
||||
(void)ret;
|
||||
return;
|
||||
}
|
||||
#endif //#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
munmap(this->priv_map_address(), this->priv_map_size());
|
||||
m_base = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void mapped_region::dont_close_on_destruction()
|
||||
{ m_base = 0; }
|
||||
|
||||
#endif //##if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
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()
|
||||
{
|
||||
if(!page_size_holder<0>::PageSize)
|
||||
return page_size_holder<0>::get_page_size();
|
||||
else
|
||||
return page_size_holder<0>::PageSize;
|
||||
}
|
||||
|
||||
inline void mapped_region::swap(mapped_region &other)
|
||||
{
|
||||
ipcdetail::do_swap(this->m_base, other.m_base);
|
||||
ipcdetail::do_swap(this->m_size, other.m_size);
|
||||
ipcdetail::do_swap(this->m_page_offset, other.m_page_offset);
|
||||
ipcdetail::do_swap(this->m_mode, other.m_mode);
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
ipcdetail::do_swap(this->m_file_or_mapping_hnd, other.m_file_or_mapping_hnd);
|
||||
#else
|
||||
ipcdetail::do_swap(this->m_is_xsi, other.m_is_xsi);
|
||||
#endif
|
||||
}
|
||||
|
||||
//!No-op functor
|
||||
struct null_mapped_region_function
|
||||
{
|
||||
bool operator()(void *, std::size_t , bool) const
|
||||
{ return true; }
|
||||
|
||||
std::size_t get_min_size() const
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MAPPED_REGION_HPP
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
|
||||
#define BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
|
||||
# include <boost/interprocess/sync/windows/sync_utils.hpp>
|
||||
# include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
template<int Dummy>
|
||||
inline void mapped_region::destroy_syncs_in_range(const void *addr, std::size_t size)
|
||||
{
|
||||
ipcdetail::sync_handles &handles =
|
||||
ipcdetail::windows_intermodule_singleton<ipcdetail::sync_handles>::get();
|
||||
handles.destroy_syncs_in_range(addr, size);
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
|
||||
|
||||
#endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
@ -0,0 +1,591 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_MEM_ALGO_COMMON_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/containers/allocation_type.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/math_functions.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/interprocess/detail/min_max.hpp>
|
||||
#include <boost/container/detail/multiallocation_chain.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
//!\file
|
||||
//!Implements common operations for memory algorithms.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class VoidPointer>
|
||||
class basic_multiallocation_chain
|
||||
: public boost::container::container_detail::
|
||||
basic_multiallocation_chain<VoidPointer>
|
||||
{
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
|
||||
typedef boost::container::container_detail::
|
||||
basic_multiallocation_chain<VoidPointer> base_t;
|
||||
public:
|
||||
|
||||
basic_multiallocation_chain()
|
||||
: base_t()
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
|
||||
: base_t(::boost::move(static_cast<base_t&>(other)))
|
||||
{}
|
||||
|
||||
basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
|
||||
{
|
||||
this->base_t::operator=(::boost::move(static_cast<base_t&>(other)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void *pop_front()
|
||||
{
|
||||
return boost::interprocess::ipcdetail::to_raw_pointer(this->base_t::pop_front());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//!This class implements several allocation functions shared by different algorithms
|
||||
//!(aligned allocation, multiple allocation...).
|
||||
template<class MemoryAlgorithm>
|
||||
class memory_algorithm_common
|
||||
{
|
||||
public:
|
||||
typedef typename MemoryAlgorithm::void_pointer void_pointer;
|
||||
typedef typename MemoryAlgorithm::block_ctrl block_ctrl;
|
||||
typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
|
||||
typedef memory_algorithm_common<MemoryAlgorithm> this_type;
|
||||
typedef typename MemoryAlgorithm::size_type size_type;
|
||||
|
||||
static const size_type Alignment = MemoryAlgorithm::Alignment;
|
||||
static const size_type MinBlockUnits = MemoryAlgorithm::MinBlockUnits;
|
||||
static const size_type AllocatedCtrlBytes = MemoryAlgorithm::AllocatedCtrlBytes;
|
||||
static const size_type AllocatedCtrlUnits = MemoryAlgorithm::AllocatedCtrlUnits;
|
||||
static const size_type BlockCtrlBytes = MemoryAlgorithm::BlockCtrlBytes;
|
||||
static const size_type BlockCtrlUnits = MemoryAlgorithm::BlockCtrlUnits;
|
||||
static const size_type UsableByPreviousChunk = MemoryAlgorithm::UsableByPreviousChunk;
|
||||
|
||||
static void assert_alignment(const void *ptr)
|
||||
{ assert_alignment((std::size_t)ptr); }
|
||||
|
||||
static void assert_alignment(size_type uint_ptr)
|
||||
{
|
||||
(void)uint_ptr;
|
||||
BOOST_ASSERT(uint_ptr % Alignment == 0);
|
||||
}
|
||||
|
||||
static bool check_alignment(const void *ptr)
|
||||
{ return (((std::size_t)ptr) % Alignment == 0); }
|
||||
|
||||
static size_type ceil_units(size_type size)
|
||||
{ return get_rounded_size(size, Alignment)/Alignment; }
|
||||
|
||||
static size_type floor_units(size_type size)
|
||||
{ return size/Alignment; }
|
||||
|
||||
static size_type multiple_of_units(size_type size)
|
||||
{ return get_rounded_size(size, Alignment); }
|
||||
|
||||
static void allocate_many
|
||||
(MemoryAlgorithm *memory_algo, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
|
||||
{
|
||||
return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0, chain);
|
||||
}
|
||||
|
||||
static void deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain)
|
||||
{
|
||||
return this_type::priv_deallocate_many(memory_algo, chain);
|
||||
}
|
||||
|
||||
static bool calculate_lcm_and_needs_backwards_lcmed
|
||||
(size_type backwards_multiple, size_type received_size, size_type size_to_achieve,
|
||||
size_type &lcm_out, size_type &needs_backwards_lcmed_out)
|
||||
{
|
||||
// Now calculate lcm_val
|
||||
size_type max = backwards_multiple;
|
||||
size_type min = Alignment;
|
||||
size_type needs_backwards;
|
||||
size_type needs_backwards_lcmed;
|
||||
size_type lcm_val;
|
||||
size_type current_forward;
|
||||
//Swap if necessary
|
||||
if(max < min){
|
||||
size_type tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
//Check if it's power of two
|
||||
if((backwards_multiple & (backwards_multiple-1)) == 0){
|
||||
if(0 != (size_to_achieve & ((backwards_multiple-1)))){
|
||||
return false;
|
||||
}
|
||||
|
||||
lcm_val = max;
|
||||
//If we want to use minbytes data to get a buffer between maxbytes
|
||||
//and minbytes if maxbytes can't be achieved, calculate the
|
||||
//biggest of all possibilities
|
||||
current_forward = get_truncated_size_po2(received_size, backwards_multiple);
|
||||
needs_backwards = size_to_achieve - current_forward;
|
||||
BOOST_ASSERT((needs_backwards % backwards_multiple) == 0);
|
||||
needs_backwards_lcmed = get_rounded_size_po2(needs_backwards, lcm_val);
|
||||
lcm_out = lcm_val;
|
||||
needs_backwards_lcmed_out = needs_backwards_lcmed;
|
||||
return true;
|
||||
}
|
||||
//Check if it's multiple of alignment
|
||||
else if((backwards_multiple & (Alignment - 1u)) == 0){
|
||||
lcm_val = backwards_multiple;
|
||||
current_forward = get_truncated_size(received_size, backwards_multiple);
|
||||
//No need to round needs_backwards because backwards_multiple == lcm_val
|
||||
needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward;
|
||||
BOOST_ASSERT((needs_backwards_lcmed & (Alignment - 1u)) == 0);
|
||||
lcm_out = lcm_val;
|
||||
needs_backwards_lcmed_out = needs_backwards_lcmed;
|
||||
return true;
|
||||
}
|
||||
//Check if it's multiple of the half of the alignmment
|
||||
else if((backwards_multiple & ((Alignment/2u) - 1u)) == 0){
|
||||
lcm_val = backwards_multiple*2u;
|
||||
current_forward = get_truncated_size(received_size, backwards_multiple);
|
||||
needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward;
|
||||
if(0 != (needs_backwards_lcmed & (Alignment-1)))
|
||||
//while(0 != (needs_backwards_lcmed & (Alignment-1)))
|
||||
needs_backwards_lcmed += backwards_multiple;
|
||||
BOOST_ASSERT((needs_backwards_lcmed % lcm_val) == 0);
|
||||
lcm_out = lcm_val;
|
||||
needs_backwards_lcmed_out = needs_backwards_lcmed;
|
||||
return true;
|
||||
}
|
||||
//Check if it's multiple of the quarter of the alignmment
|
||||
else if((backwards_multiple & ((Alignment/4u) - 1u)) == 0){
|
||||
size_type remainder;
|
||||
lcm_val = backwards_multiple*4u;
|
||||
current_forward = get_truncated_size(received_size, backwards_multiple);
|
||||
needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward;
|
||||
//while(0 != (needs_backwards_lcmed & (Alignment-1)))
|
||||
//needs_backwards_lcmed += backwards_multiple;
|
||||
if(0 != (remainder = ((needs_backwards_lcmed & (Alignment-1))>>(Alignment/8u)))){
|
||||
if(backwards_multiple & Alignment/2u){
|
||||
needs_backwards_lcmed += (remainder)*backwards_multiple;
|
||||
}
|
||||
else{
|
||||
needs_backwards_lcmed += (4-remainder)*backwards_multiple;
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT((needs_backwards_lcmed % lcm_val) == 0);
|
||||
lcm_out = lcm_val;
|
||||
needs_backwards_lcmed_out = needs_backwards_lcmed;
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
lcm_val = lcm(max, min);
|
||||
}
|
||||
//If we want to use minbytes data to get a buffer between maxbytes
|
||||
//and minbytes if maxbytes can't be achieved, calculate the
|
||||
//biggest of all possibilities
|
||||
current_forward = get_truncated_size(received_size, backwards_multiple);
|
||||
needs_backwards = size_to_achieve - current_forward;
|
||||
BOOST_ASSERT((needs_backwards % backwards_multiple) == 0);
|
||||
needs_backwards_lcmed = get_rounded_size(needs_backwards, lcm_val);
|
||||
lcm_out = lcm_val;
|
||||
needs_backwards_lcmed_out = needs_backwards_lcmed;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void allocate_many
|
||||
( MemoryAlgorithm *memory_algo
|
||||
, const size_type *elem_sizes
|
||||
, size_type n_elements
|
||||
, size_type sizeof_element
|
||||
, multiallocation_chain &chain)
|
||||
{
|
||||
this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element, chain);
|
||||
}
|
||||
|
||||
static void* allocate_aligned
|
||||
(MemoryAlgorithm *memory_algo, size_type nbytes, size_type alignment)
|
||||
{
|
||||
|
||||
//Ensure power of 2
|
||||
if ((alignment & (alignment - size_type(1u))) != 0){
|
||||
//Alignment is not power of two
|
||||
BOOST_ASSERT((alignment & (alignment - size_type(1u))) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_type real_size;
|
||||
if(alignment <= Alignment){
|
||||
return memory_algo->priv_allocate
|
||||
(boost::interprocess::allocate_new, nbytes, nbytes, real_size).first;
|
||||
}
|
||||
|
||||
if(nbytes > UsableByPreviousChunk)
|
||||
nbytes -= UsableByPreviousChunk;
|
||||
|
||||
//We can find a aligned portion if we allocate a block that has alignment
|
||||
//nbytes + alignment bytes or more.
|
||||
size_type minimum_allocation = max_value
|
||||
(nbytes + alignment, size_type(MinBlockUnits*Alignment));
|
||||
//Since we will split that block, we must request a bit more memory
|
||||
//if the alignment is near the beginning of the buffer, because otherwise,
|
||||
//there is no space for a new block before the alignment.
|
||||
//
|
||||
// ____ Aligned here
|
||||
// |
|
||||
// -----------------------------------------------------
|
||||
// | MBU |
|
||||
// -----------------------------------------------------
|
||||
size_type request =
|
||||
minimum_allocation + (2*MinBlockUnits*Alignment - AllocatedCtrlBytes
|
||||
//prevsize - UsableByPreviousChunk
|
||||
);
|
||||
|
||||
//Now allocate the buffer
|
||||
void *buffer = memory_algo->priv_allocate
|
||||
(boost::interprocess::allocate_new, request, request, real_size).first;
|
||||
if(!buffer){
|
||||
return 0;
|
||||
}
|
||||
else if ((((std::size_t)(buffer)) % alignment) == 0){
|
||||
//If we are lucky and the buffer is aligned, just split it and
|
||||
//return the high part
|
||||
block_ctrl *first = memory_algo->priv_get_block(buffer);
|
||||
size_type old_size = first->m_size;
|
||||
const size_type first_min_units =
|
||||
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 *>
|
||||
(reinterpret_cast<char*>(first) + Alignment*first_min_units);
|
||||
first->m_size = first_min_units;
|
||||
second->m_size = old_size - first->m_size;
|
||||
BOOST_ASSERT(second->m_size >= MinBlockUnits);
|
||||
memory_algo->priv_mark_new_allocated_block(first);
|
||||
//memory_algo->priv_tail_size(first, first->m_size);
|
||||
memory_algo->priv_mark_new_allocated_block(second);
|
||||
memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(second));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//Buffer not aligned, find the aligned part.
|
||||
//
|
||||
// ____ Aligned here
|
||||
// |
|
||||
// -----------------------------------------------------
|
||||
// | MBU +more | ACB |
|
||||
// -----------------------------------------------------
|
||||
char *pos = reinterpret_cast<char*>
|
||||
(reinterpret_cast<std::size_t>(static_cast<char*>(buffer) +
|
||||
//This is the minimum size of (2)
|
||||
(MinBlockUnits*Alignment - AllocatedCtrlBytes) +
|
||||
//This is the next MBU for the aligned memory
|
||||
AllocatedCtrlBytes +
|
||||
//This is the alignment trick
|
||||
alignment - 1) & -alignment);
|
||||
|
||||
//Now obtain the address of the blocks
|
||||
block_ctrl *first = memory_algo->priv_get_block(buffer);
|
||||
block_ctrl *second = memory_algo->priv_get_block(pos);
|
||||
BOOST_ASSERT(pos <= (reinterpret_cast<char*>(first) + first->m_size*Alignment));
|
||||
BOOST_ASSERT(first->m_size >= 2*MinBlockUnits);
|
||||
BOOST_ASSERT((pos + MinBlockUnits*Alignment - AllocatedCtrlBytes + nbytes*Alignment/Alignment) <=
|
||||
(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;
|
||||
memory_algo->priv_mark_new_allocated_block(first);
|
||||
|
||||
//Now check if we can create a new buffer in the end
|
||||
//
|
||||
// __"second" block
|
||||
// | __Aligned here
|
||||
// | | __"third" block
|
||||
// -----------|-----|-----|------------------------------
|
||||
// | MBU +more | ACB | (3) | BCU |
|
||||
// -----------------------------------------------------
|
||||
//This size will be the minimum size to be able to create a
|
||||
//new block in the end.
|
||||
const size_type second_min_units = max_value(size_type(MinBlockUnits),
|
||||
ceil_units(nbytes) + AllocatedCtrlUnits );
|
||||
|
||||
//Check if we can create a new block (of size MinBlockUnits) in the end of the segment
|
||||
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;
|
||||
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;
|
||||
BOOST_ASSERT(second->m_size >= MinBlockUnits);
|
||||
memory_algo->priv_mark_new_allocated_block(second);
|
||||
}
|
||||
|
||||
memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(first));
|
||||
return memory_algo->priv_get_user_buffer(second);
|
||||
}
|
||||
|
||||
static bool try_shrink
|
||||
(MemoryAlgorithm *memory_algo, void *ptr
|
||||
,const size_type max_size, const size_type preferred_size
|
||||
,size_type &received_size)
|
||||
{
|
||||
(void)memory_algo;
|
||||
//Obtain the real block
|
||||
block_ctrl *block = memory_algo->priv_get_block(ptr);
|
||||
size_type old_block_units = (size_type)block->m_size;
|
||||
|
||||
//The block must be marked as allocated
|
||||
BOOST_ASSERT(memory_algo->priv_is_allocated_block(block));
|
||||
|
||||
//Check if alignment and block size are right
|
||||
assert_alignment(ptr);
|
||||
|
||||
//Put this to a safe value
|
||||
received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk;
|
||||
|
||||
//Now translate it to Alignment units
|
||||
const size_type max_user_units = floor_units(max_size - UsableByPreviousChunk);
|
||||
const size_type preferred_user_units = ceil_units(preferred_size - UsableByPreviousChunk);
|
||||
|
||||
//Check if rounded max and preferred are possible correct
|
||||
if(max_user_units < preferred_user_units)
|
||||
return false;
|
||||
|
||||
//Check if the block is smaller than the requested minimum
|
||||
size_type old_user_units = old_block_units - AllocatedCtrlUnits;
|
||||
|
||||
if(old_user_units < preferred_user_units)
|
||||
return false;
|
||||
|
||||
//If the block is smaller than the requested minimum
|
||||
if(old_user_units == preferred_user_units)
|
||||
return true;
|
||||
|
||||
size_type shrunk_user_units =
|
||||
((BlockCtrlUnits - AllocatedCtrlUnits) >= preferred_user_units)
|
||||
? (BlockCtrlUnits - AllocatedCtrlUnits)
|
||||
: preferred_user_units;
|
||||
|
||||
//Some parameter checks
|
||||
if(max_user_units < shrunk_user_units)
|
||||
return false;
|
||||
|
||||
//We must be able to create at least a new empty block
|
||||
if((old_user_units - shrunk_user_units) < BlockCtrlUnits ){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Update new size
|
||||
received_size = shrunk_user_units*Alignment + UsableByPreviousChunk;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool shrink
|
||||
(MemoryAlgorithm *memory_algo, void *ptr
|
||||
,const size_type max_size, const size_type preferred_size
|
||||
,size_type &received_size)
|
||||
{
|
||||
//Obtain the real block
|
||||
block_ctrl *block = memory_algo->priv_get_block(ptr);
|
||||
size_type old_block_units = (size_type)block->m_size;
|
||||
|
||||
if(!try_shrink
|
||||
(memory_algo, ptr, max_size, preferred_size, received_size)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check if the old size was just the shrunk size (no splitting)
|
||||
if((old_block_units - AllocatedCtrlUnits) == ceil_units(preferred_size - UsableByPreviousChunk))
|
||||
return true;
|
||||
|
||||
//Now we can just rewrite the size of the old buffer
|
||||
block->m_size = (received_size-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits;
|
||||
BOOST_ASSERT(block->m_size >= BlockCtrlUnits);
|
||||
|
||||
//We create the new block
|
||||
block_ctrl *new_block = reinterpret_cast<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;
|
||||
BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits);
|
||||
memory_algo->priv_mark_new_allocated_block(block);
|
||||
memory_algo->priv_mark_new_allocated_block(new_block);
|
||||
memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(new_block));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static void priv_allocate_many
|
||||
( MemoryAlgorithm *memory_algo
|
||||
, const size_type *elem_sizes
|
||||
, size_type n_elements
|
||||
, size_type sizeof_element
|
||||
, multiallocation_chain &chain)
|
||||
{
|
||||
//Note: sizeof_element == 0 indicates that we want to
|
||||
//allocate n_elements of the same size "*elem_sizes"
|
||||
|
||||
//Calculate the total size of all requests
|
||||
size_type total_request_units = 0;
|
||||
size_type elem_units = 0;
|
||||
const size_type ptr_size_units = memory_algo->priv_get_total_units(sizeof(void_pointer));
|
||||
if(!sizeof_element){
|
||||
elem_units = memory_algo->priv_get_total_units(*elem_sizes);
|
||||
elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units;
|
||||
total_request_units = n_elements*elem_units;
|
||||
}
|
||||
else{
|
||||
for(size_type i = 0; i < n_elements; ++i){
|
||||
if(multiplication_overflows(elem_sizes[i], sizeof_element)){
|
||||
total_request_units = 0;
|
||||
break;
|
||||
}
|
||||
elem_units = memory_algo->priv_get_total_units(elem_sizes[i]*sizeof_element);
|
||||
elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units;
|
||||
if(sum_overflows(total_request_units, elem_units)){
|
||||
total_request_units = 0;
|
||||
break;
|
||||
}
|
||||
total_request_units += elem_units;
|
||||
}
|
||||
}
|
||||
|
||||
if(total_request_units && !multiplication_overflows(total_request_units, Alignment)){
|
||||
size_type low_idx = 0;
|
||||
while(low_idx < n_elements){
|
||||
size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
|
||||
size_type min_allocation = (!sizeof_element)
|
||||
? elem_units
|
||||
: memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element);
|
||||
min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
|
||||
|
||||
size_type received_size;
|
||||
std::pair<void *, bool> ret = memory_algo->priv_allocate
|
||||
(boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0);
|
||||
if(!ret.first){
|
||||
break;
|
||||
}
|
||||
|
||||
block_ctrl *block = memory_algo->priv_get_block(ret.first);
|
||||
size_type received_units = (size_type)block->m_size;
|
||||
char *block_address = reinterpret_cast<char*>(block);
|
||||
|
||||
size_type total_used_units = 0;
|
||||
while(total_used_units < received_units){
|
||||
if(sizeof_element){
|
||||
elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element);
|
||||
elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units;
|
||||
}
|
||||
if(total_used_units + elem_units > received_units)
|
||||
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);
|
||||
assert_alignment(new_block);
|
||||
|
||||
//The last block should take all the remaining space
|
||||
if((low_idx + 1) == n_elements ||
|
||||
(total_used_units + elem_units +
|
||||
((!sizeof_element)
|
||||
? elem_units
|
||||
: std::max(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;
|
||||
memory_algo->priv_mark_new_allocated_block(new_block);
|
||||
|
||||
//If the remaining units are bigger than needed and we can
|
||||
//split it obtaining a new free memory block do it.
|
||||
if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){
|
||||
size_type shrunk_received;
|
||||
size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk;
|
||||
bool shrink_ok = shrink
|
||||
(memory_algo
|
||||
,memory_algo->priv_get_user_buffer(new_block)
|
||||
,shrunk_request
|
||||
,shrunk_request
|
||||
,shrunk_received);
|
||||
(void)shrink_ok;
|
||||
//Shrink must always succeed with passed parameters
|
||||
BOOST_ASSERT(shrink_ok);
|
||||
//Some sanity checks
|
||||
BOOST_ASSERT(shrunk_request == shrunk_received);
|
||||
BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits));
|
||||
//"new_block->m_size" must have been reduced to elem_units by "shrink"
|
||||
BOOST_ASSERT(new_block->m_size == elem_units);
|
||||
//Now update the total received units with the reduction
|
||||
received_units = elem_units + total_used_units;
|
||||
}
|
||||
}
|
||||
else{
|
||||
new_block->m_size = elem_units;
|
||||
memory_algo->priv_mark_new_allocated_block(new_block);
|
||||
}
|
||||
|
||||
block_address += new_block->m_size*Alignment;
|
||||
total_used_units += (size_type)new_block->m_size;
|
||||
//Check we have enough room to overwrite the intrusive pointer
|
||||
BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer));
|
||||
void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0);
|
||||
chain.push_back(p);
|
||||
++low_idx;
|
||||
}
|
||||
//Sanity check
|
||||
BOOST_ASSERT(total_used_units == received_units);
|
||||
}
|
||||
|
||||
if(low_idx != n_elements){
|
||||
priv_deallocate_many(memory_algo, chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain &chain)
|
||||
{
|
||||
while(!chain.empty()){
|
||||
memory_algo->priv_deallocate(to_raw_pointer(chain.pop_front()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP
|
1413
cpp/BoostParts/boost/interprocess/mem_algo/rbtree_best_fit.hpp
Normal file
1413
cpp/BoostParts/boost/interprocess/mem_algo/rbtree_best_fit.hpp
Normal file
File diff suppressed because it is too large
Load Diff
730
cpp/BoostParts/boost/interprocess/offset_ptr.hpp
Normal file
730
cpp/BoostParts/boost/interprocess/offset_ptr.hpp
Normal file
@ -0,0 +1,730 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_OFFSET_PTR_HPP
|
||||
#define BOOST_INTERPROCESS_OFFSET_PTR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/cast_tags.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
#include <iterator>
|
||||
#include <boost/aligned_storage.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a smart pointer that stores the offset between this pointer and
|
||||
//!target pointee, called offset_ptr.
|
||||
|
||||
namespace boost {
|
||||
|
||||
//Predeclarations
|
||||
template <class T>
|
||||
struct has_trivial_constructor;
|
||||
|
||||
template <class T>
|
||||
struct has_trivial_destructor;
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class OffsetType, std::size_t OffsetAlignment>
|
||||
union offset_ptr_internal
|
||||
{
|
||||
explicit offset_ptr_internal(OffsetType off)
|
||||
: m_offset(off)
|
||||
{}
|
||||
OffsetType m_offset; //Distance between this object and pointee address
|
||||
typename ::boost::aligned_storage
|
||||
< sizeof(OffsetType)
|
||||
, (OffsetAlignment == offset_type_alignment) ?
|
||||
::boost::alignment_of<OffsetType>::value : OffsetAlignment
|
||||
>::type alignment_helper;
|
||||
};
|
||||
|
||||
//Note: using the address of a local variable to point to another address
|
||||
//is not standard conforming and this can be optimized-away by the compiler.
|
||||
//Non-inlining is a method to remain illegal but correct
|
||||
|
||||
//Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline
|
||||
//this code without breaking the library
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// offset_ptr_to_raw_pointer
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
|
||||
#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
|
||||
|
||||
template<int Dummy>
|
||||
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
|
||||
BOOST_INTERPROCESS_NEVER_INLINE
|
||||
#elif defined(NDEBUG)
|
||||
inline
|
||||
#endif
|
||||
void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, std::size_t offset)
|
||||
{
|
||||
typedef pointer_size_t_caster<void*> caster_t;
|
||||
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
|
||||
if(offset == 1){
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
caster_t caster((void*)this_ptr);
|
||||
return caster_t(caster.size() + offset).pointer();
|
||||
}
|
||||
#else
|
||||
caster_t caster((void*)this_ptr);
|
||||
return caster_t((caster.size() + offset) & -std::size_t(offset != 1)).pointer();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
|
||||
#undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
|
||||
#endif
|
||||
#ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
|
||||
#undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// offset_ptr_to_offset
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
|
||||
//Branchless seems slower in x86
|
||||
//#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
|
||||
|
||||
template<int Dummy>
|
||||
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
|
||||
BOOST_INTERPROCESS_NEVER_INLINE
|
||||
#elif defined(NDEBUG)
|
||||
inline
|
||||
#endif
|
||||
std::size_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
|
||||
{
|
||||
typedef pointer_size_t_caster<void*> caster_t;
|
||||
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
|
||||
//offset == 1 && ptr != 0 is not legal for this pointer
|
||||
if(!ptr){
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
caster_t this_caster((void*)this_ptr);
|
||||
caster_t ptr_caster((void*)ptr);
|
||||
std::size_t offset = ptr_caster.size() - this_caster.size();
|
||||
BOOST_ASSERT(offset != 1);
|
||||
return offset;
|
||||
}
|
||||
#else
|
||||
caster_t this_caster((void*)this_ptr);
|
||||
caster_t ptr_caster((void*)ptr);
|
||||
std::size_t offset = (ptr_caster.size() - this_caster.size() - 1) & -std::size_t(ptr != 0);
|
||||
++offset;
|
||||
return offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
|
||||
#undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
|
||||
#endif
|
||||
#ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
|
||||
#undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// offset_ptr_to_offset_from_other
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
|
||||
//Branchless seems slower in x86
|
||||
//#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
|
||||
|
||||
template<int Dummy>
|
||||
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
|
||||
BOOST_INTERPROCESS_NEVER_INLINE
|
||||
#elif defined(NDEBUG)
|
||||
inline
|
||||
#endif
|
||||
std::size_t offset_ptr_to_offset_from_other
|
||||
(const volatile void *this_ptr, const volatile void *other_ptr, std::size_t other_offset)
|
||||
{
|
||||
typedef pointer_size_t_caster<void*> caster_t;
|
||||
#ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
|
||||
if(other_offset == 1){
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
caster_t this_caster((void*)this_ptr);
|
||||
caster_t other_caster((void*)other_ptr);
|
||||
std::size_t offset = other_caster.size() - this_caster.size() + other_offset;
|
||||
BOOST_ASSERT(offset != 1);
|
||||
return offset;
|
||||
}
|
||||
#else
|
||||
caster_t this_caster((void*)this_ptr);
|
||||
caster_t other_caster((void*)other_ptr);
|
||||
std::size_t offset = (other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1);
|
||||
offset += other_offset;
|
||||
return offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
|
||||
#undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
|
||||
#endif
|
||||
#ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
|
||||
#undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Let's assume cast to void and cv cast don't change any target address
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
template<class From, class To>
|
||||
struct offset_ptr_maintains_address
|
||||
{
|
||||
static const bool value = ipcdetail::is_cv_same<From, To>::value
|
||||
|| ipcdetail::is_cv_same<void, To>::value;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
/// @endcond
|
||||
|
||||
//!A smart pointer that stores the offset between between the pointer and the
|
||||
//!the object it points. This allows offset allows special properties, since
|
||||
//!the pointer is independent from the address address of the pointee, if the
|
||||
//!pointer and the pointee are still separated by the same offset. This feature
|
||||
//!converts offset_ptr in a smart pointer that can be placed in shared memory and
|
||||
//!memory mapped files mapped in different addresses in every process.
|
||||
template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
|
||||
class offset_ptr
|
||||
{
|
||||
/// @cond
|
||||
typedef offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> self_t;
|
||||
void unspecified_bool_type_func() const {}
|
||||
typedef void (self_t::*unspecified_bool_type)() const;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef PointedType element_type;
|
||||
typedef PointedType * pointer;
|
||||
typedef typename ipcdetail::
|
||||
add_reference<PointedType>::type reference;
|
||||
typedef typename ipcdetail::
|
||||
remove_volatile<typename ipcdetail::
|
||||
remove_const<PointedType>::type
|
||||
>::type value_type;
|
||||
typedef DifferenceType difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef OffsetType offset_type;
|
||||
|
||||
public: //Public Functions
|
||||
|
||||
//!Default constructor (null pointer).
|
||||
//!Never throws.
|
||||
offset_ptr()
|
||||
: internal(1)
|
||||
{}
|
||||
|
||||
//!Constructor from raw pointer (allows "0" pointer conversion).
|
||||
//!Never throws.
|
||||
offset_ptr(pointer ptr)
|
||||
: internal(static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(ptr, this)))
|
||||
{}
|
||||
|
||||
//!Constructor from other pointer.
|
||||
//!Never throws.
|
||||
template <class T>
|
||||
offset_ptr( T *ptr
|
||||
, typename ipcdetail::enable_if< ipcdetail::is_convertible<T*, PointedType*> >::type * = 0)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr), this)))
|
||||
{}
|
||||
|
||||
//!Constructor from other offset_ptr
|
||||
//!Never throws.
|
||||
offset_ptr(const offset_ptr& ptr)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset)))
|
||||
{}
|
||||
|
||||
//!Constructor from other offset_ptr. If pointers of pointee types are
|
||||
//!convertible, offset_ptrs will be convertibles. Never throws.
|
||||
template<class T2>
|
||||
offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
, typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
|
||||
&& ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
|
||||
>::type * = 0
|
||||
#endif
|
||||
)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset())))
|
||||
{}
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Constructor from other offset_ptr. If pointers of pointee types are
|
||||
//!convertible, offset_ptrs will be convertibles. Never throws.
|
||||
template<class T2>
|
||||
offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
|
||||
, typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
|
||||
&& !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
|
||||
>::type * = 0)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this)))
|
||||
{}
|
||||
|
||||
#endif
|
||||
|
||||
//!Emulates static_cast operator.
|
||||
//!Never throws.
|
||||
template<class T2, class P2, class O2, std::size_t A2>
|
||||
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(r.get()), this)))
|
||||
{}
|
||||
|
||||
//!Emulates const_cast operator.
|
||||
//!Never throws.
|
||||
template<class T2, class P2, class O2, std::size_t A2>
|
||||
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset<0>(const_cast<PointedType*>(r.get()), this)))
|
||||
{}
|
||||
|
||||
//!Emulates dynamic_cast operator.
|
||||
//!Never throws.
|
||||
template<class T2, class P2, class O2, std::size_t A2>
|
||||
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset<0>(dynamic_cast<PointedType*>(r.get()), this)))
|
||||
{}
|
||||
|
||||
//!Emulates reinterpret_cast operator.
|
||||
//!Never throws.
|
||||
template<class T2, class P2, class O2, std::size_t A2>
|
||||
offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag)
|
||||
: internal(static_cast<OffsetType>
|
||||
(ipcdetail::offset_ptr_to_offset<0>(reinterpret_cast<PointedType*>(r.get()), this)))
|
||||
{}
|
||||
|
||||
//!Obtains raw pointer from offset.
|
||||
//!Never throws.
|
||||
pointer get() const
|
||||
{ return (pointer)ipcdetail::offset_ptr_to_raw_pointer<0>(this, this->internal.m_offset); }
|
||||
|
||||
offset_type get_offset() const
|
||||
{ return this->internal.m_offset; }
|
||||
|
||||
//!Pointer-like -> operator. It can return 0 pointer.
|
||||
//!Never throws.
|
||||
pointer operator->() const
|
||||
{ return this->get(); }
|
||||
|
||||
//!Dereferencing operator, if it is a null offset_ptr behavior
|
||||
//! is undefined. Never throws.
|
||||
reference operator* () const
|
||||
{
|
||||
pointer p = this->get();
|
||||
reference r = *p;
|
||||
return r;
|
||||
}
|
||||
|
||||
//!Indexing operator.
|
||||
//!Never throws.
|
||||
reference operator[](difference_type idx) const
|
||||
{ return this->get()[idx]; }
|
||||
|
||||
//!Assignment from pointer (saves extra conversion).
|
||||
//!Never throws.
|
||||
offset_ptr& operator= (pointer from)
|
||||
{
|
||||
this->internal.m_offset =
|
||||
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(from, this));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Assignment from other offset_ptr.
|
||||
//!Never throws.
|
||||
offset_ptr& operator= (const offset_ptr & ptr)
|
||||
{
|
||||
this->internal.m_offset =
|
||||
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Assignment from related offset_ptr. If pointers of pointee types
|
||||
//! are assignable, offset_ptrs will be assignable. Never throws.
|
||||
template<class T2>
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
|
||||
&& ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
|
||||
, offset_ptr&>::type
|
||||
#else
|
||||
offset_ptr&
|
||||
#endif
|
||||
operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr)
|
||||
{
|
||||
this->internal.m_offset =
|
||||
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
template<class T2>
|
||||
typename ipcdetail::enable_if_c<ipcdetail::is_convertible<T2*, PointedType*>::value
|
||||
&& !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
|
||||
, offset_ptr&>::type
|
||||
operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr)
|
||||
{
|
||||
this->internal.m_offset =
|
||||
static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//!offset_ptr += difference_type.
|
||||
//!Never throws.
|
||||
offset_ptr &operator+= (difference_type offset)
|
||||
{ this->inc_offset(offset * sizeof (PointedType)); return *this; }
|
||||
|
||||
//!offset_ptr -= difference_type.
|
||||
//!Never throws.
|
||||
offset_ptr &operator-= (difference_type offset)
|
||||
{ this->dec_offset(offset * sizeof (PointedType)); return *this; }
|
||||
|
||||
//!++offset_ptr.
|
||||
//!Never throws.
|
||||
offset_ptr& operator++ (void)
|
||||
{ this->inc_offset(sizeof (PointedType)); return *this; }
|
||||
|
||||
//!offset_ptr++.
|
||||
//!Never throws.
|
||||
offset_ptr operator++ (int)
|
||||
{
|
||||
offset_ptr tmp(*this);
|
||||
this->inc_offset(sizeof (PointedType));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//!--offset_ptr.
|
||||
//!Never throws.
|
||||
offset_ptr& operator-- (void)
|
||||
{ this->dec_offset(sizeof (PointedType)); return *this; }
|
||||
|
||||
//!offset_ptr--.
|
||||
//!Never throws.
|
||||
offset_ptr operator-- (int)
|
||||
{
|
||||
offset_ptr tmp(*this);
|
||||
this->dec_offset(sizeof (PointedType));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//!safe bool conversion operator.
|
||||
//!Never throws.
|
||||
operator unspecified_bool_type() const
|
||||
{ return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; }
|
||||
|
||||
//!Not operator. Not needed in theory, but improves portability.
|
||||
//!Never throws
|
||||
bool operator! () const
|
||||
{ return this->internal.m_offset == 1; }
|
||||
|
||||
//!Compatibility with pointer_traits
|
||||
//!
|
||||
template <class U>
|
||||
struct rebind
|
||||
{ typedef offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment> other; };
|
||||
|
||||
//!Compatibility with pointer_traits
|
||||
//!
|
||||
static offset_ptr pointer_to(reference r)
|
||||
{ return offset_ptr(&r); }
|
||||
|
||||
//!difference_type + offset_ptr
|
||||
//!operation
|
||||
friend offset_ptr operator+(difference_type diff, offset_ptr right)
|
||||
{ right += diff; return right; }
|
||||
|
||||
//!offset_ptr + difference_type
|
||||
//!operation
|
||||
friend offset_ptr operator+(offset_ptr left, difference_type diff)
|
||||
{ left += diff; return left; }
|
||||
|
||||
//!offset_ptr - diff
|
||||
//!operation
|
||||
friend offset_ptr operator-(offset_ptr left, difference_type diff)
|
||||
{ left -= diff; return left; }
|
||||
|
||||
//!offset_ptr - diff
|
||||
//!operation
|
||||
friend offset_ptr operator-(difference_type diff, offset_ptr right)
|
||||
{ right -= diff; return right; }
|
||||
|
||||
//!offset_ptr - offset_ptr
|
||||
//!operation
|
||||
friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2)
|
||||
{ return difference_type(pt.get()- pt2.get()); }
|
||||
|
||||
//Comparison
|
||||
friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2)
|
||||
{ return pt1.get() == pt2.get(); }
|
||||
|
||||
friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2)
|
||||
{ return pt1.get() != pt2.get(); }
|
||||
|
||||
friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2)
|
||||
{ return pt1.get() < pt2.get(); }
|
||||
|
||||
friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2)
|
||||
{ return pt1.get() <= pt2.get(); }
|
||||
|
||||
friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2)
|
||||
{ return pt1.get() > pt2.get(); }
|
||||
|
||||
friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2)
|
||||
{ return pt1.get() >= pt2.get(); }
|
||||
|
||||
//Comparison to raw ptr to support literal 0
|
||||
friend bool operator== (pointer pt1, const offset_ptr &pt2)
|
||||
{ return pt1 == pt2.get(); }
|
||||
|
||||
friend bool operator!= (pointer pt1, const offset_ptr &pt2)
|
||||
{ return pt1 != pt2.get(); }
|
||||
|
||||
friend bool operator<(pointer pt1, const offset_ptr &pt2)
|
||||
{ return pt1 < pt2.get(); }
|
||||
|
||||
friend bool operator<=(pointer pt1, const offset_ptr &pt2)
|
||||
{ return pt1 <= pt2.get(); }
|
||||
|
||||
friend bool operator>(pointer pt1, const offset_ptr &pt2)
|
||||
{ return pt1 > pt2.get(); }
|
||||
|
||||
friend bool operator>=(pointer pt1, const offset_ptr &pt2)
|
||||
{ return pt1 >= pt2.get(); }
|
||||
|
||||
//Comparison
|
||||
friend bool operator== (const offset_ptr &pt1, pointer pt2)
|
||||
{ return pt1.get() == pt2; }
|
||||
|
||||
friend bool operator!= (const offset_ptr &pt1, pointer pt2)
|
||||
{ return pt1.get() != pt2; }
|
||||
|
||||
friend bool operator<(const offset_ptr &pt1, pointer pt2)
|
||||
{ return pt1.get() < pt2; }
|
||||
|
||||
friend bool operator<=(const offset_ptr &pt1, pointer pt2)
|
||||
{ return pt1.get() <= pt2; }
|
||||
|
||||
friend bool operator>(const offset_ptr &pt1, pointer pt2)
|
||||
{ return pt1.get() > pt2; }
|
||||
|
||||
friend bool operator>=(const offset_ptr &pt1, pointer pt2)
|
||||
{ return pt1.get() >= pt2; }
|
||||
|
||||
friend void swap(offset_ptr &left, offset_ptr &right)
|
||||
{
|
||||
pointer ptr = right.get();
|
||||
right = left;
|
||||
left = ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @cond
|
||||
void inc_offset(DifferenceType bytes)
|
||||
{ internal.m_offset += bytes; }
|
||||
|
||||
void dec_offset(DifferenceType bytes)
|
||||
{ internal.m_offset -= bytes; }
|
||||
|
||||
ipcdetail::offset_ptr_internal<OffsetType, OffsetAlignment> internal;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!operator<<
|
||||
//!for offset ptr
|
||||
template<class E, class T, class W, class X, class Y, std::size_t Z>
|
||||
inline std::basic_ostream<E, T> & operator<<
|
||||
(std::basic_ostream<E, T> & os, offset_ptr<W, X, Y, Z> const & p)
|
||||
{ return os << p.get_offset(); }
|
||||
|
||||
//!operator>>
|
||||
//!for offset ptr
|
||||
template<class E, class T, class W, class X, class Y, std::size_t Z>
|
||||
inline std::basic_istream<E, T> & operator>>
|
||||
(std::basic_istream<E, T> & is, offset_ptr<W, X, Y, Z> & p)
|
||||
{ return is >> p.get_offset(); }
|
||||
|
||||
//!Simulation of static_cast between pointers. Never throws.
|
||||
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
|
||||
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
static_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
|
||||
{
|
||||
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
(r, boost::interprocess::ipcdetail::static_cast_tag());
|
||||
}
|
||||
|
||||
//!Simulation of const_cast between pointers. Never throws.
|
||||
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
|
||||
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
const_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
|
||||
{
|
||||
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
(r, boost::interprocess::ipcdetail::const_cast_tag());
|
||||
}
|
||||
|
||||
//!Simulation of dynamic_cast between pointers. Never throws.
|
||||
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
|
||||
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
dynamic_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
|
||||
{
|
||||
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
(r, boost::interprocess::ipcdetail::dynamic_cast_tag());
|
||||
}
|
||||
|
||||
//!Simulation of reinterpret_cast between pointers. Never throws.
|
||||
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
|
||||
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
reinterpret_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
|
||||
{
|
||||
return boost::interprocess::offset_ptr<T1, P1, O1, A1>
|
||||
(r, boost::interprocess::ipcdetail::reinterpret_cast_tag());
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
//!has_trivial_constructor<> == true_type specialization for optimizations
|
||||
template <class T, class P, class O, std::size_t A>
|
||||
struct has_trivial_constructor< boost::interprocess::offset_ptr<T, P, O, A> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
///has_trivial_destructor<> == true_type specialization for optimizations
|
||||
template <class T, class P, class O, std::size_t A>
|
||||
struct has_trivial_destructor< boost::interprocess::offset_ptr<T, P, O, A> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr.
|
||||
//!Never throws.
|
||||
template <class T, class P, class O, std::size_t A>
|
||||
inline T * to_raw_pointer(boost::interprocess::offset_ptr<T, P, O, A> const & p)
|
||||
{ return ipcdetail::to_raw_pointer(p); }
|
||||
|
||||
} //namespace interprocess
|
||||
|
||||
|
||||
/// @endcond
|
||||
} //namespace boost {
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace boost{
|
||||
|
||||
//This is to support embedding a bit in the pointer
|
||||
//for intrusive containers, saving space
|
||||
namespace intrusive {
|
||||
|
||||
//Predeclaration to avoid including header
|
||||
template<class VoidPointer, std::size_t N>
|
||||
struct max_pointer_plus_bits;
|
||||
|
||||
template<std::size_t OffsetAlignment, class P, class O, std::size_t A>
|
||||
struct max_pointer_plus_bits<boost::interprocess::offset_ptr<void, P, O, A>, OffsetAlignment>
|
||||
{
|
||||
//The offset ptr can embed one bit less than the alignment since it
|
||||
//uses offset == 1 to store the null pointer.
|
||||
static const std::size_t value = ::boost::interprocess::ipcdetail::ls_zeros<OffsetAlignment>::value - 1;
|
||||
};
|
||||
|
||||
//Predeclaration
|
||||
template<class Pointer, std::size_t NumBits>
|
||||
struct pointer_plus_bits;
|
||||
|
||||
template<class T, class P, class O, std::size_t A, std::size_t NumBits>
|
||||
struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
|
||||
{
|
||||
typedef boost::interprocess::offset_ptr<T, P, O, A> pointer;
|
||||
typedef ::boost::interprocess::pointer_size_t_caster<T*> caster_t;
|
||||
//Bits are stored in the lower bits of the pointer except the LSB,
|
||||
//because this bit is used to represent the null pointer.
|
||||
static const std::size_t Mask = ((std::size_t(1) << NumBits) - 1) << 1u;
|
||||
|
||||
static pointer get_pointer(const pointer &n)
|
||||
{
|
||||
caster_t caster(n.get());
|
||||
return pointer(caster_t(caster.size() & ~Mask).pointer());
|
||||
}
|
||||
|
||||
static void set_pointer(pointer &n, const pointer &p)
|
||||
{
|
||||
caster_t n_caster(n.get());
|
||||
caster_t p_caster(p.get());
|
||||
BOOST_ASSERT(0 == (p_caster.size() & Mask));
|
||||
n = caster_t(p_caster.size() | (n_caster.size() & Mask)).pointer();
|
||||
}
|
||||
|
||||
static std::size_t get_bits(const pointer &n)
|
||||
{ return (caster_t(n.get()).size() & Mask) >> 1u; }
|
||||
|
||||
static void set_bits(pointer &n, std::size_t b)
|
||||
{
|
||||
BOOST_ASSERT(b < (std::size_t(1) << NumBits));
|
||||
caster_t n_caster(n.get());
|
||||
n = caster_t((n_caster.size() & ~Mask) | (b << 1u)).pointer();
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
|
||||
//Predeclaration
|
||||
template<class T, class U>
|
||||
struct pointer_to_other;
|
||||
|
||||
//Backwards compatibility with pointer_to_other
|
||||
template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment, class U>
|
||||
struct pointer_to_other
|
||||
< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment>, U >
|
||||
{
|
||||
typedef ::boost::interprocess::offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment> type;
|
||||
};
|
||||
|
||||
} //namespace boost{
|
||||
/// @endcond
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP
|
132
cpp/BoostParts/boost/interprocess/permissions.hpp
Normal file
132
cpp/BoostParts/boost/interprocess/permissions.hpp
Normal file
@ -0,0 +1,132 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_PERMISSIONS_HPP
|
||||
#define BOOST_INTERPROCESS_PERMISSIONS_HPP
|
||||
|
||||
/// @cond
|
||||
|
||||
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!\file
|
||||
//!Describes permissions class
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
template <int Dummy>
|
||||
struct unrestricted_permissions_holder
|
||||
{
|
||||
static winapi::interprocess_all_access_security unrestricted;
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
winapi::interprocess_all_access_security unrestricted_permissions_holder<Dummy>::unrestricted;
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
#endif //defined BOOST_INTERPROCESS_WINDOWS
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!The permissions class represents permissions to be set to shared memory or
|
||||
//!files, that can be constructed form usual permission representations:
|
||||
//!a SECURITY_ATTRIBUTES pointer in windows or ORed rwx chmod integer in UNIX.
|
||||
class permissions
|
||||
{
|
||||
/// @cond
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
typedef void* os_permissions_type;
|
||||
#else
|
||||
typedef int os_permissions_type;
|
||||
#endif
|
||||
os_permissions_type m_perm;
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructs a permissions object from a user provided os-dependent
|
||||
//!permissions.
|
||||
permissions(os_permissions_type type)
|
||||
: m_perm(type)
|
||||
{}
|
||||
|
||||
//!Constructs a default permissions object:
|
||||
//!A null security attributes pointer for windows or 0644
|
||||
//!for UNIX.
|
||||
permissions()
|
||||
{ set_default(); }
|
||||
|
||||
//!Sets permissions to default values:
|
||||
//!A null security attributes pointer for windows or 0644
|
||||
//!for UNIX.
|
||||
void set_default()
|
||||
{
|
||||
/// @cond
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
m_perm = 0;
|
||||
#else
|
||||
m_perm = 0644;
|
||||
#endif
|
||||
/// @endcond
|
||||
}
|
||||
|
||||
//!Sets permissions to unrestricted access:
|
||||
//!A null DACL for windows or 0666 for UNIX.
|
||||
void set_unrestricted()
|
||||
{
|
||||
/// @cond
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
m_perm = &ipcdetail::unrestricted_permissions_holder<0>::unrestricted;
|
||||
#else
|
||||
m_perm = 0666;
|
||||
#endif
|
||||
/// @endcond
|
||||
}
|
||||
|
||||
//!Sets permissions from a user provided os-dependent
|
||||
//!permissions.
|
||||
void set_permissions(os_permissions_type perm)
|
||||
{ m_perm = perm; }
|
||||
|
||||
//!Returns stored os-dependent
|
||||
//!permissions
|
||||
os_permissions_type get_permissions() const
|
||||
{ return m_perm; }
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_PERMISSIONS_HPP
|
||||
|
1366
cpp/BoostParts/boost/interprocess/segment_manager.hpp
Normal file
1366
cpp/BoostParts/boost/interprocess/segment_manager.hpp
Normal file
File diff suppressed because it is too large
Load Diff
422
cpp/BoostParts/boost/interprocess/shared_memory_object.hpp
Normal file
422
cpp/BoostParts/boost/interprocess/shared_memory_object.hpp
Normal file
@ -0,0 +1,422 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_SHARED_MEMORY_OBJECT_HPP
|
||||
#define BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY)
|
||||
# include <sys/shm.h> //System V shared memory...
|
||||
#elif defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
|
||||
# include <fcntl.h> //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,
|
||||
# if defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
|
||||
# if defined(__FreeBSD__)
|
||||
# include <sys/sysctl.h>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
//
|
||||
#endif
|
||||
|
||||
//!\file
|
||||
//!Describes a shared memory object management class.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!A class that wraps a shared memory mapping that can be used to
|
||||
//!create mapped regions from the mapped files
|
||||
class shared_memory_object
|
||||
{
|
||||
/// @cond
|
||||
//Non-copyable and non-assignable
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(shared_memory_object)
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Default constructor. Represents an empty shared_memory_object.
|
||||
shared_memory_object();
|
||||
|
||||
//!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode"
|
||||
//!If the file previously exists, throws an error.*/
|
||||
shared_memory_object(create_only_t, const char *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.
|
||||
shared_memory_object(open_or_create_t, const char *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.
|
||||
shared_memory_object(open_only_t, const char *name, mode_t mode)
|
||||
{ this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
|
||||
|
||||
//!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)
|
||||
: m_handle(file_handle_t(ipcdetail::invalid_file()))
|
||||
{ this->swap(moved); }
|
||||
|
||||
//!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 tmp(boost::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps the shared_memory_objects. Does not throw
|
||||
void swap(shared_memory_object &moved);
|
||||
|
||||
//!Erases a shared memory object from the system.
|
||||
//!Returns false on error. Never throws
|
||||
static bool remove(const char *name);
|
||||
|
||||
//!Sets the size of the shared memory mapping
|
||||
void truncate(offset_t length);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. All mapped regions are still
|
||||
//!valid after destruction. The destructor function will deallocate
|
||||
//!any system resources allocated by the system for use by this process for
|
||||
//!this resource. The resource can still be opened again calling
|
||||
//!the open constructor overload. To erase the resource from the system
|
||||
//!use remove().
|
||||
~shared_memory_object();
|
||||
|
||||
//!Returns the name of the shared memory object.
|
||||
const char *get_name() const;
|
||||
|
||||
//!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;
|
||||
|
||||
//!Returns access mode
|
||||
mode_t get_mode() const;
|
||||
|
||||
//!Returns mapping handle. Never throws.
|
||||
mapping_handle_t get_mapping_handle() const;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
|
||||
//!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);
|
||||
|
||||
file_handle_t m_handle;
|
||||
mode_t m_mode;
|
||||
std::string m_filename;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
inline shared_memory_object::shared_memory_object()
|
||||
: m_handle(file_handle_t(ipcdetail::invalid_file()))
|
||||
{}
|
||||
|
||||
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 bool shared_memory_object::get_size(offset_t &size) const
|
||||
{ return ipcdetail::get_file_size((file_handle_t)m_handle, size); }
|
||||
|
||||
inline void shared_memory_object::swap(shared_memory_object &other)
|
||||
{
|
||||
std::swap(m_handle, other.m_handle);
|
||||
std::swap(m_mode, other.m_mode);
|
||||
m_filename.swap(other.m_filename);
|
||||
}
|
||||
|
||||
inline mapping_handle_t shared_memory_object::get_mapping_handle() const
|
||||
{
|
||||
return ipcdetail::mapping_handle_from_file_handle(m_handle);
|
||||
}
|
||||
|
||||
inline mode_t shared_memory_object::get_mode() const
|
||||
{ return m_mode; }
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
|
||||
|
||||
inline bool shared_memory_object::priv_open_or_create
|
||||
(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm)
|
||||
{
|
||||
m_filename = filename;
|
||||
std::string shmfile;
|
||||
ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, shmfile);
|
||||
|
||||
//Set accesses
|
||||
if (mode != read_write && mode != read_only){
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
switch(type){
|
||||
case ipcdetail::DoOpen:
|
||||
m_handle = ipcdetail::open_existing_file(shmfile.c_str(), mode, true);
|
||||
break;
|
||||
case ipcdetail::DoCreate:
|
||||
m_handle = ipcdetail::create_new_file(shmfile.c_str(), mode, perm, true);
|
||||
break;
|
||||
case ipcdetail::DoOpenOrCreate:
|
||||
m_handle = ipcdetail::create_or_open_file(shmfile.c_str(), mode, perm, true);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//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;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool shared_memory_object::remove(const char *filename)
|
||||
{
|
||||
try{
|
||||
//Make sure a temporary path is created for shared memory
|
||||
std::string shmfile;
|
||||
ipcdetail::tmp_filename(filename, shmfile);
|
||||
return ipcdetail::delete_file(shmfile.c_str());
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void shared_memory_object::truncate(offset_t length)
|
||||
{
|
||||
if(!ipcdetail::truncate_file(m_handle, length)){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void shared_memory_object::priv_close()
|
||||
{
|
||||
if(m_handle != ipcdetail::invalid_file()){
|
||||
ipcdetail::close_file(m_handle);
|
||||
m_handle = ipcdetail::invalid_file();
|
||||
}
|
||||
}
|
||||
|
||||
#else //!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
|
||||
|
||||
namespace shared_memory_object_detail {
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
|
||||
inline bool use_filesystem_based_posix()
|
||||
{
|
||||
int jailed = 0;
|
||||
std::size_t len = sizeof(jailed);
|
||||
::sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0);
|
||||
return jailed != 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Not supported platform for BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
} //shared_memory_object_detail
|
||||
|
||||
inline bool shared_memory_object::priv_open_or_create
|
||||
(ipcdetail::create_enum_t type,
|
||||
const char *filename,
|
||||
mode_t mode, const permissions &perm)
|
||||
{
|
||||
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
|
||||
const bool add_leading_slash = false;
|
||||
#elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
|
||||
const bool add_leading_slash = !shared_memory_object_detail::use_filesystem_based_posix();
|
||||
#else
|
||||
const bool add_leading_slash = true;
|
||||
#endif
|
||||
if(add_leading_slash){
|
||||
ipcdetail::add_leading_slash(filename, m_filename);
|
||||
}
|
||||
else{
|
||||
ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, m_filename);
|
||||
}
|
||||
|
||||
//Create new mapping
|
||||
int oflag = 0;
|
||||
if(mode == read_only){
|
||||
oflag |= O_RDONLY;
|
||||
}
|
||||
else if(mode == read_write){
|
||||
oflag |= O_RDWR;
|
||||
}
|
||||
else{
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
int unix_perm = perm.get_permissions();
|
||||
|
||||
switch(type){
|
||||
case ipcdetail::DoOpen:
|
||||
{
|
||||
//No oflag addition
|
||||
m_handle = shm_open(m_filename.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);
|
||||
if(m_handle >= 0){
|
||||
::fchmod(m_handle, unix_perm);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ipcdetail::DoOpenOrCreate:
|
||||
{
|
||||
oflag |= O_CREAT;
|
||||
//We need a loop to change permissions correctly using fchmod, since
|
||||
//with "O_CREAT only" shm_open we don't know if we've created or opened the file.
|
||||
while(1){
|
||||
m_handle = shm_open(m_filename.c_str(), oflag, unix_perm);
|
||||
if(m_handle >= 0){
|
||||
::fchmod(m_handle, unix_perm);
|
||||
break;
|
||||
}
|
||||
else if(errno == EEXIST){
|
||||
if((m_handle = shm_open(m_filename.c_str(), oflag, unix_perm)) >= 0 || errno != ENOENT){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//Check for error
|
||||
if(m_handle == -1){
|
||||
error_info err = errno;
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
m_filename = filename;
|
||||
m_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool shared_memory_object::remove(const char *filename)
|
||||
{
|
||||
try{
|
||||
std::string file_str;
|
||||
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
|
||||
const bool add_leading_slash = false;
|
||||
#elif defined(BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY)
|
||||
const bool add_leading_slash = !shared_memory_object_detail::use_filesystem_based_posix();
|
||||
#else
|
||||
const bool add_leading_slash = true;
|
||||
#endif
|
||||
if(add_leading_slash){
|
||||
ipcdetail::add_leading_slash(filename, file_str);
|
||||
}
|
||||
else{
|
||||
ipcdetail::tmp_filename(filename, file_str);
|
||||
}
|
||||
return 0 == shm_unlink(file_str.c_str());
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void shared_memory_object::truncate(offset_t length)
|
||||
{
|
||||
if(0 != ftruncate(m_handle, length)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void shared_memory_object::priv_close()
|
||||
{
|
||||
if(m_handle != -1){
|
||||
::close(m_handle);
|
||||
m_handle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
///@endcond
|
||||
|
||||
//!A class that stores the name of a shared memory
|
||||
//!and calls shared_memory_object::remove(name) in its destructor
|
||||
//!Useful to remove temporary shared memory objects in the presence
|
||||
//!of exceptions
|
||||
class remove_shared_memory_on_destroy
|
||||
{
|
||||
const char * m_name;
|
||||
public:
|
||||
remove_shared_memory_on_destroy(const char *name)
|
||||
: m_name(name)
|
||||
{}
|
||||
|
||||
~remove_shared_memory_on_destroy()
|
||||
{ shared_memory_object::remove(m_name); }
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP
|
64
cpp/BoostParts/boost/interprocess/smart_ptr/deleter.hpp
Normal file
64
cpp/BoostParts/boost/interprocess/smart_ptr/deleter.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-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_DELETER_HPP
|
||||
#define BOOST_INTERPROCESS_DELETER_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes the functor to delete objects from the segment.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!A deleter that uses the segment manager's destroy_ptr
|
||||
//!function to destroy the passed pointer resource.
|
||||
//!
|
||||
//!This deleter is used
|
||||
template<class T, class SegmentManager>
|
||||
class deleter
|
||||
{
|
||||
public:
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<typename SegmentManager::void_pointer>::template
|
||||
rebind_pointer<T>::type pointer;
|
||||
|
||||
private:
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<pointer>::template
|
||||
rebind_pointer<SegmentManager>::type segment_manager_pointer;
|
||||
|
||||
segment_manager_pointer mp_mngr;
|
||||
|
||||
public:
|
||||
deleter(segment_manager_pointer pmngr)
|
||||
: mp_mngr(pmngr)
|
||||
{}
|
||||
|
||||
void operator()(const pointer &p)
|
||||
{ mp_mngr->destroy_ptr(ipcdetail::to_raw_pointer(p)); }
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DELETER_HPP
|
444
cpp/BoostParts/boost/interprocess/streams/bufferstream.hpp
Normal file
444
cpp/BoostParts/boost/interprocess/streams/bufferstream.hpp
Normal file
@ -0,0 +1,444 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012.
|
||||
// Changed internal SGI string to a buffer. Added efficient
|
||||
// internal buffer get/set/swap functions, so that we can obtain/establish the
|
||||
// internal buffer without any reallocation or copy. Kill those temporaries!
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Copyright (c) 1998
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
//!\file
|
||||
//!This file defines basic_bufferbuf, basic_ibufferstream,
|
||||
//!basic_obufferstream, and basic_bufferstream classes. These classes
|
||||
//!represent streamsbufs and streams whose sources or destinations
|
||||
//!are fixed size character buffers.
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_BUFFERSTREAM_HPP
|
||||
#define BOOST_INTERPROCESS_BUFFERSTREAM_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <ios>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string> // char traits
|
||||
#include <cstddef> // ptrdiff_t
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
|
||||
namespace boost { namespace interprocess {
|
||||
|
||||
//!A streambuf class that controls the transmission of elements to and from
|
||||
//!a basic_xbufferstream. The elements are transmitted from a to a fixed
|
||||
//!size buffer
|
||||
template <class CharT, class CharTraits>
|
||||
class basic_bufferbuf
|
||||
: public std::basic_streambuf<CharT, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef CharT char_type;
|
||||
typedef typename CharTraits::int_type int_type;
|
||||
typedef typename CharTraits::pos_type pos_type;
|
||||
typedef typename CharTraits::off_type off_type;
|
||||
typedef CharTraits traits_type;
|
||||
typedef std::basic_streambuf<char_type, traits_type> base_t;
|
||||
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Does not throw.
|
||||
explicit basic_bufferbuf(std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: base_t(), m_mode(mode), m_buffer(0), m_length(0)
|
||||
{}
|
||||
|
||||
//!Constructor. Assigns formatting buffer.
|
||||
//!Does not throw.
|
||||
explicit basic_bufferbuf(CharT *buf, std::size_t length,
|
||||
std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: base_t(), m_mode(mode), m_buffer(buf), m_length(length)
|
||||
{ this->set_pointers(); }
|
||||
|
||||
virtual ~basic_bufferbuf(){}
|
||||
|
||||
public:
|
||||
//!Returns the pointer and size of the internal buffer.
|
||||
//!Does not throw.
|
||||
std::pair<CharT *, std::size_t> buffer() const
|
||||
{ return std::pair<CharT *, std::size_t>(m_buffer, m_length); }
|
||||
|
||||
//!Sets the underlying buffer to a new value
|
||||
//!Does not throw.
|
||||
void buffer(CharT *buf, std::size_t length)
|
||||
{ m_buffer = buf; m_length = length; this->set_pointers(); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
void set_pointers()
|
||||
{
|
||||
// The initial read position is the beginning of the buffer.
|
||||
if(m_mode & std::ios_base::in)
|
||||
this->setg(m_buffer, m_buffer, m_buffer + m_length);
|
||||
|
||||
// The initial write position is the beginning of the buffer.
|
||||
if(m_mode & std::ios_base::out)
|
||||
this->setp(m_buffer, m_buffer + m_length);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int_type underflow()
|
||||
{
|
||||
// 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())
|
||||
{
|
||||
if(this->gptr() != this->eback()) {
|
||||
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
|
||||
if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) {
|
||||
this->gbump(-1);
|
||||
return c;
|
||||
}
|
||||
else if(m_mode & std::ios_base::out) {
|
||||
this->gbump(-1);
|
||||
*this->gptr() = c;
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return CharTraits::eof();
|
||||
}
|
||||
else {
|
||||
this->gbump(-1);
|
||||
return CharTraits::not_eof(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
return CharTraits::eof();
|
||||
}
|
||||
|
||||
virtual int_type overflow(int_type c = CharTraits::eof())
|
||||
{
|
||||
if(m_mode & std::ios_base::out) {
|
||||
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
|
||||
// if(!(m_mode & std::ios_base::in)) {
|
||||
// if(this->pptr() != this->epptr()) {
|
||||
// *this->pptr() = CharTraits::to_char_type(c);
|
||||
// this->pbump(1);
|
||||
// return c;
|
||||
// }
|
||||
// else
|
||||
// return CharTraits::eof();
|
||||
// }
|
||||
// else {
|
||||
if(this->pptr() == this->epptr()) {
|
||||
//We can't append to a static buffer
|
||||
return CharTraits::eof();
|
||||
}
|
||||
else {
|
||||
*this->pptr() = CharTraits::to_char_type(c);
|
||||
this->pbump(1);
|
||||
return c;
|
||||
}
|
||||
// }
|
||||
}
|
||||
else // c is EOF, so we don't have to do anything
|
||||
return CharTraits::not_eof(c);
|
||||
}
|
||||
else // Overflow always fails if it's read-only.
|
||||
return CharTraits::eof();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
bool in = false;
|
||||
bool out = false;
|
||||
|
||||
const std::ios_base::openmode inout =
|
||||
std::ios_base::in | std::ios_base::out;
|
||||
|
||||
if((mode & inout) == inout) {
|
||||
if(dir == std::ios_base::beg || dir == std::ios_base::end)
|
||||
in = out = true;
|
||||
}
|
||||
else if(mode & std::ios_base::in)
|
||||
in = true;
|
||||
else if(mode & std::ios_base::out)
|
||||
out = true;
|
||||
|
||||
if(!in && !out)
|
||||
return pos_type(off_type(-1));
|
||||
else if((in && (!(m_mode & std::ios_base::in) || this->gptr() == 0)) ||
|
||||
(out && (!(m_mode & std::ios_base::out) || this->pptr() == 0)))
|
||||
return pos_type(off_type(-1));
|
||||
|
||||
std::streamoff newoff;
|
||||
switch(dir) {
|
||||
case std::ios_base::beg:
|
||||
newoff = 0;
|
||||
break;
|
||||
case std::ios_base::end:
|
||||
newoff = static_cast<std::streamoff>(m_length);
|
||||
break;
|
||||
case std::ios_base::cur:
|
||||
newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback())
|
||||
: static_cast<std::streamoff>(this->pptr() - this->pbase());
|
||||
break;
|
||||
default:
|
||||
return pos_type(off_type(-1));
|
||||
}
|
||||
|
||||
off += newoff;
|
||||
|
||||
if(in) {
|
||||
std::ptrdiff_t n = this->egptr() - this->eback();
|
||||
|
||||
if(off < 0 || off > n)
|
||||
return pos_type(off_type(-1));
|
||||
else
|
||||
this->setg(this->eback(), this->eback() + off, this->eback() + n);
|
||||
}
|
||||
|
||||
if(out) {
|
||||
std::ptrdiff_t n = this->epptr() - this->pbase();
|
||||
|
||||
if(off < 0 || off > n)
|
||||
return pos_type(off_type(-1));
|
||||
else {
|
||||
this->setp(this->pbase(), this->pbase() + n);
|
||||
this->pbump(off);
|
||||
}
|
||||
}
|
||||
|
||||
return pos_type(off);
|
||||
}
|
||||
|
||||
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
{ return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); }
|
||||
|
||||
private:
|
||||
std::ios_base::openmode m_mode;
|
||||
CharT * m_buffer;
|
||||
std::size_t m_length;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!A basic_istream class that uses a fixed size character buffer
|
||||
//!as its formatting buffer.
|
||||
template <class CharT, class CharTraits>
|
||||
class basic_ibufferstream
|
||||
: public std::basic_istream<CharT, CharTraits>
|
||||
{
|
||||
public: // Typedefs
|
||||
typedef typename std::basic_ios
|
||||
<CharT, CharTraits>::char_type char_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
|
||||
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_istream<char_type, CharTraits> base_t;
|
||||
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Does not throw.
|
||||
basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
//!Constructor. Assigns formatting buffer.
|
||||
//!Does not throw.
|
||||
basic_ibufferstream(const CharT *buf, std::size_t length,
|
||||
std::ios_base::openmode mode = std::ios_base::in)
|
||||
: basic_ios_t(), base_t(0),
|
||||
m_buf(const_cast<CharT*>(buf), length, mode | std::ios_base::in)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
~basic_ibufferstream(){};
|
||||
|
||||
public:
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
|
||||
|
||||
//!Returns the pointer and size of the internal buffer.
|
||||
//!Does not throw.
|
||||
std::pair<const CharT *, std::size_t> buffer() const
|
||||
{ return m_buf.buffer(); }
|
||||
|
||||
//!Sets the underlying buffer to a new value. Resets
|
||||
//!stream position. Does not throw.
|
||||
void buffer(const CharT *buf, std::size_t length)
|
||||
{ m_buf.buffer(const_cast<CharT*>(buf), length); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
basic_bufferbuf<CharT, CharTraits> m_buf;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!A basic_ostream class that uses a fixed size character buffer
|
||||
//!as its formatting buffer.
|
||||
template <class CharT, class CharTraits>
|
||||
class basic_obufferstream
|
||||
: public std::basic_ostream<CharT, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef typename std::basic_ios
|
||||
<CharT, CharTraits>::char_type char_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_ostream<char_type, CharTraits> base_t;
|
||||
/// @endcond
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Does not throw.
|
||||
basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
//!Constructor. Assigns formatting buffer.
|
||||
//!Does not throw.
|
||||
basic_obufferstream(CharT *buf, std::size_t length,
|
||||
std::ios_base::openmode mode = std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0),
|
||||
m_buf(buf, length, mode | std::ios_base::out)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
~basic_obufferstream(){}
|
||||
|
||||
public:
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
|
||||
|
||||
//!Returns the pointer and size of the internal buffer.
|
||||
//!Does not throw.
|
||||
std::pair<CharT *, std::size_t> buffer() const
|
||||
{ return m_buf.buffer(); }
|
||||
|
||||
//!Sets the underlying buffer to a new value. Resets
|
||||
//!stream position. Does not throw.
|
||||
void buffer(CharT *buf, std::size_t length)
|
||||
{ m_buf.buffer(buf, length); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
basic_bufferbuf<CharT, CharTraits> m_buf;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
|
||||
//!A basic_iostream class that uses a fixed size character buffer
|
||||
//!as its formatting buffer.
|
||||
template <class CharT, class CharTraits>
|
||||
class basic_bufferstream
|
||||
: public std::basic_iostream<CharT, CharTraits>
|
||||
|
||||
{
|
||||
public: // Typedefs
|
||||
typedef typename std::basic_ios
|
||||
<CharT, CharTraits>::char_type char_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_iostream<char_type, CharTraits> base_t;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Does not throw.
|
||||
basic_bufferstream(std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
//!Constructor. Assigns formatting buffer.
|
||||
//!Does not throw.
|
||||
basic_bufferstream(CharT *buf, std::size_t length,
|
||||
std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(buf, length, mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
~basic_bufferstream(){}
|
||||
|
||||
public:
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
|
||||
|
||||
//!Returns the pointer and size of the internal buffer.
|
||||
//!Does not throw.
|
||||
std::pair<CharT *, std::size_t> buffer() const
|
||||
{ return m_buf.buffer(); }
|
||||
|
||||
//!Sets the underlying buffer to a new value. Resets
|
||||
//!stream position. Does not throw.
|
||||
void buffer(CharT *buf, std::size_t length)
|
||||
{ m_buf.buffer(buf, length); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
basic_bufferbuf<CharT, CharTraits> m_buf;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//Some typedefs to simplify usage
|
||||
typedef basic_bufferbuf<char> bufferbuf;
|
||||
typedef basic_bufferstream<char> bufferstream;
|
||||
typedef basic_ibufferstream<char> ibufferstream;
|
||||
typedef basic_obufferstream<char> obufferstream;
|
||||
|
||||
typedef basic_bufferbuf<wchar_t> wbufferbuf;
|
||||
typedef basic_bufferstream<wchar_t> wbufferstream;
|
||||
typedef basic_ibufferstream<wchar_t> wibufferstream;
|
||||
typedef basic_obufferstream<wchar_t> wobufferstream;
|
||||
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif /* BOOST_INTERPROCESS_BUFFERSTREAM_HPP */
|
184
cpp/BoostParts/boost/interprocess/sync/interprocess_mutex.hpp
Normal file
184
cpp/BoostParts/boost/interprocess/sync/interprocess_mutex.hpp
Normal file
@ -0,0 +1,184 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_MUTEX_HPP
|
||||
|
||||
/// @cond
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#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>
|
||||
|
||||
#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...
|
||||
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
#include <boost/interprocess/sync/windows/mutex.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_WINDOWS
|
||||
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
#include <boost/interprocess/sync/spin/mutex.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
namespace robust_emulation_helpers {
|
||||
|
||||
template<class T>
|
||||
class mutex_traits;
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!\file
|
||||
//!Describes a mutex class that can be placed in memory shared by
|
||||
//!several processes.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
class interprocess_condition;
|
||||
|
||||
//!Wraps a interprocess_mutex that can be placed in shared memory and can be
|
||||
//!shared between processes. Allows timed lock tries
|
||||
class interprocess_mutex
|
||||
{
|
||||
/// @cond
|
||||
//Non-copyable
|
||||
interprocess_mutex(const interprocess_mutex &);
|
||||
interprocess_mutex &operator=(const interprocess_mutex &);
|
||||
friend class interprocess_condition;
|
||||
|
||||
public:
|
||||
#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
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
|
||||
|
||||
/// @endcond
|
||||
public:
|
||||
|
||||
//!Constructor.
|
||||
//!Throws interprocess_exception on error.
|
||||
interprocess_mutex();
|
||||
|
||||
//!Destructor. If any process uses the mutex after the destructor is called
|
||||
//!the result is undefined. Does not throw.
|
||||
~interprocess_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.
|
||||
void lock();
|
||||
|
||||
//!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.
|
||||
bool try_lock();
|
||||
|
||||
//!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
|
||||
//! number of times it is locked.
|
||||
//!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);
|
||||
|
||||
//!Effects: The calling thread releases the exclusive ownership of the mutex.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void unlock();
|
||||
|
||||
/// @cond
|
||||
internal_mutex_type &internal_mutex()
|
||||
{ return m_mutex; }
|
||||
|
||||
const internal_mutex_type &internal_mutex() const
|
||||
{ return m_mutex; }
|
||||
|
||||
private:
|
||||
internal_mutex_type m_mutex;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
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
|
||||
= boost::posix_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
|
||||
}
|
||||
|
||||
inline bool interprocess_mutex::try_lock()
|
||||
{ return m_mutex.try_lock(); }
|
||||
|
||||
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return m_mutex.timed_lock(abs_time); }
|
||||
|
||||
inline void interprocess_mutex::unlock()
|
||||
{ m_mutex.unlock(); }
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MUTEX_HPP
|
@ -0,0 +1,177 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
|
||||
|
||||
/// @cond
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#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...
|
||||
#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
#include <boost/interprocess/sync/windows/recursive_mutex.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_WINDOWS
|
||||
#elif !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
|
||||
#define BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
#endif
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
namespace robust_emulation_helpers {
|
||||
|
||||
template<class T>
|
||||
class mutex_traits;
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!\file
|
||||
//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!Wraps a interprocess_mutex that can be placed in shared memory and can be
|
||||
//!shared between processes. Allows several locking calls by the same
|
||||
//!process. Allows timed lock tries
|
||||
class interprocess_recursive_mutex
|
||||
{
|
||||
/// @cond
|
||||
//Non-copyable
|
||||
interprocess_recursive_mutex(const interprocess_recursive_mutex &);
|
||||
interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &);
|
||||
/// @endcond
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Throws interprocess_exception on error.
|
||||
interprocess_recursive_mutex();
|
||||
|
||||
//!Destructor. If any process uses the mutex after the destructor is called
|
||||
//!the result is undefined. Does not throw.
|
||||
~interprocess_recursive_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. The mutex must be unlocked
|
||||
//! the same number of times it is locked.
|
||||
//!Throws: interprocess_exception on error.
|
||||
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
|
||||
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);
|
||||
|
||||
//!Effects: The calling thread releases the exclusive ownership of the mutex.
|
||||
//! If the mutex supports recursive locking, the mutex must be unlocked the
|
||||
//! same number of times it is locked.
|
||||
//!Throws: interprocess_exception on error.
|
||||
void unlock();
|
||||
/// @cond
|
||||
private:
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION)
|
||||
#undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION
|
||||
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
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
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
|
||||
= boost::posix_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
|
||||
}
|
||||
|
||||
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)
|
||||
{ return mutex.timed_lock(abs_time); }
|
||||
|
||||
inline void interprocess_recursive_mutex::unlock()
|
||||
{ mutex.unlock(); }
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user