Imported existing code
This commit is contained in:
@@ -0,0 +1,465 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_ADAPTIVE_POOL_HPP
|
||||
#define BOOST_INTERPROCESS_ADAPTIVE_POOL_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/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
//!Describes adaptive_pool pooled shared memory STL compatible allocator
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail{
|
||||
|
||||
template < unsigned int Version
|
||||
, class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, unsigned char OverheadPercent
|
||||
>
|
||||
class adaptive_pool_base
|
||||
: public node_pool_allocation_impl
|
||||
< adaptive_pool_base
|
||||
< Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
|
||||
, Version
|
||||
, T
|
||||
, SegmentManager
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
typedef SegmentManager segment_manager;
|
||||
typedef adaptive_pool_base
|
||||
<Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> self_t;
|
||||
|
||||
/// @cond
|
||||
|
||||
template <int dummy>
|
||||
struct node_pool
|
||||
{
|
||||
typedef detail::shared_adaptive_node_pool
|
||||
< SegmentManager, sizeof_value<T>::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type;
|
||||
|
||||
static type *get(void *p)
|
||||
{ return static_cast<type*>(p); }
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
BOOST_STATIC_ASSERT((Version <=2));
|
||||
|
||||
public:
|
||||
//-------
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, T>::type pointer;
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::interprocess::version_type<adaptive_pool_base, Version> version;
|
||||
typedef detail::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
|
||||
//!Obtains adaptive_pool_base from
|
||||
//!adaptive_pool_base
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
//!Not assignable from related adaptive_pool_base
|
||||
template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2>
|
||||
adaptive_pool_base& operator=
|
||||
(const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
adaptive_pool_base(segment_manager *segment_mngr)
|
||||
: mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
|
||||
|
||||
//!Copy constructor from other adaptive_pool_base. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
adaptive_pool_base(const adaptive_pool_base &other)
|
||||
: mp_node_pool(other.get_node_pool())
|
||||
{
|
||||
node_pool<0>::get(detail::get_pointer(mp_node_pool))->inc_ref_count();
|
||||
}
|
||||
|
||||
//!Assignment from other adaptive_pool_base
|
||||
adaptive_pool_base& operator=(const adaptive_pool_base &other)
|
||||
{
|
||||
adaptive_pool_base c(other);
|
||||
swap(*this, c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Copy constructor from related 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>
|
||||
adaptive_pool_base
|
||||
(const adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~adaptive_pool_base()
|
||||
{ detail::destroy_node_pool_if_last_link(node_pool<0>::get(detail::get_pointer(mp_node_pool))); }
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
void* get_node_pool() const
|
||||
{ return detail::get_pointer(mp_node_pool); }
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const
|
||||
{ return node_pool<0>::get(detail::get_pointer(mp_node_pool))->get_segment_manager(); }
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2)
|
||||
{ detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
void_pointer mp_node_pool;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!Equality test for same type
|
||||
//!of adaptive_pool_base
|
||||
template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
|
||||
bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
|
||||
const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
|
||||
{ return alloc1.get_node_pool() == alloc2.get_node_pool(); }
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of adaptive_pool_base
|
||||
template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
|
||||
bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
|
||||
const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
|
||||
{ return alloc1.get_node_pool() != alloc2.get_node_pool(); }
|
||||
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock = 64
|
||||
, std::size_t MaxFreeBlocks = 2
|
||||
, unsigned char OverheadPercent = 5
|
||||
>
|
||||
class adaptive_pool_v1
|
||||
: public adaptive_pool_base
|
||||
< 1
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef detail::adaptive_pool_base
|
||||
< 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
adaptive_pool_v1(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
adaptive_pool_v1
|
||||
(const adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail{
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!An STL node 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...
|
||||
//!
|
||||
//!This node allocator shares a segregated storage between all instances
|
||||
//!of adaptive_pool with equal sizeof(T) placed in the same segment
|
||||
//!group. NodesPerBlock is the number of nodes allocated at once when the allocator
|
||||
//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
|
||||
//!that the adaptive node pool will hold. The rest of the totally free blocks will be
|
||||
//!deallocated with the segment manager.
|
||||
//!
|
||||
//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
|
||||
//!(memory usable for nodes / total memory allocated from the segment manager)
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, unsigned char OverheadPercent
|
||||
>
|
||||
class adaptive_pool
|
||||
/// @cond
|
||||
: public detail::adaptive_pool_base
|
||||
< 2
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
/// @endcond
|
||||
{
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
typedef detail::adaptive_pool_base
|
||||
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
|
||||
public:
|
||||
typedef boost::interprocess::version_type<adaptive_pool, 2> version;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
adaptive_pool(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
adaptive_pool
|
||||
(const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
#else //BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
typedef implementation_defined::segment_manager segment_manager;
|
||||
typedef segment_manager::void_pointer void_pointer;
|
||||
typedef implementation_defined::pointer pointer;
|
||||
typedef implementation_defined::const_pointer const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
//!Obtains adaptive_pool from
|
||||
//!adaptive_pool
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from
|
||||
//!related adaptive_pool
|
||||
template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
|
||||
adaptive_pool& operator=
|
||||
(const adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
|
||||
|
||||
//!Not assignable from
|
||||
//!other adaptive_pool
|
||||
//adaptive_pool& operator=(const adaptive_pool&);
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
adaptive_pool(segment_manager *segment_mngr);
|
||||
|
||||
//!Copy constructor from other adaptive_pool. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
adaptive_pool(const adaptive_pool &other);
|
||||
|
||||
//!Copy constructor from related adaptive_pool. 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>
|
||||
adaptive_pool
|
||||
(const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~adaptive_pool();
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
void* get_node_pool() const;
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const;
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const;
|
||||
|
||||
//!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);
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count);
|
||||
|
||||
//!Deallocates all free blocks
|
||||
//!of the pool
|
||||
void deallocate_free_blocks();
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2);
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const;
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//!Copy construct an object.
|
||||
//!Throws if T's copy constructor throws
|
||||
void construct(const pointer &ptr, const_reference v);
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr);
|
||||
|
||||
//!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;
|
||||
|
||||
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);
|
||||
|
||||
//!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(...)
|
||||
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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();
|
||||
|
||||
//!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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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 it);
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Equality test for same type
|
||||
//!of adaptive_pool
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of adaptive_pool
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
|
||||
|
||||
304
libraries/include/boost/interprocess/allocators/allocator.hpp
Normal file
304
libraries/include/boost/interprocess/allocators/allocator.hpp
Normal file
@@ -0,0 +1,304 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/containers/allocation_type.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 <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::pointer_to_other
|
||||
<aux_pointer_t, const void>::type cvoid_ptr;
|
||||
|
||||
//Pointer to the allocator
|
||||
typedef typename boost::pointer_to_other
|
||||
<cvoid_ptr, 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::pointer_to_other
|
||||
<cvoid_ptr, T>::type pointer;
|
||||
typedef typename boost::
|
||||
pointer_to_other<pointer, const T>::type const_pointer;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::interprocess::version_type<allocator, 2> version;
|
||||
|
||||
/// @cond
|
||||
|
||||
//Experimental. Don't use.
|
||||
typedef boost::interprocess::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 detail::get_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(count > this->max_size())
|
||||
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*)detail::get_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)
|
||||
{ detail::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(detail::get_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, detail::get_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(...)
|
||||
multiallocation_chain allocate_many
|
||||
(size_type elem_size, std::size_t num_elements)
|
||||
{
|
||||
return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements));
|
||||
}
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many
|
||||
(const size_type *elem_sizes, size_type n_elements)
|
||||
{
|
||||
multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
|
||||
}
|
||||
|
||||
//!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)
|
||||
{
|
||||
return mp_mngr->deallocate_many(chain.extract_multiallocation_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().
|
||||
multiallocation_chain allocate_individual
|
||||
(std::size_t num_elements)
|
||||
{ return this->allocate_many(1, num_elements); }
|
||||
|
||||
//!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)
|
||||
{ return this->deallocate_many(boost::interprocess::move(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)); }
|
||||
|
||||
//!Copy construct an object
|
||||
//!Throws if T's copy constructor throws
|
||||
void construct(const pointer &ptr, const_reference v)
|
||||
{ new((void*)detail::get_pointer(ptr)) value_type(v); }
|
||||
|
||||
//!Default construct an object.
|
||||
//!Throws if T's default constructor throws
|
||||
void construct(const pointer &ptr)
|
||||
{ new((void*)detail::get_pointer(ptr)) value_type; }
|
||||
|
||||
//!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> >
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_ALLOCATOR_HPP
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CACHED_ADAPTIVE_POOL_HPP
|
||||
#define BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_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/allocators/detail/adaptive_node_pool.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/containers/version_type.hpp>
|
||||
#include <boost/interprocess/allocators/detail/node_tools.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail {
|
||||
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock = 64
|
||||
, std::size_t MaxFreeBlocks = 2
|
||||
, unsigned char OverheadPercent = 5
|
||||
>
|
||||
class cached_adaptive_pool_v1
|
||||
: public detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_adaptive_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
, 1>
|
||||
{
|
||||
public:
|
||||
typedef detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_adaptive_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
, 1> base_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef cached_adaptive_pool_v1
|
||||
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
cached_adaptive_pool_v1(SegmentManager *segment_mngr,
|
||||
std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_adaptive_pool_v1
|
||||
(const cached_adaptive_pool_v1
|
||||
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail{
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!An STL node 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...
|
||||
//!
|
||||
//!This node allocator shares a segregated storage between all instances of
|
||||
//!cached_adaptive_pool with equal sizeof(T) placed in the same
|
||||
//!memory segment. But also caches some nodes privately to
|
||||
//!avoid some synchronization overhead.
|
||||
//!
|
||||
//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when
|
||||
//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
|
||||
//!that the adaptive node pool will hold. The rest of the totally free blocks will be
|
||||
//!deallocated with the segment manager.
|
||||
//!
|
||||
//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
|
||||
//!(memory usable for nodes / total memory allocated from the segment manager)
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, unsigned char OverheadPercent
|
||||
>
|
||||
class cached_adaptive_pool
|
||||
/// @cond
|
||||
: public detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_adaptive_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
, 2>
|
||||
/// @endcond
|
||||
{
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
typedef detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_adaptive_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
, 2> base_t;
|
||||
|
||||
public:
|
||||
typedef boost::interprocess::version_type<cached_adaptive_pool, 2> version;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef cached_adaptive_pool
|
||||
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
cached_adaptive_pool(SegmentManager *segment_mngr,
|
||||
std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_adaptive_pool
|
||||
(const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
#else
|
||||
public:
|
||||
typedef implementation_defined::segment_manager segment_manager;
|
||||
typedef segment_manager::void_pointer void_pointer;
|
||||
typedef implementation_defined::pointer pointer;
|
||||
typedef implementation_defined::const_pointer const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
//!Obtains cached_adaptive_pool from
|
||||
//!cached_adaptive_pool
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from
|
||||
//!related cached_adaptive_pool
|
||||
template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
|
||||
cached_adaptive_pool& operator=
|
||||
(const cached_adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
|
||||
|
||||
//!Not assignable from
|
||||
//!other cached_adaptive_pool
|
||||
cached_adaptive_pool& operator=(const cached_adaptive_pool&);
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
cached_adaptive_pool(segment_manager *segment_mngr);
|
||||
|
||||
//!Copy constructor from other cached_adaptive_pool. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
cached_adaptive_pool(const cached_adaptive_pool &other);
|
||||
|
||||
//!Copy constructor from related cached_adaptive_pool. 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>
|
||||
cached_adaptive_pool
|
||||
(const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~cached_adaptive_pool();
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
node_pool_t* get_node_pool() const;
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const;
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const;
|
||||
|
||||
//!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);
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count);
|
||||
|
||||
//!Deallocates all free blocks
|
||||
//!of the pool
|
||||
void deallocate_free_blocks();
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2);
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const;
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//!Copy construct an object.
|
||||
//!Throws if T's copy constructor throws
|
||||
void construct(const pointer &ptr, const_reference v);
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr);
|
||||
|
||||
//!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;
|
||||
|
||||
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);
|
||||
|
||||
//!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(...)
|
||||
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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();
|
||||
|
||||
//!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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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);
|
||||
//!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(std::size_t newmax);
|
||||
|
||||
//!Returns the max cached nodes parameter.
|
||||
//!Never throws
|
||||
std::size_t get_max_cached_nodes() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Equality test for same type
|
||||
//!of cached_adaptive_pool
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline
|
||||
bool operator==(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of cached_adaptive_pool
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline
|
||||
bool operator!=(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CACHED_NODE_ALLOCATOR_HPP
|
||||
#define BOOST_INTERPROCESS_CACHED_NODE_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/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/allocators/detail/node_pool.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/containers/version_type.hpp>
|
||||
#include <boost/interprocess/allocators/detail/node_tools.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail {
|
||||
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock = 64
|
||||
>
|
||||
class cached_node_allocator_v1
|
||||
: public detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
>
|
||||
, 1>
|
||||
{
|
||||
public:
|
||||
typedef detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
>
|
||||
, 1> base_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef cached_node_allocator_v1
|
||||
<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
cached_node_allocator_v1(SegmentManager *segment_mngr,
|
||||
std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_node_allocator_v1
|
||||
(const cached_node_allocator_v1
|
||||
<T2, SegmentManager, NodesPerBlock> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail{
|
||||
|
||||
/// @endcond
|
||||
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
>
|
||||
class cached_node_allocator
|
||||
/// @cond
|
||||
: public detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
>
|
||||
, 2>
|
||||
/// @endcond
|
||||
{
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
typedef detail::cached_allocator_impl
|
||||
< T
|
||||
, detail::shared_node_pool
|
||||
< SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
>
|
||||
, 2> base_t;
|
||||
|
||||
public:
|
||||
typedef boost::interprocess::version_type<cached_node_allocator, 2> version;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef cached_node_allocator<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
cached_node_allocator(SegmentManager *segment_mngr,
|
||||
std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
|
||||
: base_t(segment_mngr, max_cached_nodes)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
cached_node_allocator
|
||||
(const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
#else
|
||||
public:
|
||||
typedef implementation_defined::segment_manager segment_manager;
|
||||
typedef segment_manager::void_pointer void_pointer;
|
||||
typedef implementation_defined::pointer pointer;
|
||||
typedef implementation_defined::const_pointer const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
//!Obtains cached_node_allocator from
|
||||
//!cached_node_allocator
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef cached_node_allocator<T2, SegmentManager> other;
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from
|
||||
//!related cached_node_allocator
|
||||
template<class T2, class SegmentManager2, std::size_t N2>
|
||||
cached_node_allocator& operator=
|
||||
(const cached_node_allocator<T2, SegmentManager2, N2>&);
|
||||
|
||||
//!Not assignable from
|
||||
//!other cached_node_allocator
|
||||
cached_node_allocator& operator=(const cached_node_allocator&);
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
cached_node_allocator(segment_manager *segment_mngr);
|
||||
|
||||
//!Copy constructor from other cached_node_allocator. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
cached_node_allocator(const cached_node_allocator &other);
|
||||
|
||||
//!Copy constructor from related cached_node_allocator. 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>
|
||||
cached_node_allocator
|
||||
(const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &other);
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~cached_node_allocator();
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
node_pool_t* get_node_pool() const;
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const;
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const;
|
||||
|
||||
//!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);
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count);
|
||||
|
||||
//!Deallocates all free blocks
|
||||
//!of the pool
|
||||
void deallocate_free_blocks();
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2);
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const;
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//!Default construct an object.
|
||||
//!Throws if T's default constructor throws
|
||||
void construct(const pointer &ptr, const_reference v);
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr);
|
||||
|
||||
//!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;
|
||||
|
||||
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);
|
||||
|
||||
//!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(...)
|
||||
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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();
|
||||
|
||||
//!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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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 it);
|
||||
//!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(std::size_t newmax);
|
||||
|
||||
//!Returns the max cached nodes parameter.
|
||||
//!Never throws
|
||||
std::size_t get_max_cached_nodes() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Equality test for same type
|
||||
//!of cached_node_allocator
|
||||
template<class T, class S, std::size_t NPC> inline
|
||||
bool operator==(const cached_node_allocator<T, S, NPC> &alloc1,
|
||||
const cached_node_allocator<T, S, NPC> &alloc2);
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of cached_node_allocator
|
||||
template<class T, class S, std::size_t NPC> inline
|
||||
bool operator!=(const cached_node_allocator<T, S, NPC> &alloc1,
|
||||
const cached_node_allocator<T, S, NPC> &alloc2);
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
|
||||
|
||||
@@ -0,0 +1,639 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_ADAPTIVE_NODE_POOL_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_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/pointer_to_other.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/min_max.hpp>
|
||||
#include <boost/interprocess/detail/math_functions.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/math/common_factor_ct.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
|
||||
#include <boost/interprocess/allocators/detail/node_tools.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <cassert>
|
||||
|
||||
//!\file
|
||||
//!Describes the real adaptive pool shared by many Interprocess pool allocators
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
template<class SegmentManagerBase>
|
||||
class private_adaptive_node_pool_impl
|
||||
{
|
||||
//Non-copyable
|
||||
private_adaptive_node_pool_impl();
|
||||
private_adaptive_node_pool_impl(const private_adaptive_node_pool_impl &);
|
||||
private_adaptive_node_pool_impl &operator=(const private_adaptive_node_pool_impl &);
|
||||
|
||||
typedef typename SegmentManagerBase::void_pointer void_pointer;
|
||||
static const std::size_t PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
|
||||
public:
|
||||
typedef typename node_slist<void_pointer>::node_t node_t;
|
||||
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
|
||||
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
|
||||
|
||||
private:
|
||||
typedef typename bi::make_set_base_hook
|
||||
< bi::void_pointer<void_pointer>
|
||||
, bi::optimize_size<true>
|
||||
, bi::constant_time_size<false>
|
||||
, bi::link_mode<bi::normal_link> >::type multiset_hook_t;
|
||||
|
||||
struct hdr_offset_holder
|
||||
{
|
||||
hdr_offset_holder(std::size_t offset = 0)
|
||||
: hdr_offset(offset)
|
||||
{}
|
||||
std::size_t hdr_offset;
|
||||
};
|
||||
|
||||
struct block_info_t
|
||||
:
|
||||
public hdr_offset_holder,
|
||||
public multiset_hook_t
|
||||
{
|
||||
//An intrusive list of free node from this block
|
||||
free_nodes_t free_nodes;
|
||||
friend bool operator <(const block_info_t &l, const block_info_t &r)
|
||||
{
|
||||
// { return l.free_nodes.size() < r.free_nodes.size(); }
|
||||
//Let's order blocks first by free nodes and then by address
|
||||
//so that highest address fully free blocks are deallocated.
|
||||
//This improves returning memory to the OS (trimming).
|
||||
const bool is_less = l.free_nodes.size() < r.free_nodes.size();
|
||||
const bool is_equal = l.free_nodes.size() == r.free_nodes.size();
|
||||
return is_less || (is_equal && (&l < &r));
|
||||
}
|
||||
};
|
||||
typedef typename bi::make_multiset
|
||||
<block_info_t, bi::base_hook<multiset_hook_t> >::type block_multiset_t;
|
||||
typedef typename block_multiset_t::iterator block_iterator;
|
||||
|
||||
static const std::size_t MaxAlign = alignment_of<node_t>::value;
|
||||
static const std::size_t HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign;
|
||||
static const std::size_t HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign;
|
||||
static std::size_t calculate_alignment
|
||||
(std::size_t overhead_percent, std::size_t real_node_size)
|
||||
{
|
||||
//to-do: handle real_node_size != node_size
|
||||
const std::size_t divisor = overhead_percent*real_node_size;
|
||||
const std::size_t dividend = HdrOffsetSize*100;
|
||||
std::size_t elements_per_subblock = (dividend - 1)/divisor + 1;
|
||||
std::size_t candidate_power_of_2 =
|
||||
upper_power_of_2(elements_per_subblock*real_node_size + HdrOffsetSize);
|
||||
bool overhead_satisfied = false;
|
||||
//Now calculate the wors-case overhead for a subblock
|
||||
const std::size_t max_subblock_overhead = HdrSize + PayloadPerAllocation;
|
||||
while(!overhead_satisfied){
|
||||
elements_per_subblock = (candidate_power_of_2 - max_subblock_overhead)/real_node_size;
|
||||
const std::size_t overhead_size = candidate_power_of_2 - elements_per_subblock*real_node_size;
|
||||
if(overhead_size*100/candidate_power_of_2 < overhead_percent){
|
||||
overhead_satisfied = true;
|
||||
}
|
||||
else{
|
||||
candidate_power_of_2 <<= 1;
|
||||
}
|
||||
}
|
||||
return candidate_power_of_2;
|
||||
}
|
||||
|
||||
static void calculate_num_subblocks
|
||||
(std::size_t alignment, std::size_t real_node_size, std::size_t elements_per_block
|
||||
,std::size_t &num_subblocks, std::size_t &real_num_node, std::size_t overhead_percent)
|
||||
{
|
||||
std::size_t elements_per_subblock = (alignment - HdrOffsetSize)/real_node_size;
|
||||
std::size_t possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1;
|
||||
std::size_t hdr_subblock_elements = (alignment - HdrSize - PayloadPerAllocation)/real_node_size;
|
||||
while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){
|
||||
++possible_num_subblock;
|
||||
}
|
||||
elements_per_subblock = (alignment - HdrOffsetSize)/real_node_size;
|
||||
bool overhead_satisfied = false;
|
||||
while(!overhead_satisfied){
|
||||
const std::size_t total_data = (elements_per_subblock*(possible_num_subblock-1) + hdr_subblock_elements)*real_node_size;
|
||||
const std::size_t total_size = alignment*possible_num_subblock;
|
||||
if((total_size - total_data)*100/total_size < overhead_percent){
|
||||
overhead_satisfied = true;
|
||||
}
|
||||
else{
|
||||
++possible_num_subblock;
|
||||
}
|
||||
}
|
||||
num_subblocks = possible_num_subblock;
|
||||
real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements;
|
||||
}
|
||||
|
||||
public:
|
||||
//!Segment manager typedef
|
||||
typedef SegmentManagerBase segment_manager_base_type;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
private_adaptive_node_pool_impl
|
||||
( segment_manager_base_type *segment_mngr_base, std::size_t node_size
|
||||
, std::size_t nodes_per_block, std::size_t max_free_blocks
|
||||
, unsigned char overhead_percent
|
||||
)
|
||||
: m_max_free_blocks(max_free_blocks)
|
||||
, m_real_node_size(lcm(node_size, std::size_t(alignment_of<node_t>::value)))
|
||||
//Round the size to a power of two value.
|
||||
//This is the total memory size (including payload) that we want to
|
||||
//allocate from the general-purpose allocator
|
||||
, m_real_block_alignment(calculate_alignment(overhead_percent, m_real_node_size))
|
||||
//This is the real number of nodes per block
|
||||
, m_num_subblocks(0)
|
||||
, m_real_num_node(0)
|
||||
//General purpose allocator
|
||||
, mp_segment_mngr_base(segment_mngr_base)
|
||||
, m_block_multiset()
|
||||
, m_totally_free_blocks(0)
|
||||
{
|
||||
calculate_num_subblocks(m_real_block_alignment, m_real_node_size, nodes_per_block, m_num_subblocks, m_real_num_node, overhead_percent);
|
||||
}
|
||||
|
||||
//!Destructor. Deallocates all allocated blocks. Never throws
|
||||
~private_adaptive_node_pool_impl()
|
||||
{ priv_clear(); }
|
||||
|
||||
std::size_t get_real_num_node() const
|
||||
{ return m_real_num_node; }
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager_base_type* get_segment_manager_base()const
|
||||
{ return detail::get_pointer(mp_segment_mngr_base); }
|
||||
|
||||
//!Allocates array of count elements. Can throw boost::interprocess::bad_alloc
|
||||
void *allocate_node()
|
||||
{
|
||||
priv_invariants();
|
||||
//If there are no free nodes we allocate a new block
|
||||
if (m_block_multiset.empty()){
|
||||
priv_alloc_block(1);
|
||||
}
|
||||
//We take the first free node the multiset can't be empty
|
||||
return priv_take_first_node();
|
||||
}
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
void deallocate_node(void *pElem)
|
||||
{
|
||||
multiallocation_chain chain;
|
||||
chain.push_front(void_pointer(pElem));
|
||||
this->priv_reinsert_nodes_in_block(chain, 1);
|
||||
//Update free block count
|
||||
if(m_totally_free_blocks > m_max_free_blocks){
|
||||
this->priv_deallocate_free_blocks(m_max_free_blocks);
|
||||
}
|
||||
priv_invariants();
|
||||
}
|
||||
|
||||
//!Allocates n nodes.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
multiallocation_chain allocate_nodes(const std::size_t n)
|
||||
{
|
||||
multiallocation_chain chain;
|
||||
std::size_t i = 0;
|
||||
try{
|
||||
priv_invariants();
|
||||
while(i != n){
|
||||
//If there are no free nodes we allocate all needed blocks
|
||||
if (m_block_multiset.empty()){
|
||||
priv_alloc_block(((n - i) - 1)/m_real_num_node + 1);
|
||||
}
|
||||
free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes;
|
||||
const std::size_t free_nodes_count_before = free_nodes.size();
|
||||
if(free_nodes_count_before == m_real_num_node){
|
||||
--m_totally_free_blocks;
|
||||
}
|
||||
const std::size_t num_elems = ((n-i) < free_nodes_count_before) ? (n-i) : free_nodes_count_before;
|
||||
for(std::size_t j = 0; j != num_elems; ++j){
|
||||
void *new_node = &free_nodes.front();
|
||||
free_nodes.pop_front();
|
||||
chain.push_back(new_node);
|
||||
}
|
||||
|
||||
if(free_nodes.empty()){
|
||||
m_block_multiset.erase(m_block_multiset.begin());
|
||||
}
|
||||
i += num_elems;
|
||||
}
|
||||
}
|
||||
catch(...){
|
||||
this->deallocate_nodes(chain, i);
|
||||
throw;
|
||||
}
|
||||
priv_invariants();
|
||||
return boost::interprocess::move(chain);
|
||||
}
|
||||
|
||||
//!Deallocates a linked list of nodes. Never throws
|
||||
void deallocate_nodes(multiallocation_chain nodes)
|
||||
{
|
||||
return deallocate_nodes(nodes, nodes.size());
|
||||
}
|
||||
|
||||
//!Deallocates the first n nodes of a linked list of nodes. Never throws
|
||||
void deallocate_nodes(multiallocation_chain &nodes, std::size_t n)
|
||||
{
|
||||
this->priv_reinsert_nodes_in_block(nodes, n);
|
||||
if(m_totally_free_blocks > m_max_free_blocks){
|
||||
this->priv_deallocate_free_blocks(m_max_free_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate_free_blocks()
|
||||
{ this->priv_deallocate_free_blocks(0); }
|
||||
|
||||
std::size_t num_free_nodes()
|
||||
{
|
||||
typedef typename block_multiset_t::const_iterator citerator;
|
||||
std::size_t count = 0;
|
||||
citerator it (m_block_multiset.begin()), itend(m_block_multiset.end());
|
||||
for(; it != itend; ++it){
|
||||
count += it->free_nodes.size();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void swap(private_adaptive_node_pool_impl &other)
|
||||
{
|
||||
assert(m_max_free_blocks == other.m_max_free_blocks);
|
||||
assert(m_real_node_size == other.m_real_node_size);
|
||||
assert(m_real_block_alignment == other.m_real_block_alignment);
|
||||
assert(m_real_num_node == other.m_real_num_node);
|
||||
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
|
||||
std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
|
||||
m_block_multiset.swap(other.m_block_multiset);
|
||||
}
|
||||
|
||||
//Deprecated, use deallocate_free_blocks
|
||||
void deallocate_free_chunks()
|
||||
{ this->priv_deallocate_free_blocks(0); }
|
||||
|
||||
private:
|
||||
void priv_deallocate_free_blocks(std::size_t max_free_blocks)
|
||||
{
|
||||
priv_invariants();
|
||||
//Now check if we've reached the free nodes limit
|
||||
//and check if we have free blocks. If so, deallocate as much
|
||||
//as we can to stay below the limit
|
||||
for( block_iterator itend = m_block_multiset.end()
|
||||
; m_totally_free_blocks > max_free_blocks
|
||||
; --m_totally_free_blocks
|
||||
){
|
||||
assert(!m_block_multiset.empty());
|
||||
block_iterator it = itend;
|
||||
--it;
|
||||
std::size_t num_nodes = it->free_nodes.size();
|
||||
assert(num_nodes == m_real_num_node);
|
||||
(void)num_nodes;
|
||||
m_block_multiset.erase_and_dispose
|
||||
(it, block_destroyer(this));
|
||||
}
|
||||
}
|
||||
|
||||
void priv_reinsert_nodes_in_block(multiallocation_chain &chain, std::size_t n)
|
||||
{
|
||||
block_iterator block_it(m_block_multiset.end());
|
||||
while(n--){
|
||||
void *pElem = detail::get_pointer(chain.front());
|
||||
chain.pop_front();
|
||||
priv_invariants();
|
||||
block_info_t *block_info = this->priv_block_from_node(pElem);
|
||||
assert(block_info->free_nodes.size() < m_real_num_node);
|
||||
//We put the node at the beginning of the free node list
|
||||
node_t * to_deallocate = static_cast<node_t*>(pElem);
|
||||
block_info->free_nodes.push_front(*to_deallocate);
|
||||
|
||||
block_iterator this_block(block_multiset_t::s_iterator_to(*block_info));
|
||||
block_iterator next_block(this_block);
|
||||
++next_block;
|
||||
|
||||
//Cache the free nodes from the block
|
||||
std::size_t this_block_free_nodes = this_block->free_nodes.size();
|
||||
|
||||
if(this_block_free_nodes == 1){
|
||||
m_block_multiset.insert(m_block_multiset.begin(), *block_info);
|
||||
}
|
||||
else{
|
||||
block_iterator next_block(this_block);
|
||||
++next_block;
|
||||
if(next_block != block_it){
|
||||
std::size_t next_free_nodes = next_block->free_nodes.size();
|
||||
if(this_block_free_nodes > next_free_nodes){
|
||||
//Now move the block to the new position
|
||||
m_block_multiset.erase(this_block);
|
||||
m_block_multiset.insert(*block_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Update free block count
|
||||
if(this_block_free_nodes == m_real_num_node){
|
||||
++m_totally_free_blocks;
|
||||
}
|
||||
priv_invariants();
|
||||
}
|
||||
}
|
||||
|
||||
node_t *priv_take_first_node()
|
||||
{
|
||||
assert(m_block_multiset.begin() != m_block_multiset.end());
|
||||
//We take the first free node the multiset can't be empty
|
||||
free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes;
|
||||
node_t *first_node = &free_nodes.front();
|
||||
const std::size_t free_nodes_count = free_nodes.size();
|
||||
assert(0 != free_nodes_count);
|
||||
free_nodes.pop_front();
|
||||
if(free_nodes_count == 1){
|
||||
m_block_multiset.erase(m_block_multiset.begin());
|
||||
}
|
||||
else if(free_nodes_count == m_real_num_node){
|
||||
--m_totally_free_blocks;
|
||||
}
|
||||
priv_invariants();
|
||||
return first_node;
|
||||
}
|
||||
|
||||
class block_destroyer;
|
||||
friend class block_destroyer;
|
||||
|
||||
class block_destroyer
|
||||
{
|
||||
public:
|
||||
block_destroyer(const private_adaptive_node_pool_impl *impl)
|
||||
: mp_impl(impl)
|
||||
{}
|
||||
|
||||
void operator()(typename block_multiset_t::pointer to_deallocate)
|
||||
{
|
||||
std::size_t free_nodes = to_deallocate->free_nodes.size();
|
||||
(void)free_nodes;
|
||||
assert(free_nodes == mp_impl->m_real_num_node);
|
||||
assert(0 == to_deallocate->hdr_offset);
|
||||
hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block(detail::get_pointer(to_deallocate));
|
||||
mp_impl->mp_segment_mngr_base->deallocate(hdr_off_holder);
|
||||
}
|
||||
const private_adaptive_node_pool_impl *mp_impl;
|
||||
};
|
||||
|
||||
//This macro will activate invariant checking. Slow, but helpful for debugging the code.
|
||||
//#define BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
|
||||
void priv_invariants()
|
||||
#ifdef BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
|
||||
#undef BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
|
||||
{
|
||||
//We iterate through the block list to free the memory
|
||||
block_iterator it(m_block_multiset.begin()),
|
||||
itend(m_block_multiset.end()), to_deallocate;
|
||||
if(it != itend){
|
||||
for(++it; it != itend; ++it){
|
||||
block_iterator prev(it);
|
||||
--prev;
|
||||
std::size_t sp = prev->free_nodes.size(),
|
||||
si = it->free_nodes.size();
|
||||
assert(sp <= si);
|
||||
(void)sp; (void)si;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
//Check that the total free nodes are correct
|
||||
it = m_block_multiset.begin();
|
||||
itend = m_block_multiset.end();
|
||||
std::size_t total_free_nodes = 0;
|
||||
for(; it != itend; ++it){
|
||||
total_free_nodes += it->free_nodes.size();
|
||||
}
|
||||
assert(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
|
||||
}
|
||||
|
||||
{
|
||||
//Check that the total totally free blocks are correct
|
||||
it = m_block_multiset.begin();
|
||||
itend = m_block_multiset.end();
|
||||
std::size_t total_free_blocks = 0;
|
||||
for(; it != itend; ++it){
|
||||
total_free_blocks += (it->free_nodes.size() == m_real_num_node);
|
||||
}
|
||||
assert(total_free_blocks == m_totally_free_blocks);
|
||||
}
|
||||
{
|
||||
//Check that header offsets are correct
|
||||
it = m_block_multiset.begin();
|
||||
for(; it != itend; ++it){
|
||||
hdr_offset_holder *hdr_off_holder = priv_first_subblock_from_block(&*it);
|
||||
for(std::size_t i = 0, max = m_num_subblocks; i < max; ++i){
|
||||
assert(hdr_off_holder->hdr_offset == std::size_t(reinterpret_cast<char*>(&*it)- reinterpret_cast<char*>(hdr_off_holder)));
|
||||
assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
|
||||
assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
|
||||
hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{} //empty
|
||||
#endif
|
||||
|
||||
//!Deallocates all used memory. Never throws
|
||||
void priv_clear()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
block_iterator it = m_block_multiset.begin();
|
||||
block_iterator itend = m_block_multiset.end();
|
||||
std::size_t num_free_nodes = 0;
|
||||
for(; it != itend; ++it){
|
||||
//Check for memory leak
|
||||
std::size_t n = (std::size_t)it->free_nodes.size(); (void)n;
|
||||
assert(it->free_nodes.size() == m_real_num_node);
|
||||
++num_free_nodes;
|
||||
}
|
||||
assert(num_free_nodes == m_totally_free_blocks);
|
||||
#endif
|
||||
priv_invariants();
|
||||
m_block_multiset.clear_and_dispose
|
||||
(block_destroyer(this));
|
||||
m_totally_free_blocks = 0;
|
||||
}
|
||||
|
||||
block_info_t *priv_block_from_node(void *node) const
|
||||
{
|
||||
hdr_offset_holder *hdr_off_holder =
|
||||
reinterpret_cast<hdr_offset_holder*>((std::size_t)node & std::size_t(~(m_real_block_alignment - 1)));
|
||||
assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
|
||||
assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
|
||||
block_info_t *block = reinterpret_cast<block_info_t *>
|
||||
(reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
|
||||
assert(block->hdr_offset == 0);
|
||||
return block;
|
||||
}
|
||||
|
||||
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
|
||||
{
|
||||
hdr_offset_holder *hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
|
||||
(reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_real_block_alignment);
|
||||
assert(hdr_off_holder->hdr_offset == std::size_t(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
|
||||
assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
|
||||
assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
|
||||
return hdr_off_holder;
|
||||
}
|
||||
|
||||
//!Allocates a several blocks of nodes. Can throw boost::interprocess::bad_alloc
|
||||
void priv_alloc_block(std::size_t n)
|
||||
{
|
||||
std::size_t real_block_size = m_real_block_alignment*m_num_subblocks - SegmentManagerBase::PayloadPerAllocation;
|
||||
std::size_t elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
|
||||
std::size_t hdr_subblock_elements = (m_real_block_alignment - HdrSize - SegmentManagerBase::PayloadPerAllocation)/m_real_node_size;
|
||||
|
||||
for(std::size_t i = 0; i != n; ++i){
|
||||
//We allocate a new NodeBlock and put it the last
|
||||
//element of the tree
|
||||
char *mem_address = static_cast<char*>
|
||||
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
|
||||
if(!mem_address) throw std::bad_alloc();
|
||||
++m_totally_free_blocks;
|
||||
|
||||
//First initialize header information on the last subblock
|
||||
char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
|
||||
block_info_t *c_info = new(hdr_addr)block_info_t;
|
||||
//Some structural checks
|
||||
assert(static_cast<void*>(&static_cast<hdr_offset_holder*>(c_info)->hdr_offset) ==
|
||||
static_cast<void*>(c_info));
|
||||
typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin();
|
||||
for( std::size_t subblock = 0, maxsubblock = m_num_subblocks - 1
|
||||
; subblock < maxsubblock
|
||||
; ++subblock, mem_address += m_real_block_alignment){
|
||||
//Initialize header offset mark
|
||||
new(mem_address) hdr_offset_holder(std::size_t(hdr_addr - mem_address));
|
||||
char *pNode = mem_address + HdrOffsetSize;
|
||||
for(std::size_t i = 0; i < elements_per_subblock; ++i){
|
||||
prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
|
||||
pNode += m_real_node_size;
|
||||
}
|
||||
}
|
||||
{
|
||||
char *pNode = hdr_addr + HdrSize;
|
||||
//We initialize all Nodes in Node Block to insert
|
||||
//them in the free Node list
|
||||
for(std::size_t i = 0; i < hdr_subblock_elements; ++i){
|
||||
prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
|
||||
pNode += m_real_node_size;
|
||||
}
|
||||
}
|
||||
//Insert the block after the free node list is full
|
||||
m_block_multiset.insert(m_block_multiset.end(), *c_info);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename boost::pointer_to_other
|
||||
<void_pointer, segment_manager_base_type>::type segment_mngr_base_ptr_t;
|
||||
|
||||
const std::size_t m_max_free_blocks;
|
||||
const std::size_t m_real_node_size;
|
||||
//Round the size to a power of two value.
|
||||
//This is the total memory size (including payload) that we want to
|
||||
//allocate from the general-purpose allocator
|
||||
const std::size_t m_real_block_alignment;
|
||||
std::size_t m_num_subblocks;
|
||||
//This is the real number of nodes per block
|
||||
//const
|
||||
std::size_t m_real_num_node;
|
||||
segment_mngr_base_ptr_t mp_segment_mngr_base;//Segment manager
|
||||
block_multiset_t m_block_multiset; //Intrusive block list
|
||||
std::size_t m_totally_free_blocks; //Free blocks
|
||||
};
|
||||
|
||||
template< class SegmentManager
|
||||
, std::size_t NodeSize
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, unsigned char OverheadPercent
|
||||
>
|
||||
class private_adaptive_node_pool
|
||||
: public private_adaptive_node_pool_impl
|
||||
<typename SegmentManager::segment_manager_base_type>
|
||||
{
|
||||
typedef private_adaptive_node_pool_impl
|
||||
<typename SegmentManager::segment_manager_base_type> base_t;
|
||||
//Non-copyable
|
||||
private_adaptive_node_pool();
|
||||
private_adaptive_node_pool(const private_adaptive_node_pool &);
|
||||
private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
|
||||
|
||||
public:
|
||||
typedef SegmentManager segment_manager;
|
||||
|
||||
static const std::size_t nodes_per_block = NodesPerBlock;
|
||||
|
||||
//Deprecated, use node_per_block
|
||||
static const std::size_t nodes_per_chunk = NodesPerBlock;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
private_adaptive_node_pool(segment_manager *segment_mngr)
|
||||
: base_t(segment_mngr, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent)
|
||||
{}
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager* get_segment_manager() const
|
||||
{ return static_cast<segment_manager*>(base_t::get_segment_manager_base()); }
|
||||
};
|
||||
|
||||
//!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 SegmentManager
|
||||
, std::size_t NodeSize
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, unsigned char OverheadPercent
|
||||
>
|
||||
class shared_adaptive_node_pool
|
||||
: public detail::shared_pool_impl
|
||||
< private_adaptive_node_pool
|
||||
<SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
|
||||
>
|
||||
{
|
||||
typedef detail::shared_pool_impl
|
||||
< private_adaptive_node_pool
|
||||
<SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
|
||||
> base_t;
|
||||
public:
|
||||
shared_adaptive_node_pool(SegmentManager *segment_mgnr)
|
||||
: base_t(segment_mgnr)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP
|
||||
|
||||
@@ -0,0 +1,839 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008. 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/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp> //get_pointer
|
||||
#include <utility> //std::pair
|
||||
#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/interprocess/mem_algo/detail/mem_algo_common.hpp>
|
||||
#include <boost/interprocess/detail/segment_manager_helper.hpp>
|
||||
#include <algorithm> //std::swap
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
|
||||
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 detail {
|
||||
|
||||
//!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)
|
||||
{
|
||||
detail::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 pointer_to_other
|
||||
<void_pointer, NodePool>::type node_pool_ptr;
|
||||
typedef typename NodePool::multiallocation_chain multiallocation_chain;
|
||||
node_pool_ptr mp_node_pool;
|
||||
multiallocation_chain m_cached_nodes;
|
||||
std::size_t m_max_cached_nodes;
|
||||
|
||||
public:
|
||||
typedef typename NodePool::segment_manager segment_manager;
|
||||
|
||||
cache_impl(segment_manager *segment_mngr, std::size_t 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();
|
||||
detail::destroy_node_pool_if_last_link(detail::get_pointer(mp_node_pool));
|
||||
}
|
||||
|
||||
NodePool *get_node_pool() const
|
||||
{ return detail::get_pointer(mp_node_pool); }
|
||||
|
||||
segment_manager *get_segment_manager() const
|
||||
{ return mp_node_pool->get_segment_manager(); }
|
||||
|
||||
std::size_t 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()){
|
||||
m_cached_nodes = mp_node_pool->allocate_nodes(m_max_cached_nodes/2);
|
||||
}
|
||||
void *ret = detail::get_pointer(m_cached_nodes.front());
|
||||
m_cached_nodes.pop_front();
|
||||
return ret;
|
||||
}
|
||||
|
||||
multiallocation_chain cached_allocation(std::size_t n)
|
||||
{
|
||||
multiallocation_chain chain;
|
||||
std::size_t 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 = detail::get_pointer(m_cached_nodes.front());
|
||||
m_cached_nodes.pop_front();
|
||||
chain.push_back(ret);
|
||||
++allocated;
|
||||
}
|
||||
|
||||
if(allocated != n){
|
||||
multiallocation_chain chain2(mp_node_pool->allocate_nodes(n - allocated));
|
||||
chain.splice_after(chain.last(), chain2, chain2.before_begin(), chain2.last(), n - allocated);
|
||||
}
|
||||
return boost::interprocess::move(chain);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
this->cached_deallocation(boost::interprocess::move(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(std::size_t 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(boost::interprocess::move(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(std::size_t n)
|
||||
{
|
||||
//Deallocate all new linked list at once
|
||||
mp_node_pool->deallocate_nodes(m_cached_nodes, n);
|
||||
}
|
||||
};
|
||||
|
||||
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::
|
||||
pointer_to_other<void_pointer, T>::type pointer;
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef 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(detail::get_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, detail::get_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(...)
|
||||
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements)
|
||||
{
|
||||
return this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements);
|
||||
}
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
|
||||
{
|
||||
return this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T));
|
||||
}
|
||||
|
||||
//!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)
|
||||
{ return this->derived()->get_segment_manager()->deallocate_many(boost::interprocess::move(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)); }
|
||||
|
||||
//!Default construct an object.
|
||||
//!Throws if T's default constructor throws
|
||||
void construct(const pointer &ptr)
|
||||
{ new((void*)detail::get_pointer(ptr)) value_type; }
|
||||
|
||||
//!Copy construct an object
|
||||
//!Throws if T's copy constructor throws
|
||||
void construct(const pointer &ptr, const_reference v)
|
||||
{ new((void*)detail::get_pointer(ptr)) value_type(v); }
|
||||
|
||||
//!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::
|
||||
pointer_to_other<void_pointer, const void>::type cvoid_pointer;
|
||||
|
||||
public:
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, T>::type pointer;
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef 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(count > this->max_size())
|
||||
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(sizeof(T)*count)));
|
||||
}
|
||||
|
||||
//!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(detail::get_pointer(ptr));
|
||||
else
|
||||
pool->get_segment_manager()->deallocate((void*)detail::get_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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements)
|
||||
{
|
||||
typedef typename node_pool<0>::type node_pool_t;
|
||||
node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
|
||||
return multiallocation_chain(pool->allocate_nodes(num_elements));
|
||||
}
|
||||
|
||||
//!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(detail::get_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.extract_multiallocation_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::
|
||||
pointer_to_other<void_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:
|
||||
enum { DEFAULT_MAX_CACHED_NODES = 64 };
|
||||
|
||||
cached_allocator_impl(segment_manager *segment_mngr, std::size_t 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(std::size_t newmax)
|
||||
{ m_cache.set_max_cached_nodes(newmax); }
|
||||
|
||||
//!Returns the max cached nodes parameter.
|
||||
//!Never throws
|
||||
std::size_t 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(count > this->max_size())
|
||||
throw bad_alloc();
|
||||
else if(Version == 1 && count == 1){
|
||||
ret = m_cache.cached_allocation();
|
||||
}
|
||||
else{
|
||||
ret = this->get_segment_manager()->allocate(sizeof(T)*count);
|
||||
}
|
||||
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(detail::get_pointer(ptr));
|
||||
}
|
||||
else{
|
||||
this->get_segment_manager()->deallocate((void*)detail::get_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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements)
|
||||
{ return multiallocation_chain(this->m_cache.cached_allocation(num_elements)); }
|
||||
|
||||
//!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(detail::get_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)
|
||||
{
|
||||
typename node_pool_t::multiallocation_chain mem
|
||||
(chain.extract_multiallocation_chain());
|
||||
m_cache.cached_deallocation(boost::interprocess::move(mem));
|
||||
}
|
||||
|
||||
//!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)
|
||||
{
|
||||
detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool);
|
||||
alloc1.m_cached_nodes.swap(alloc2.m_cached_nodes);
|
||||
detail::do_swap(alloc1.m_max_cached_nodes, alloc2.m_max_cached_nodes);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 a singly linked list of n nodes ending in null pointer.
|
||||
//!can throw boost::interprocess::bad_alloc
|
||||
void allocate_nodes(multiallocation_chain &nodes, std::size_t n)
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::allocate_nodes(nodes, n);
|
||||
}
|
||||
*/
|
||||
//!Allocates n nodes.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
multiallocation_chain allocate_nodes(const std::size_t n)
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
return private_node_allocator_t::allocate_nodes(n);
|
||||
}
|
||||
|
||||
//!Deallocates a linked list of nodes ending in null pointer. Never throws
|
||||
void deallocate_nodes(multiallocation_chain &nodes, std::size_t 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(boost::interprocess::move(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
|
||||
std::size_t 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
|
||||
std::size_t dec_ref_count()
|
||||
{
|
||||
//-----------------------
|
||||
boost::interprocess::scoped_lock<mutex_type> guard(m_header);
|
||||
//-----------------------
|
||||
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
|
||||
//!interprocess_mutex to allow EBO when using null_mutex
|
||||
struct header_t : mutex_type
|
||||
{
|
||||
std::size_t m_usecount; //Number of attached allocators
|
||||
|
||||
header_t()
|
||||
: m_usecount(0) {}
|
||||
} m_header;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
|
||||
@@ -0,0 +1,409 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_NODE_POOL_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_NODE_POOL_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/slist.hpp>
|
||||
#include <boost/math/common_factor_ct.hpp>
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/math_functions.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/allocators/detail/node_tools.hpp>
|
||||
#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
//!\file
|
||||
//!Describes the real adaptive pool shared by many Interprocess adaptive pool allocators
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
template<class SegmentManagerBase>
|
||||
class private_node_pool_impl
|
||||
{
|
||||
//Non-copyable
|
||||
private_node_pool_impl();
|
||||
private_node_pool_impl(const private_node_pool_impl &);
|
||||
private_node_pool_impl &operator=(const private_node_pool_impl &);
|
||||
|
||||
//A node object will hold node_t when it's not allocated
|
||||
public:
|
||||
typedef typename SegmentManagerBase::void_pointer void_pointer;
|
||||
typedef typename node_slist<void_pointer>::slist_hook_t slist_hook_t;
|
||||
typedef typename node_slist<void_pointer>::node_t node_t;
|
||||
typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
|
||||
typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
|
||||
|
||||
private:
|
||||
typedef typename bi::make_slist
|
||||
< node_t, bi::base_hook<slist_hook_t>
|
||||
, bi::linear<true>
|
||||
, bi::constant_time_size<false> >::type blockslist_t;
|
||||
public:
|
||||
|
||||
//!Segment manager typedef
|
||||
typedef SegmentManagerBase segment_manager_base_type;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
private_node_pool_impl(segment_manager_base_type *segment_mngr_base, std::size_t node_size, std::size_t nodes_per_block)
|
||||
: m_nodes_per_block(nodes_per_block)
|
||||
, m_real_node_size(detail::lcm(node_size, std::size_t(alignment_of<node_t>::value)))
|
||||
//General purpose allocator
|
||||
, mp_segment_mngr_base(segment_mngr_base)
|
||||
, m_blocklist()
|
||||
, m_freelist()
|
||||
//Debug node count
|
||||
, m_allocated(0)
|
||||
{}
|
||||
|
||||
//!Destructor. Deallocates all allocated blocks. Never throws
|
||||
~private_node_pool_impl()
|
||||
{ this->purge_blocks(); }
|
||||
|
||||
std::size_t get_real_num_node() const
|
||||
{ return m_nodes_per_block; }
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager_base_type* get_segment_manager_base()const
|
||||
{ return detail::get_pointer(mp_segment_mngr_base); }
|
||||
|
||||
//!Allocates array of count elements. Can throw boost::interprocess::bad_alloc
|
||||
void *allocate_node()
|
||||
{
|
||||
//If there are no free nodes we allocate a new block
|
||||
if (m_freelist.empty())
|
||||
priv_alloc_block();
|
||||
//We take the first free node
|
||||
node_t *n = &m_freelist.front();
|
||||
m_freelist.pop_front();
|
||||
++m_allocated;
|
||||
return n;
|
||||
}
|
||||
|
||||
//!Deallocates an array pointed by ptr. Never throws
|
||||
void deallocate_node(void *ptr)
|
||||
{
|
||||
//We put the node at the beginning of the free node list
|
||||
node_t * to_deallocate = static_cast<node_t*>(ptr);
|
||||
m_freelist.push_front(*to_deallocate);
|
||||
assert(m_allocated>0);
|
||||
--m_allocated;
|
||||
}
|
||||
|
||||
//!Allocates a singly linked list of n nodes ending in null pointer
|
||||
//!can throw boost::interprocess::bad_alloc
|
||||
multiallocation_chain allocate_nodes(const std::size_t n)
|
||||
{
|
||||
multiallocation_chain nodes;
|
||||
std::size_t i = 0;
|
||||
try{
|
||||
for(; i < n; ++i){
|
||||
nodes.push_front(this->allocate_node());
|
||||
}
|
||||
}
|
||||
catch(...){
|
||||
this->deallocate_nodes(nodes, i);
|
||||
throw;
|
||||
}
|
||||
return boost::interprocess::move(nodes);
|
||||
}
|
||||
|
||||
//!Deallocates the first n nodes of a linked list of nodes. Never throws
|
||||
void deallocate_nodes(multiallocation_chain &nodes, std::size_t n)
|
||||
{
|
||||
for(std::size_t i = 0; i < n; ++i){
|
||||
void *p = detail::get_pointer(nodes.front());
|
||||
assert(p);
|
||||
nodes.pop_front();
|
||||
this->deallocate_node(p);
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
|
||||
void deallocate_nodes(multiallocation_chain chain)
|
||||
{
|
||||
while(!chain.empty()){
|
||||
void *addr = detail::get_pointer(chain.front());
|
||||
chain.pop_front();
|
||||
deallocate_node(addr);
|
||||
}
|
||||
}
|
||||
|
||||
//!Deallocates all the free blocks of memory. Never throws
|
||||
void deallocate_free_blocks()
|
||||
{
|
||||
typedef typename free_nodes_t::iterator nodelist_iterator;
|
||||
typename blockslist_t::iterator bit(m_blocklist.before_begin()),
|
||||
it(m_blocklist.begin()),
|
||||
itend(m_blocklist.end());
|
||||
free_nodes_t backup_list;
|
||||
nodelist_iterator backup_list_last = backup_list.before_begin();
|
||||
|
||||
//Execute the algorithm and get an iterator to the last value
|
||||
std::size_t blocksize = detail::get_rounded_size
|
||||
(m_real_node_size*m_nodes_per_block, alignment_of<node_t>::value);
|
||||
|
||||
while(it != itend){
|
||||
//Collect all the nodes from the block pointed by it
|
||||
//and push them in the list
|
||||
free_nodes_t free_nodes;
|
||||
nodelist_iterator last_it = free_nodes.before_begin();
|
||||
const void *addr = get_block_from_hook(&*it, blocksize);
|
||||
|
||||
m_freelist.remove_and_dispose_if
|
||||
(is_between(addr, blocksize), push_in_list(free_nodes, last_it));
|
||||
|
||||
//If the number of nodes is equal to m_nodes_per_block
|
||||
//this means that the block can be deallocated
|
||||
if(free_nodes.size() == m_nodes_per_block){
|
||||
//Unlink the nodes
|
||||
free_nodes.clear();
|
||||
it = m_blocklist.erase_after(bit);
|
||||
mp_segment_mngr_base->deallocate((void*)addr);
|
||||
}
|
||||
//Otherwise, insert them in the backup list, since the
|
||||
//next "remove_if" does not need to check them again.
|
||||
else{
|
||||
//Assign the iterator to the last value if necessary
|
||||
if(backup_list.empty() && !m_freelist.empty()){
|
||||
backup_list_last = last_it;
|
||||
}
|
||||
//Transfer nodes. This is constant time.
|
||||
backup_list.splice_after
|
||||
( backup_list.before_begin()
|
||||
, free_nodes
|
||||
, free_nodes.before_begin()
|
||||
, last_it
|
||||
, free_nodes.size());
|
||||
bit = it;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
//We should have removed all the nodes from the free list
|
||||
assert(m_freelist.empty());
|
||||
|
||||
//Now pass all the node to the free list again
|
||||
m_freelist.splice_after
|
||||
( m_freelist.before_begin()
|
||||
, backup_list
|
||||
, backup_list.before_begin()
|
||||
, backup_list_last
|
||||
, backup_list.size());
|
||||
}
|
||||
|
||||
std::size_t num_free_nodes()
|
||||
{ return m_freelist.size(); }
|
||||
|
||||
//!Deallocates all used memory. Precondition: all nodes allocated from this pool should
|
||||
//!already be deallocated. Otherwise, undefined behaviour. Never throws
|
||||
void purge_blocks()
|
||||
{
|
||||
//check for memory leaks
|
||||
assert(m_allocated==0);
|
||||
std::size_t blocksize = detail::get_rounded_size
|
||||
(m_real_node_size*m_nodes_per_block, alignment_of<node_t>::value);
|
||||
typename blockslist_t::iterator
|
||||
it(m_blocklist.begin()), itend(m_blocklist.end()), aux;
|
||||
|
||||
//We iterate though the NodeBlock list to free the memory
|
||||
while(!m_blocklist.empty()){
|
||||
void *addr = get_block_from_hook(&m_blocklist.front(), blocksize);
|
||||
m_blocklist.pop_front();
|
||||
mp_segment_mngr_base->deallocate((void*)addr);
|
||||
}
|
||||
//Just clear free node list
|
||||
m_freelist.clear();
|
||||
}
|
||||
|
||||
void swap(private_node_pool_impl &other)
|
||||
{
|
||||
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
|
||||
m_blocklist.swap(other.m_blocklist);
|
||||
m_freelist.swap(other.m_freelist);
|
||||
std::swap(m_allocated, other.m_allocated);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct push_in_list
|
||||
{
|
||||
push_in_list(free_nodes_t &l, typename free_nodes_t::iterator &it)
|
||||
: slist_(l), last_it_(it)
|
||||
{}
|
||||
|
||||
void operator()(typename free_nodes_t::pointer p) const
|
||||
{
|
||||
slist_.push_front(*p);
|
||||
if(slist_.size() == 1){ //Cache last element
|
||||
++last_it_ = slist_.begin();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
free_nodes_t &slist_;
|
||||
typename free_nodes_t::iterator &last_it_;
|
||||
};
|
||||
|
||||
struct is_between
|
||||
: std::unary_function<typename free_nodes_t::value_type, bool>
|
||||
{
|
||||
is_between(const void *addr, std::size_t size)
|
||||
: beg_(static_cast<const char *>(addr)), end_(beg_+size)
|
||||
{}
|
||||
|
||||
bool operator()(typename free_nodes_t::const_reference v) const
|
||||
{
|
||||
return (beg_ <= reinterpret_cast<const char *>(&v) &&
|
||||
end_ > reinterpret_cast<const char *>(&v));
|
||||
}
|
||||
private:
|
||||
const char * beg_;
|
||||
const char * end_;
|
||||
};
|
||||
|
||||
//!Allocates a block of nodes. Can throw boost::interprocess::bad_alloc
|
||||
void priv_alloc_block()
|
||||
{
|
||||
//We allocate a new NodeBlock and put it as first
|
||||
//element in the free Node list
|
||||
std::size_t blocksize =
|
||||
detail::get_rounded_size(m_real_node_size*m_nodes_per_block, alignment_of<node_t>::value);
|
||||
char *pNode = reinterpret_cast<char*>
|
||||
(mp_segment_mngr_base->allocate(blocksize + sizeof(node_t)));
|
||||
if(!pNode) throw bad_alloc();
|
||||
char *pBlock = pNode;
|
||||
m_blocklist.push_front(get_block_hook(pBlock, blocksize));
|
||||
|
||||
//We initialize all Nodes in Node Block to insert
|
||||
//them in the free Node list
|
||||
for(std::size_t i = 0; i < m_nodes_per_block; ++i, pNode += m_real_node_size){
|
||||
m_freelist.push_front(*new (pNode) node_t);
|
||||
}
|
||||
}
|
||||
|
||||
//!Deprecated, use deallocate_free_blocks
|
||||
void deallocate_free_chunks()
|
||||
{ this->deallocate_free_blocks(); }
|
||||
|
||||
//!Deprecated, use purge_blocks
|
||||
void purge_chunks()
|
||||
{ this->purge_blocks(); }
|
||||
|
||||
private:
|
||||
//!Returns a reference to the block hook placed in the end of the block
|
||||
static inline node_t & get_block_hook (void *block, std::size_t blocksize)
|
||||
{
|
||||
return *reinterpret_cast<node_t*>(reinterpret_cast<char*>(block) + blocksize);
|
||||
}
|
||||
|
||||
//!Returns the starting address of the block reference to the block hook placed in the end of the block
|
||||
inline void *get_block_from_hook (node_t *hook, std::size_t blocksize)
|
||||
{
|
||||
return (reinterpret_cast<char*>(hook) - blocksize);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename boost::pointer_to_other
|
||||
<void_pointer, segment_manager_base_type>::type segment_mngr_base_ptr_t;
|
||||
|
||||
const std::size_t m_nodes_per_block;
|
||||
const std::size_t m_real_node_size;
|
||||
segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
|
||||
blockslist_t m_blocklist; //Intrusive container of blocks
|
||||
free_nodes_t m_freelist; //Intrusive container of free nods
|
||||
std::size_t m_allocated; //Used nodes for debugging
|
||||
};
|
||||
|
||||
|
||||
//!Pooled shared memory allocator using single segregated storage. 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 SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock >
|
||||
class private_node_pool
|
||||
//Inherit from the implementation to avoid template bloat
|
||||
: public private_node_pool_impl<typename SegmentManager::segment_manager_base_type>
|
||||
{
|
||||
typedef private_node_pool_impl<typename SegmentManager::segment_manager_base_type> base_t;
|
||||
//Non-copyable
|
||||
private_node_pool();
|
||||
private_node_pool(const private_node_pool &);
|
||||
private_node_pool &operator=(const private_node_pool &);
|
||||
|
||||
public:
|
||||
typedef SegmentManager segment_manager;
|
||||
|
||||
static const std::size_t nodes_per_block = NodesPerBlock;
|
||||
//Deprecated, use nodes_per_block
|
||||
static const std::size_t nodes_per_chunk = NodesPerBlock;
|
||||
|
||||
//!Constructor from a segment manager. Never throws
|
||||
private_node_pool(segment_manager *segment_mngr)
|
||||
: base_t(segment_mngr, NodeSize, NodesPerBlock)
|
||||
{}
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager* get_segment_manager() const
|
||||
{ return static_cast<segment_manager*>(base_t::get_segment_manager_base()); }
|
||||
};
|
||||
|
||||
|
||||
//!Pooled shared memory allocator using single segregated storage. 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
|
||||
//!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 SegmentManager
|
||||
, std::size_t NodeSize
|
||||
, std::size_t NodesPerBlock
|
||||
>
|
||||
class shared_node_pool
|
||||
: public detail::shared_pool_impl
|
||||
< private_node_pool
|
||||
<SegmentManager, NodeSize, NodesPerBlock>
|
||||
>
|
||||
{
|
||||
typedef detail::shared_pool_impl
|
||||
< private_node_pool
|
||||
<SegmentManager, NodeSize, NodesPerBlock>
|
||||
> base_t;
|
||||
public:
|
||||
shared_node_pool(SegmentManager *segment_mgnr)
|
||||
: base_t(segment_mgnr)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP
|
||||
@@ -0,0 +1,50 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2008. 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_NODE_TOOLS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_NODE_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/intrusive/slist.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
|
||||
template<class VoidPointer>
|
||||
struct node_slist
|
||||
{
|
||||
//This hook will be used to chain the individual nodes
|
||||
typedef typename bi::make_slist_base_hook
|
||||
<bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type slist_hook_t;
|
||||
|
||||
//A node object will hold node_t when it's not allocated
|
||||
struct node_t
|
||||
: public slist_hook_t
|
||||
{};
|
||||
|
||||
typedef typename bi::make_slist
|
||||
<node_t, bi::linear<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP
|
||||
@@ -0,0 +1,449 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_NODE_ALLOCATOR_HPP
|
||||
#define BOOST_INTERPROCESS_NODE_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/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/allocators/detail/node_pool.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/allocators/detail/allocator_common.hpp>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
//!Describes node_allocator pooled shared memory STL compatible allocator
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail{
|
||||
|
||||
template < unsigned int Version
|
||||
, class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
>
|
||||
class node_allocator_base
|
||||
: public node_pool_allocation_impl
|
||||
< node_allocator_base
|
||||
< Version, T, SegmentManager, NodesPerBlock>
|
||||
, Version
|
||||
, T
|
||||
, SegmentManager
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
typedef SegmentManager segment_manager;
|
||||
typedef node_allocator_base
|
||||
<Version, T, SegmentManager, NodesPerBlock> self_t;
|
||||
|
||||
/// @cond
|
||||
|
||||
template <int dummy>
|
||||
struct node_pool
|
||||
{
|
||||
typedef detail::shared_node_pool
|
||||
< SegmentManager, sizeof_value<T>::value, NodesPerBlock> type;
|
||||
|
||||
static type *get(void *p)
|
||||
{ return static_cast<type*>(p); }
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
BOOST_STATIC_ASSERT((Version <=2));
|
||||
|
||||
public:
|
||||
//-------
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, T>::type pointer;
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef boost::interprocess::version_type<node_allocator_base, Version> version;
|
||||
typedef detail::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
|
||||
//!Obtains node_allocator_base from
|
||||
//!node_allocator_base
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
//!Not assignable from related node_allocator_base
|
||||
template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2>
|
||||
node_allocator_base& operator=
|
||||
(const node_allocator_base<Version2, T2, SegmentManager2, N2>&);
|
||||
|
||||
//!Not assignable from other node_allocator_base
|
||||
//node_allocator_base& operator=(const node_allocator_base&);
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
node_allocator_base(segment_manager *segment_mngr)
|
||||
: mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
|
||||
|
||||
//!Copy constructor from other node_allocator_base. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
node_allocator_base(const node_allocator_base &other)
|
||||
: mp_node_pool(other.get_node_pool())
|
||||
{
|
||||
node_pool<0>::get(detail::get_pointer(mp_node_pool))->inc_ref_count();
|
||||
}
|
||||
|
||||
//!Copy constructor from related node_allocator_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>
|
||||
node_allocator_base
|
||||
(const node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> &other)
|
||||
: mp_node_pool(detail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
|
||||
|
||||
//!Assignment from other node_allocator_base
|
||||
node_allocator_base& operator=(const node_allocator_base &other)
|
||||
{
|
||||
node_allocator_base c(other);
|
||||
swap(*this, c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~node_allocator_base()
|
||||
{ detail::destroy_node_pool_if_last_link(node_pool<0>::get(detail::get_pointer(mp_node_pool))); }
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
void* get_node_pool() const
|
||||
{ return detail::get_pointer(mp_node_pool); }
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const
|
||||
{ return node_pool<0>::get(detail::get_pointer(mp_node_pool))->get_segment_manager(); }
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2)
|
||||
{ detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
void_pointer mp_node_pool;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!Equality test for same type
|
||||
//!of node_allocator_base
|
||||
template<unsigned int V, class T, class S, std::size_t NPC> inline
|
||||
bool operator==(const node_allocator_base<V, T, S, NPC> &alloc1,
|
||||
const node_allocator_base<V, T, S, NPC> &alloc2)
|
||||
{ return alloc1.get_node_pool() == alloc2.get_node_pool(); }
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of node_allocator_base
|
||||
template<unsigned int V, class T, class S, std::size_t NPC> inline
|
||||
bool operator!=(const node_allocator_base<V, T, S, NPC> &alloc1,
|
||||
const node_allocator_base<V, T, S, NPC> &alloc2)
|
||||
{ return alloc1.get_node_pool() != alloc2.get_node_pool(); }
|
||||
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock = 64
|
||||
>
|
||||
class node_allocator_v1
|
||||
: public node_allocator_base
|
||||
< 1
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef detail::node_allocator_base
|
||||
< 1, T, SegmentManager, NodesPerBlock> base_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef node_allocator_v1<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
node_allocator_v1(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
node_allocator_v1
|
||||
(const node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail{
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!An STL node 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...
|
||||
//!This node allocator shares a segregated storage between all instances
|
||||
//!of node_allocator with equal sizeof(T) placed in the same segment
|
||||
//!group. NodesPerBlock is the number of nodes allocated at once when the allocator
|
||||
//!needs runs out of nodes
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
>
|
||||
class node_allocator
|
||||
/// @cond
|
||||
: public detail::node_allocator_base
|
||||
< 2
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
>
|
||||
/// @endcond
|
||||
{
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
typedef detail::node_allocator_base
|
||||
< 2, T, SegmentManager, NodesPerBlock> base_t;
|
||||
public:
|
||||
typedef boost::interprocess::version_type<node_allocator, 2> version;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef node_allocator<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
node_allocator(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
node_allocator
|
||||
(const node_allocator<T2, SegmentManager, NodesPerBlock> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
#else //BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
public:
|
||||
typedef implementation_defined::segment_manager segment_manager;
|
||||
typedef segment_manager::void_pointer void_pointer;
|
||||
typedef implementation_defined::pointer pointer;
|
||||
typedef implementation_defined::const_pointer const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
//!Obtains node_allocator from
|
||||
//!node_allocator
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef node_allocator<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from
|
||||
//!related node_allocator
|
||||
template<class T2, class SegmentManager2, std::size_t N2>
|
||||
node_allocator& operator=
|
||||
(const node_allocator<T2, SegmentManager2, N2>&);
|
||||
|
||||
//!Not assignable from
|
||||
//!other node_allocator
|
||||
//node_allocator& operator=(const node_allocator&);
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
node_allocator(segment_manager *segment_mngr);
|
||||
|
||||
//!Copy constructor from other node_allocator. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
node_allocator(const node_allocator &other);
|
||||
|
||||
//!Copy constructor from related node_allocator. 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>
|
||||
node_allocator
|
||||
(const node_allocator<T2, SegmentManager, NodesPerBlock> &other);
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~node_allocator();
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
void* get_node_pool() const;
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const;
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const;
|
||||
|
||||
//!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);
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count);
|
||||
|
||||
//!Deallocates all free blocks
|
||||
//!of the pool
|
||||
void deallocate_free_blocks();
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2);
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const;
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//!Copy construct an object.
|
||||
//!Throws if T's copy constructor throws
|
||||
void construct(const pointer &ptr, const_reference v);
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr);
|
||||
|
||||
//!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;
|
||||
|
||||
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);
|
||||
|
||||
//!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(...)
|
||||
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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();
|
||||
|
||||
//!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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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);
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Equality test for same type
|
||||
//!of node_allocator
|
||||
template<class T, class S, std::size_t NPC> inline
|
||||
bool operator==(const node_allocator<T, S, NPC> &alloc1,
|
||||
const node_allocator<T, S, NPC> &alloc2);
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of node_allocator
|
||||
template<class T, class S, std::size_t NPC> inline
|
||||
bool operator!=(const node_allocator<T, S, NPC> &alloc1,
|
||||
const node_allocator<T, S, NPC> &alloc2);
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,465 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_PRIVATE_ADAPTIVE_POOL_HPP
|
||||
#define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_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/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail {
|
||||
|
||||
template < unsigned int Version
|
||||
, class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, unsigned char OverheadPercent
|
||||
>
|
||||
class private_adaptive_pool_base
|
||||
: public node_pool_allocation_impl
|
||||
< private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock
|
||||
, MaxFreeBlocks, OverheadPercent>
|
||||
, Version
|
||||
, T
|
||||
, SegmentManager
|
||||
>
|
||||
{
|
||||
public:
|
||||
//Segment manager
|
||||
typedef SegmentManager segment_manager;
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef private_adaptive_pool_base
|
||||
< Version, T, SegmentManager, NodesPerBlock
|
||||
, MaxFreeBlocks, OverheadPercent> self_t;
|
||||
typedef detail::private_adaptive_node_pool
|
||||
<SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
> node_pool_t;
|
||||
|
||||
BOOST_STATIC_ASSERT((Version <=2));
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, T>::type pointer;
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef boost::interprocess::version_type
|
||||
<private_adaptive_pool_base, Version> version;
|
||||
typedef detail::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
|
||||
//!Obtains node_allocator from other node_allocator
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_adaptive_pool_base
|
||||
<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
template <int dummy>
|
||||
struct node_pool
|
||||
{
|
||||
typedef detail::private_adaptive_node_pool
|
||||
<SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
> type;
|
||||
|
||||
static type *get(void *p)
|
||||
{ return static_cast<type*>(p); }
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from related private_adaptive_pool_base
|
||||
template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2, std::size_t F2, unsigned char OP2>
|
||||
private_adaptive_pool_base& operator=
|
||||
(const private_adaptive_pool_base<Version2, T2, MemoryAlgorithm2, N2, F2, OP2>&);
|
||||
|
||||
//!Not assignable from other private_adaptive_pool_base
|
||||
private_adaptive_pool_base& operator=(const private_adaptive_pool_base&);
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager
|
||||
private_adaptive_pool_base(segment_manager *segment_mngr)
|
||||
: m_node_pool(segment_mngr)
|
||||
{}
|
||||
|
||||
//!Copy constructor from other private_adaptive_pool_base. Never throws
|
||||
private_adaptive_pool_base(const private_adaptive_pool_base &other)
|
||||
: m_node_pool(other.get_segment_manager())
|
||||
{}
|
||||
|
||||
//!Copy constructor from related private_adaptive_pool_base. Never throws.
|
||||
template<class T2>
|
||||
private_adaptive_pool_base
|
||||
(const private_adaptive_pool_base
|
||||
<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: m_node_pool(other.get_segment_manager())
|
||||
{}
|
||||
|
||||
//!Destructor, frees all used memory. Never throws
|
||||
~private_adaptive_pool_base()
|
||||
{}
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager* get_segment_manager()const
|
||||
{ return m_node_pool.get_segment_manager(); }
|
||||
|
||||
//!Returns the internal node pool. Never throws
|
||||
node_pool_t* get_node_pool() const
|
||||
{ return const_cast<node_pool_t*>(&m_node_pool); }
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different shared memory segments, the result is undefined.
|
||||
friend void swap(self_t &alloc1,self_t &alloc2)
|
||||
{ alloc1.m_node_pool.swap(alloc2.m_node_pool); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_pool_t m_node_pool;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!Equality test for same type of private_adaptive_pool_base
|
||||
template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator==(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
|
||||
{ return &alloc1 == &alloc2; }
|
||||
|
||||
//!Inequality test for same type of private_adaptive_pool_base
|
||||
template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator!=(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
|
||||
{ return &alloc1 != &alloc2; }
|
||||
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock = 64
|
||||
, std::size_t MaxFreeBlocks = 2
|
||||
, unsigned char OverheadPercent = 5
|
||||
>
|
||||
class private_adaptive_pool_v1
|
||||
: public private_adaptive_pool_base
|
||||
< 1
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef detail::private_adaptive_pool_base
|
||||
< 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
private_adaptive_pool_v1(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_adaptive_pool_v1
|
||||
(const private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!An STL node 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...
|
||||
//!This allocator has its own node pool.
|
||||
//!
|
||||
//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when
|
||||
//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
|
||||
//!that the adaptive node pool will hold. The rest of the totally free blocks will be
|
||||
//!deallocated with the segment manager.
|
||||
//!
|
||||
//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
|
||||
//!(memory usable for nodes / total memory allocated from the segment manager)
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
, std::size_t MaxFreeBlocks
|
||||
, unsigned char OverheadPercent
|
||||
>
|
||||
class private_adaptive_pool
|
||||
/// @cond
|
||||
: public detail::private_adaptive_pool_base
|
||||
< 2
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
, MaxFreeBlocks
|
||||
, OverheadPercent
|
||||
>
|
||||
/// @endcond
|
||||
{
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
typedef detail::private_adaptive_pool_base
|
||||
< 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
|
||||
public:
|
||||
typedef boost::interprocess::version_type<private_adaptive_pool, 2> version;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_adaptive_pool
|
||||
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
private_adaptive_pool(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_adaptive_pool
|
||||
(const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
#else
|
||||
public:
|
||||
typedef implementation_defined::segment_manager segment_manager;
|
||||
typedef segment_manager::void_pointer void_pointer;
|
||||
typedef implementation_defined::pointer pointer;
|
||||
typedef implementation_defined::const_pointer const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
//!Obtains private_adaptive_pool from
|
||||
//!private_adaptive_pool
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_adaptive_pool
|
||||
<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from
|
||||
//!related private_adaptive_pool
|
||||
template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
|
||||
private_adaptive_pool& operator=
|
||||
(const private_adaptive_pool<T2, SegmentManager2, N2, F2>&);
|
||||
|
||||
//!Not assignable from
|
||||
//!other private_adaptive_pool
|
||||
private_adaptive_pool& operator=(const private_adaptive_pool&);
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
private_adaptive_pool(segment_manager *segment_mngr);
|
||||
|
||||
//!Copy constructor from other private_adaptive_pool. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
private_adaptive_pool(const private_adaptive_pool &other);
|
||||
|
||||
//!Copy constructor from related private_adaptive_pool. 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>
|
||||
private_adaptive_pool
|
||||
(const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~private_adaptive_pool();
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
node_pool_t* get_node_pool() const;
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const;
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const;
|
||||
|
||||
//!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);
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count);
|
||||
|
||||
//!Deallocates all free blocks
|
||||
//!of the pool
|
||||
void deallocate_free_blocks();
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2);
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const;
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//!Copy construct an object.
|
||||
//!Throws if T's copy constructor throws
|
||||
void construct(const pointer &ptr, const_reference v);
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr);
|
||||
|
||||
//!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;
|
||||
|
||||
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);
|
||||
|
||||
//!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(...)
|
||||
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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();
|
||||
|
||||
//!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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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);
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Equality test for same type
|
||||
//!of private_adaptive_pool
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator==(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of private_adaptive_pool
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator!=(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_PRIVATE_NODE_ALLOCATOR_HPP
|
||||
#define BOOST_INTERPROCESS_PRIVATE_NODE_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/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/interprocess/allocators/detail/node_pool.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
//!\file
|
||||
//!Describes private_node_allocator_base pooled shared memory STL compatible allocator
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail {
|
||||
|
||||
template < unsigned int Version
|
||||
, class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
>
|
||||
class private_node_allocator_base
|
||||
: public node_pool_allocation_impl
|
||||
< private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock>
|
||||
, Version
|
||||
, T
|
||||
, SegmentManager
|
||||
>
|
||||
{
|
||||
public:
|
||||
//Segment manager
|
||||
typedef SegmentManager segment_manager;
|
||||
typedef typename SegmentManager::void_pointer void_pointer;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef private_node_allocator_base
|
||||
< Version, T, SegmentManager, NodesPerBlock> self_t;
|
||||
typedef detail::private_node_pool
|
||||
<SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
> node_pool_t;
|
||||
|
||||
BOOST_STATIC_ASSERT((Version <=2));
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, T>::type pointer;
|
||||
typedef typename boost::
|
||||
pointer_to_other<void_pointer, const T>::type const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef boost::interprocess::version_type
|
||||
<private_node_allocator_base, Version> version;
|
||||
typedef detail::transform_multiallocation_chain
|
||||
<typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
|
||||
|
||||
//!Obtains node_allocator from other node_allocator
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_node_allocator_base
|
||||
<Version, T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <int dummy>
|
||||
struct node_pool
|
||||
{
|
||||
typedef detail::private_node_pool
|
||||
<SegmentManager
|
||||
, sizeof_value<T>::value
|
||||
, NodesPerBlock
|
||||
> type;
|
||||
|
||||
static type *get(void *p)
|
||||
{ return static_cast<type*>(p); }
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from related private_node_allocator_base
|
||||
template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2>
|
||||
private_node_allocator_base& operator=
|
||||
(const private_node_allocator_base<Version2, T2, MemoryAlgorithm2, N2>&);
|
||||
|
||||
//!Not assignable from other private_node_allocator_base
|
||||
private_node_allocator_base& operator=(const private_node_allocator_base&);
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager
|
||||
private_node_allocator_base(segment_manager *segment_mngr)
|
||||
: m_node_pool(segment_mngr)
|
||||
{}
|
||||
|
||||
//!Copy constructor from other private_node_allocator_base. Never throws
|
||||
private_node_allocator_base(const private_node_allocator_base &other)
|
||||
: m_node_pool(other.get_segment_manager())
|
||||
{}
|
||||
|
||||
//!Copy constructor from related private_node_allocator_base. Never throws.
|
||||
template<class T2>
|
||||
private_node_allocator_base
|
||||
(const private_node_allocator_base
|
||||
<Version, T2, SegmentManager, NodesPerBlock> &other)
|
||||
: m_node_pool(other.get_segment_manager())
|
||||
{}
|
||||
|
||||
//!Destructor, frees all used memory. Never throws
|
||||
~private_node_allocator_base()
|
||||
{}
|
||||
|
||||
//!Returns the segment manager. Never throws
|
||||
segment_manager* get_segment_manager()const
|
||||
{ return m_node_pool.get_segment_manager(); }
|
||||
|
||||
//!Returns the internal node pool. Never throws
|
||||
node_pool_t* get_node_pool() const
|
||||
{ return const_cast<node_pool_t*>(&m_node_pool); }
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different shared memory segments, the result is undefined.
|
||||
friend void swap(self_t &alloc1,self_t &alloc2)
|
||||
{ alloc1.m_node_pool.swap(alloc2.m_node_pool); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
node_pool_t m_node_pool;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
//!Equality test for same type of private_node_allocator_base
|
||||
template<unsigned int V, class T, class S, std::size_t NPC> inline
|
||||
bool operator==(const private_node_allocator_base<V, T, S, NPC> &alloc1,
|
||||
const private_node_allocator_base<V, T, S, NPC> &alloc2)
|
||||
{ return &alloc1 == &alloc2; }
|
||||
|
||||
//!Inequality test for same type of private_node_allocator_base
|
||||
template<unsigned int V, class T, class S, std::size_t NPC> inline
|
||||
bool operator!=(const private_node_allocator_base<V, T, S, NPC> &alloc1,
|
||||
const private_node_allocator_base<V, T, S, NPC> &alloc2)
|
||||
{ return &alloc1 != &alloc2; }
|
||||
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock = 64
|
||||
>
|
||||
class private_node_allocator_v1
|
||||
: public private_node_allocator_base
|
||||
< 1
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef detail::private_node_allocator_base
|
||||
< 1, T, SegmentManager, NodesPerBlock> base_t;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
private_node_allocator_v1(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_node_allocator_v1
|
||||
(const private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!An STL node 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...
|
||||
//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated
|
||||
//!at once when the allocator needs runs out of nodes
|
||||
template < class T
|
||||
, class SegmentManager
|
||||
, std::size_t NodesPerBlock
|
||||
>
|
||||
class private_node_allocator
|
||||
/// @cond
|
||||
: public detail::private_node_allocator_base
|
||||
< 2
|
||||
, T
|
||||
, SegmentManager
|
||||
, NodesPerBlock
|
||||
>
|
||||
/// @endcond
|
||||
{
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
typedef detail::private_node_allocator_base
|
||||
< 2, T, SegmentManager, NodesPerBlock> base_t;
|
||||
public:
|
||||
typedef boost::interprocess::version_type<private_node_allocator, 2> version;
|
||||
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_node_allocator
|
||||
<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
private_node_allocator(SegmentManager *segment_mngr)
|
||||
: base_t(segment_mngr)
|
||||
{}
|
||||
|
||||
template<class T2>
|
||||
private_node_allocator
|
||||
(const private_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
#else
|
||||
public:
|
||||
typedef implementation_defined::segment_manager segment_manager;
|
||||
typedef segment_manager::void_pointer void_pointer;
|
||||
typedef implementation_defined::pointer pointer;
|
||||
typedef implementation_defined::const_pointer const_pointer;
|
||||
typedef T value_type;
|
||||
typedef typename detail::add_reference
|
||||
<value_type>::type reference;
|
||||
typedef typename detail::add_reference
|
||||
<const value_type>::type const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
//!Obtains private_node_allocator from
|
||||
//!private_node_allocator
|
||||
template<class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef private_node_allocator
|
||||
<T2, SegmentManager, NodesPerBlock> other;
|
||||
};
|
||||
|
||||
private:
|
||||
//!Not assignable from
|
||||
//!related private_node_allocator
|
||||
template<class T2, class SegmentManager2, std::size_t N2>
|
||||
private_node_allocator& operator=
|
||||
(const private_node_allocator<T2, SegmentManager2, N2>&);
|
||||
|
||||
//!Not assignable from
|
||||
//!other private_node_allocator
|
||||
private_node_allocator& operator=(const private_node_allocator&);
|
||||
|
||||
public:
|
||||
//!Constructor from a segment manager. If not present, constructs a node
|
||||
//!pool. Increments the reference count of the associated node pool.
|
||||
//!Can throw boost::interprocess::bad_alloc
|
||||
private_node_allocator(segment_manager *segment_mngr);
|
||||
|
||||
//!Copy constructor from other private_node_allocator. Increments the reference
|
||||
//!count of the associated node pool. Never throws
|
||||
private_node_allocator(const private_node_allocator &other);
|
||||
|
||||
//!Copy constructor from related private_node_allocator. 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>
|
||||
private_node_allocator
|
||||
(const private_node_allocator<T2, SegmentManager, NodesPerBlock> &other);
|
||||
|
||||
//!Destructor, removes node_pool_t from memory
|
||||
//!if its reference count reaches to zero. Never throws
|
||||
~private_node_allocator();
|
||||
|
||||
//!Returns a pointer to the node pool.
|
||||
//!Never throws
|
||||
node_pool_t* get_node_pool() const;
|
||||
|
||||
//!Returns the segment manager.
|
||||
//!Never throws
|
||||
segment_manager* get_segment_manager()const;
|
||||
|
||||
//!Returns the number of elements that could be allocated.
|
||||
//!Never throws
|
||||
size_type max_size() const;
|
||||
|
||||
//!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);
|
||||
|
||||
//!Deallocate allocated memory.
|
||||
//!Never throws
|
||||
void deallocate(const pointer &ptr, size_type count);
|
||||
|
||||
//!Deallocates all free blocks
|
||||
//!of the pool
|
||||
void deallocate_free_blocks();
|
||||
|
||||
//!Swaps allocators. Does not throw. If each allocator is placed in a
|
||||
//!different memory segment, the result is undefined.
|
||||
friend void swap(self_t &alloc1, self_t &alloc2);
|
||||
|
||||
//!Returns address of mutable object.
|
||||
//!Never throws
|
||||
pointer address(reference value) const;
|
||||
|
||||
//!Returns address of non mutable object.
|
||||
//!Never throws
|
||||
const_pointer address(const_reference value) const;
|
||||
|
||||
//!Copy construct an object.
|
||||
//!Throws if T's copy constructor throws
|
||||
void construct(const pointer &ptr, const_reference v);
|
||||
|
||||
//!Destroys object. Throws if object's
|
||||
//!destructor throws
|
||||
void destroy(const pointer &ptr);
|
||||
|
||||
//!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;
|
||||
|
||||
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);
|
||||
|
||||
//!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(...)
|
||||
multiallocation_chain allocate_many(size_type elem_size, std::size_t num_elements);
|
||||
|
||||
//!Allocates n_elements elements, each one of size elem_sizes[i]in a
|
||||
//!contiguous block
|
||||
//!of memory. The elements must be deallocated
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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();
|
||||
|
||||
//!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().
|
||||
multiallocation_chain allocate_individual(std::size_t num_elements);
|
||||
|
||||
//!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);
|
||||
|
||||
//!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);
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//!Equality test for same type
|
||||
//!of private_node_allocator
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator==(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
//!Inequality test for same type
|
||||
//!of private_node_allocator
|
||||
template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
|
||||
bool operator!=(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1,
|
||||
const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
|
||||
|
||||
119
libraries/include/boost/interprocess/anonymous_shared_memory.hpp
Normal file
119
libraries/include/boost/interprocess/anonymous_shared_memory.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_ANONYMOUS_SHARED_MEMORY_HPP
|
||||
#define BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#if (!defined(BOOST_INTERPROCESS_WINDOWS))
|
||||
# include <fcntl.h> //open, O_CREAT, O_*...
|
||||
# include <sys/mman.h> //mmap
|
||||
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
|
||||
#else
|
||||
#include <boost/interprocess/windows_shared_memory.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
//!\file
|
||||
//!Describes a function that creates anonymous shared memory that can be
|
||||
//!shared between forked processes
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail{
|
||||
|
||||
class raw_mapped_region_creator
|
||||
{
|
||||
public:
|
||||
static mapped_region
|
||||
create_posix_mapped_region(void *address, offset_t offset, std::size_t size)
|
||||
{
|
||||
mapped_region region;
|
||||
region.m_base = address;
|
||||
region.m_offset = offset;
|
||||
region.m_extra_offset = 0;
|
||||
region.m_size = size;
|
||||
return region;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!A function that creates an anonymous shared memory segment of size "size".
|
||||
//!If "address" is passed the function will try to map the segment in that address.
|
||||
//!Otherwise the operating system will choose the mapping address.
|
||||
//!The function returns a mapped_region holding that segment or throws
|
||||
//!interprocess_exception if the function fails.
|
||||
//static mapped_region
|
||||
static mapped_region
|
||||
anonymous_shared_memory(std::size_t size, void *address = 0)
|
||||
#if (!defined(BOOST_INTERPROCESS_WINDOWS))
|
||||
{
|
||||
int flags;
|
||||
int fd = -1;
|
||||
|
||||
#if defined(MAP_ANONYMOUS) //Use MAP_ANONYMOUS
|
||||
flags = MAP_ANONYMOUS | MAP_SHARED;
|
||||
#elif !defined(MAP_ANONYMOUS) && defined(MAP_ANON) //use MAP_ANON
|
||||
flags = MAP_ANON | MAP_SHARED;
|
||||
#else // Use "/dev/zero"
|
||||
fd = open("/dev/zero", O_RDWR);
|
||||
flags = MAP_SHARED;
|
||||
if(fd == -1){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
address = mmap( address
|
||||
, size
|
||||
, PROT_READ|PROT_WRITE
|
||||
, flags
|
||||
, fd
|
||||
, 0);
|
||||
|
||||
if(address == MAP_FAILED){
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
|
||||
return detail::raw_mapped_region_creator::create_posix_mapped_region(address, 0, size);
|
||||
}
|
||||
#else
|
||||
{
|
||||
windows_shared_memory anonymous_mapping(create_only, 0, read_write, size);
|
||||
return mapped_region(anonymous_mapping, read_write, 0, size, address);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP
|
||||
@@ -0,0 +1,40 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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/interprocess/containers/container/detail/allocation_type.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
typedef int allocation_type;
|
||||
/// @endcond
|
||||
static const allocation_type allocate_new = boost::interprocess_container::allocate_new;
|
||||
static const allocation_type expand_fwd = boost::interprocess_container::expand_fwd;
|
||||
static const allocation_type expand_bwd = boost::interprocess_container::expand_bwd;
|
||||
static const allocation_type shrink_in_place = boost::interprocess_container::shrink_in_place;
|
||||
static const allocation_type try_shrink_in_place= boost::interprocess_container::try_shrink_in_place;
|
||||
static const allocation_type nothrow_allocation = boost::interprocess_container::nothrow_allocation;
|
||||
static const allocation_type zero_memory = boost::interprocess_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,153 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_CONTAINERS_FWD_HPP
|
||||
#define BOOST_CONTAINERS_CONTAINERS_FWD_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Standard predeclarations
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
//Create namespace to avoid compilation errors
|
||||
}}
|
||||
|
||||
namespace boost{ namespace interprocess_container{ namespace containers_detail{
|
||||
|
||||
namespace bi = boost::intrusive;
|
||||
|
||||
}}}
|
||||
|
||||
namespace std {
|
||||
|
||||
template <class T>
|
||||
class allocator;
|
||||
|
||||
template <class T>
|
||||
struct less;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair;
|
||||
|
||||
template <class CharType>
|
||||
struct char_traits;
|
||||
|
||||
} //namespace std {
|
||||
|
||||
/// @endcond
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Containers
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
#else
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
#endif
|
||||
|
||||
//vector class
|
||||
template <class T
|
||||
,class A = std::allocator<T> >
|
||||
class vector;
|
||||
|
||||
//vector class
|
||||
template <class T
|
||||
,class A = std::allocator<T> >
|
||||
class deque;
|
||||
|
||||
//list class
|
||||
template <class T
|
||||
,class A = std::allocator<T> >
|
||||
class list;
|
||||
|
||||
//slist class
|
||||
template <class T
|
||||
,class Alloc = std::allocator<T> >
|
||||
class slist;
|
||||
|
||||
//set class
|
||||
template <class T
|
||||
,class Pred = std::less<T>
|
||||
,class Alloc = std::allocator<T> >
|
||||
class set;
|
||||
|
||||
//multiset class
|
||||
template <class T
|
||||
,class Pred = std::less<T>
|
||||
,class Alloc = std::allocator<T> >
|
||||
class multiset;
|
||||
|
||||
//map class
|
||||
template <class Key
|
||||
,class T
|
||||
,class Pred = std::less<Key>
|
||||
,class Alloc = std::allocator<std::pair<const Key, T> > >
|
||||
class map;
|
||||
|
||||
//multimap class
|
||||
template <class Key
|
||||
,class T
|
||||
,class Pred = std::less<Key>
|
||||
,class Alloc = std::allocator<std::pair<const Key, T> > >
|
||||
class multimap;
|
||||
|
||||
//flat_set class
|
||||
template <class T
|
||||
,class Pred = std::less<T>
|
||||
,class Alloc = std::allocator<T> >
|
||||
class flat_set;
|
||||
|
||||
//flat_multiset class
|
||||
template <class T
|
||||
,class Pred = std::less<T>
|
||||
,class Alloc = std::allocator<T> >
|
||||
class flat_multiset;
|
||||
|
||||
//flat_map class
|
||||
template <class Key
|
||||
,class T
|
||||
,class Pred = std::less<Key>
|
||||
,class Alloc = std::allocator<std::pair<Key, T> > >
|
||||
class flat_map;
|
||||
|
||||
//flat_multimap class
|
||||
template <class Key
|
||||
,class T
|
||||
,class Pred = std::less<Key>
|
||||
,class Alloc = std::allocator<std::pair<Key, T> > >
|
||||
class flat_multimap;
|
||||
|
||||
//basic_string class
|
||||
template <class CharT
|
||||
,class Traits = std::char_traits<CharT>
|
||||
,class Alloc = std::allocator<CharT> >
|
||||
class basic_string;
|
||||
|
||||
//string class
|
||||
typedef basic_string
|
||||
<char
|
||||
,std::char_traits<char>
|
||||
,std::allocator<char> >
|
||||
string;
|
||||
|
||||
}} //namespace boost { namespace interprocess_container {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_CONTAINERS_FWD_HPP
|
||||
|
||||
1482
libraries/include/boost/interprocess/containers/container/deque.hpp
Normal file
1482
libraries/include/boost/interprocess/containers/container/deque.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,386 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2008. 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_CONTAINERS_ADVANCED_INSERT_INT_HPP
|
||||
#define BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <iterator> //std::iterator_traits
|
||||
#include <algorithm> //std::copy, std::uninitialized_copy
|
||||
#include <new> //placement new
|
||||
#include <cassert>
|
||||
|
||||
namespace boost { namespace interprocess_container { namespace containers_detail {
|
||||
|
||||
//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
|
||||
template<class T, class Iterator>
|
||||
struct advanced_insert_aux_int
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
|
||||
virtual void copy_all_to(Iterator p) = 0;
|
||||
virtual void uninitialized_copy_all_to(Iterator p) = 0;
|
||||
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
|
||||
virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
|
||||
virtual ~advanced_insert_aux_int() {}
|
||||
};
|
||||
|
||||
//This class template will adapt each FwIt types to advanced_insert_aux_int
|
||||
template<class T, class FwdIt, class Iterator>
|
||||
struct advanced_insert_aux_proxy
|
||||
: public advanced_insert_aux_int<T, Iterator>
|
||||
{
|
||||
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
|
||||
advanced_insert_aux_proxy(FwdIt first, FwdIt last)
|
||||
: first_(first), last_(last)
|
||||
{}
|
||||
|
||||
virtual ~advanced_insert_aux_proxy()
|
||||
{}
|
||||
|
||||
virtual void copy_all_to(Iterator p)
|
||||
{ std::copy(first_, last_, p); }
|
||||
|
||||
virtual void uninitialized_copy_all_to(Iterator p)
|
||||
{ boost::interprocess::uninitialized_copy_or_move(first_, last_, p); }
|
||||
|
||||
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
|
||||
{
|
||||
FwdIt mid = first_;
|
||||
std::advance(mid, division_count);
|
||||
if(first_n){
|
||||
boost::interprocess::uninitialized_copy_or_move(first_, mid, pos);
|
||||
first_ = mid;
|
||||
}
|
||||
else{
|
||||
boost::interprocess::uninitialized_copy_or_move(mid, last_, pos);
|
||||
last_ = mid;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
|
||||
{
|
||||
FwdIt mid = first_;
|
||||
std::advance(mid, division_count);
|
||||
if(first_n){
|
||||
std::copy(first_, mid, pos);
|
||||
first_ = mid;
|
||||
}
|
||||
else{
|
||||
std::copy(mid, last_, pos);
|
||||
last_ = mid;
|
||||
}
|
||||
}
|
||||
|
||||
FwdIt first_, last_;
|
||||
};
|
||||
|
||||
//This class template will adapt each FwIt types to advanced_insert_aux_int
|
||||
template<class T, class Iterator, class SizeType>
|
||||
struct default_construct_aux_proxy
|
||||
: public advanced_insert_aux_int<T, Iterator>
|
||||
{
|
||||
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
|
||||
default_construct_aux_proxy(SizeType count)
|
||||
: count_(count)
|
||||
{}
|
||||
|
||||
void uninitialized_copy_impl(Iterator p, const SizeType n)
|
||||
{
|
||||
assert(n <= count_);
|
||||
Iterator orig_p = p;
|
||||
SizeType i = 0;
|
||||
try{
|
||||
for(; i < n; ++i, ++p){
|
||||
new(containers_detail::get_pointer(&*p))T();
|
||||
}
|
||||
}
|
||||
catch(...){
|
||||
while(i--){
|
||||
containers_detail::get_pointer(&*orig_p++)->~T();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
count_ -= n;
|
||||
}
|
||||
|
||||
virtual ~default_construct_aux_proxy()
|
||||
{}
|
||||
|
||||
virtual void copy_all_to(Iterator)
|
||||
{ //This should never be called with any count
|
||||
assert(count_ == 0);
|
||||
}
|
||||
|
||||
virtual void uninitialized_copy_all_to(Iterator p)
|
||||
{ this->uninitialized_copy_impl(p, count_); }
|
||||
|
||||
virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
|
||||
{
|
||||
SizeType new_count;
|
||||
if(first_n){
|
||||
new_count = division_count;
|
||||
}
|
||||
else{
|
||||
assert(difference_type(count_)>= division_count);
|
||||
new_count = count_ - division_count;
|
||||
}
|
||||
this->uninitialized_copy_impl(pos, new_count);
|
||||
}
|
||||
|
||||
virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n)
|
||||
{
|
||||
assert(count_ == 0);
|
||||
SizeType new_count;
|
||||
if(first_n){
|
||||
new_count = division_count;
|
||||
}
|
||||
else{
|
||||
assert(difference_type(count_)>= division_count);
|
||||
new_count = count_ - division_count;
|
||||
}
|
||||
//This function should never called with a count different to zero
|
||||
assert(new_count == 0);
|
||||
(void)new_count;
|
||||
}
|
||||
|
||||
SizeType count_;
|
||||
};
|
||||
|
||||
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
|
||||
|
||||
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/variadic_templates_tools.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <typeinfo>
|
||||
//#include <iostream> //For debugging purposes
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
//This class template will adapt each FwIt types to advanced_insert_aux_int
|
||||
template<class T, class Iterator, class ...Args>
|
||||
struct advanced_insert_aux_emplace
|
||||
: public advanced_insert_aux_int<T, Iterator>
|
||||
{
|
||||
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
|
||||
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
advanced_insert_aux_emplace(Args&&... args)
|
||||
: args_(args...), used_(false)
|
||||
{}
|
||||
|
||||
~advanced_insert_aux_emplace()
|
||||
{}
|
||||
|
||||
virtual void copy_all_to(Iterator p)
|
||||
{ this->priv_copy_all_to(index_tuple_t(), p); }
|
||||
|
||||
virtual void uninitialized_copy_all_to(Iterator p)
|
||||
{ this->priv_uninitialized_copy_all_to(index_tuple_t(), p); }
|
||||
|
||||
virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
|
||||
{ this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
|
||||
|
||||
virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
|
||||
{ this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
|
||||
|
||||
private:
|
||||
template<int ...IdxPack>
|
||||
void priv_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
|
||||
{
|
||||
if(!used_){
|
||||
T object(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
|
||||
*p = boost::interprocess::move(object);
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
template<int ...IdxPack>
|
||||
void priv_uninitialized_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
|
||||
{
|
||||
if(!used_){
|
||||
new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
template<int ...IdxPack>
|
||||
void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
|
||||
{
|
||||
assert(division_count <=1);
|
||||
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
|
||||
if(!used_){
|
||||
new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<int ...IdxPack>
|
||||
void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
|
||||
{
|
||||
assert(division_count <=1);
|
||||
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
|
||||
if(!used_){
|
||||
T object(boost::interprocess::forward<Args>(get<IdxPack>(args_))...);
|
||||
*p = boost::interprocess::move(object);
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
tuple<Args&&...> args_;
|
||||
bool used_;
|
||||
};
|
||||
|
||||
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
|
||||
|
||||
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/value_init.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
//This class template will adapt each FwIt types to advanced_insert_aux_int
|
||||
template<class T, class Iterator>
|
||||
struct advanced_insert_aux_emplace
|
||||
: public advanced_insert_aux_int<T, Iterator>
|
||||
{
|
||||
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
|
||||
advanced_insert_aux_emplace()
|
||||
: used_(false)
|
||||
{}
|
||||
|
||||
~advanced_insert_aux_emplace()
|
||||
{}
|
||||
|
||||
virtual void copy_all_to(Iterator p)
|
||||
{
|
||||
if(!used_){
|
||||
value_init<T>v;
|
||||
*p = boost::interprocess::move(v.m_t);
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void uninitialized_copy_all_to(Iterator p)
|
||||
{
|
||||
if(!used_){
|
||||
new(containers_detail::get_pointer(&*p))T();
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
|
||||
{
|
||||
assert(division_count <=1);
|
||||
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
|
||||
if(!used_){
|
||||
new(containers_detail::get_pointer(&*p))T();
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
|
||||
{
|
||||
assert(division_count <=1);
|
||||
if((first_n && division_count == 1) || (!first_n && division_count == 0)){
|
||||
if(!used_){
|
||||
value_init<T>v;
|
||||
*p = boost::interprocess::move(v.m_t);
|
||||
used_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool used_;
|
||||
};
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<class T, class Iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
|
||||
: public advanced_insert_aux_int<T, Iterator> \
|
||||
{ \
|
||||
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; \
|
||||
\
|
||||
BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
|
||||
( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \
|
||||
: used_(false), BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \
|
||||
\
|
||||
virtual void copy_all_to(Iterator p) \
|
||||
{ \
|
||||
if(!used_){ \
|
||||
T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
|
||||
*p = boost::interprocess::move(v); \
|
||||
used_ = true; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
virtual void uninitialized_copy_all_to(Iterator p) \
|
||||
{ \
|
||||
if(!used_){ \
|
||||
new(containers_detail::get_pointer(&*p))T \
|
||||
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
|
||||
used_ = true; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
virtual void uninitialized_copy_some_and_update \
|
||||
(Iterator p, difference_type division_count, bool first_n) \
|
||||
{ \
|
||||
assert(division_count <=1); \
|
||||
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
|
||||
if(!used_){ \
|
||||
new(containers_detail::get_pointer(&*p))T \
|
||||
(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
|
||||
used_ = true; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
virtual void copy_some_and_update \
|
||||
(Iterator p, difference_type division_count, bool first_n) \
|
||||
{ \
|
||||
assert(division_count <=1); \
|
||||
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
|
||||
if(!used_){ \
|
||||
T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
|
||||
*p = boost::interprocess::move(v); \
|
||||
used_ = true; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
bool used_; \
|
||||
BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \
|
||||
}; \
|
||||
//!
|
||||
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
}}} //namespace boost { namespace interprocess_container { namespace containers_detail {
|
||||
|
||||
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
|
||||
@@ -0,0 +1,215 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
//
|
||||
// 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_CONTAINERS_DETAIL_ALGORITHMS_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/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/get_pointer.hpp>
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/mpl.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/iterators.hpp>
|
||||
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
|
||||
#if !defined(BOOST_HAS_RVALUE_REFS)
|
||||
template<class T>
|
||||
struct has_own_construct_from_it
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
namespace containers_detail {
|
||||
|
||||
template<class T, class InpIt>
|
||||
inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::true_)
|
||||
{
|
||||
T::construct(dest, *source);
|
||||
}
|
||||
|
||||
template<class T, class InpIt>
|
||||
inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::false_)
|
||||
{
|
||||
new((void*)dest)T(*source);
|
||||
}
|
||||
|
||||
} //namespace containers_detail {
|
||||
|
||||
template<class T, class InpIt>
|
||||
inline void construct_in_place(T* dest, InpIt source)
|
||||
{
|
||||
typedef containers_detail::bool_<has_own_construct_from_it<T>::value> boolean_t;
|
||||
containers_detail::construct_in_place_impl(dest, source, boolean_t());
|
||||
}
|
||||
|
||||
#else
|
||||
template<class T, class InpIt>
|
||||
inline void construct_in_place(T* dest, InpIt source)
|
||||
{ ::new((void*)dest)T(*source); }
|
||||
#endif
|
||||
|
||||
template<class T, class U, class D>
|
||||
inline void construct_in_place(T *dest, default_construct_iterator<U, D>)
|
||||
{
|
||||
::new((void*)dest)T();
|
||||
}
|
||||
|
||||
template<class T, class U, class E>
|
||||
inline void construct_in_place(T *dest, emplace_iterator<U, E> ei)
|
||||
{
|
||||
ei.construct_in_place(dest);
|
||||
}
|
||||
|
||||
template<class InIt, class OutIt>
|
||||
struct optimize_assign
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct optimize_assign<const T*, T*>
|
||||
{
|
||||
static const bool value = boost::has_trivial_assign<T>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct optimize_assign<T*, T*>
|
||||
: public optimize_assign<const T*, T*>
|
||||
{};
|
||||
|
||||
template<class InIt, class OutIt>
|
||||
struct optimize_copy
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct optimize_copy<const T*, T*>
|
||||
{
|
||||
static const bool value = boost::has_trivial_copy<T>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct optimize_copy<T*, T*>
|
||||
: public optimize_copy<const T*, T*>
|
||||
{};
|
||||
|
||||
template<class InIt, class OutIt> inline
|
||||
OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest, containers_detail::bool_<false>)
|
||||
{
|
||||
for (; length--; ++dest, ++first)
|
||||
*dest = *first;
|
||||
return dest;
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
T *copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>)
|
||||
{
|
||||
std::size_t size = length*sizeof(T);
|
||||
return (static_cast<T*>(std::memmove(dest, first, size))) + size;
|
||||
}
|
||||
|
||||
template<class InIt, class OutIt> inline
|
||||
OutIt copy_n(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest)
|
||||
{
|
||||
const bool do_optimized_assign = optimize_assign<InIt, OutIt>::value;
|
||||
return copy_n_dispatch(first, length, dest, containers_detail::bool_<do_optimized_assign>());
|
||||
}
|
||||
|
||||
template<class InIt, class FwdIt> inline
|
||||
FwdIt uninitialized_copy_n_dispatch
|
||||
(InIt first,
|
||||
typename std::iterator_traits<InIt>::difference_type count,
|
||||
FwdIt dest, containers_detail::bool_<false>)
|
||||
{
|
||||
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
|
||||
//Save initial destination position
|
||||
FwdIt dest_init = dest;
|
||||
typename std::iterator_traits<InIt>::difference_type new_count = count+1;
|
||||
|
||||
BOOST_TRY{
|
||||
//Try to build objects
|
||||
for (; --new_count; ++dest, ++first){
|
||||
construct_in_place(containers_detail::get_pointer(&*dest), first);
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
//Call destructors
|
||||
new_count = count - new_count;
|
||||
for (; new_count--; ++dest_init){
|
||||
containers_detail::get_pointer(&*dest_init)->~value_type();
|
||||
}
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return dest;
|
||||
}
|
||||
template<class T> inline
|
||||
T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>)
|
||||
{
|
||||
std::size_t size = length*sizeof(T);
|
||||
return (static_cast<T*>(std::memmove(dest, first, size))) + size;
|
||||
}
|
||||
|
||||
template<class InIt, class FwdIt> inline
|
||||
FwdIt uninitialized_copy_n
|
||||
(InIt first,
|
||||
typename std::iterator_traits<InIt>::difference_type count,
|
||||
FwdIt dest)
|
||||
{
|
||||
const bool do_optimized_copy = optimize_copy<InIt, FwdIt>::value;
|
||||
return uninitialized_copy_n_dispatch(first, count, dest, containers_detail::bool_<do_optimized_copy>());
|
||||
}
|
||||
|
||||
// uninitialized_copy_copy
|
||||
// Copies [first1, last1) into [result, result + (last1 - first1)), and
|
||||
// copies [first2, last2) into
|
||||
// [result + (last1 - first1), result + (last1 - first1) + (last2 - first2)).
|
||||
template <class InpIt1, class InpIt2, class FwdIt>
|
||||
FwdIt uninitialized_copy_copy
|
||||
(InpIt1 first1, InpIt1 last1, InpIt2 first2, InpIt2 last2, FwdIt result)
|
||||
{
|
||||
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
|
||||
FwdIt mid = std::uninitialized_copy(first1, last1, result);
|
||||
BOOST_TRY {
|
||||
return std::uninitialized_copy(first2, last2, mid);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
for(;result != mid; ++result){
|
||||
containers_detail::get_pointer(&*result)->~value_type();
|
||||
}
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_ALLOCATION_TYPE_HPP
|
||||
#define BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_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 interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINERS_ALLOCATION_TYPE_HPP
|
||||
@@ -0,0 +1,47 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
|
||||
#define BOOST_CONTAINERS_CONTAINER_DETAIL_CONFIG_INCLUDED
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define BOOST_CONTAINERS_DETAIL_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
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#if defined BOOST_MSVC
|
||||
#pragma warning (pop)
|
||||
#ifdef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
|
||||
#undef BOOST_CONTAINERS_DETAIL_CRT_SECURE_NO_DEPRECATE
|
||||
#undef _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
//
|
||||
// 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_CONTAINERS_DESTROYERS_HPP
|
||||
#define BOOST_CONTAINERS_DESTROYERS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/version_type.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/utilities.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
//!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 typename Allocator::pointer pointer;
|
||||
typedef typename Allocator::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 typename Allocator::pointer pointer;
|
||||
typedef typename Allocator::size_type size_type;
|
||||
|
||||
null_scoped_array_deallocator(pointer, Allocator&, size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_destructor_n
|
||||
{
|
||||
typedef typename Allocator::pointer pointer;
|
||||
typedef typename Allocator::value_type value_type;
|
||||
typedef typename Allocator::size_type size_type;
|
||||
|
||||
pointer m_p;
|
||||
size_type m_n;
|
||||
|
||||
scoped_destructor_n(pointer p, size_type n)
|
||||
: m_p(p), m_n(n)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ m_p = 0; }
|
||||
|
||||
void increment_size(size_type inc)
|
||||
{ m_n += inc; }
|
||||
|
||||
~scoped_destructor_n()
|
||||
{
|
||||
if(!m_p) return;
|
||||
value_type *raw_ptr = containers_detail::get_pointer(m_p);
|
||||
for(std::size_t i = 0; i < m_n; ++i, ++raw_ptr)
|
||||
raw_ptr->~value_type();
|
||||
}
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct null_scoped_destructor_n
|
||||
{
|
||||
typedef typename Allocator::pointer pointer;
|
||||
typedef typename Allocator::size_type size_type;
|
||||
|
||||
null_scoped_destructor_n(pointer, size_type)
|
||||
{}
|
||||
|
||||
void increment_size(size_type)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{}
|
||||
};
|
||||
|
||||
template <class A>
|
||||
class allocator_destroyer
|
||||
{
|
||||
typedef typename A::value_type value_type;
|
||||
typedef containers_detail::integral_constant<unsigned,
|
||||
boost::interprocess_container::containers_detail::
|
||||
version<A>::value> alloc_version;
|
||||
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
|
||||
|
||||
private:
|
||||
A & a_;
|
||||
|
||||
private:
|
||||
void priv_deallocate(const typename A::pointer &p, allocator_v1)
|
||||
{ a_.deallocate(p, 1); }
|
||||
|
||||
void priv_deallocate(const typename A::pointer &p, allocator_v2)
|
||||
{ a_.deallocate_one(p); }
|
||||
|
||||
public:
|
||||
allocator_destroyer(A &a)
|
||||
: a_(a)
|
||||
{}
|
||||
|
||||
void operator()(const typename A::pointer &p)
|
||||
{
|
||||
containers_detail::get_pointer(p)->~value_type();
|
||||
priv_deallocate(p, alloc_version());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} //namespace containers_detail {
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DESTROYERS_HPP
|
||||
@@ -0,0 +1,837 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||
// This code accompanies the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
// Permission to use, copy, modify, distribute and sell this software 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.
|
||||
// The author or Addison-Welsey Longman make no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of this file come from AssocVector.h file from Loki library
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINERS_FLAT_TREE_HPP
|
||||
#define BOOST_CONTAINERS_FLAT_TREE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/type_traits/has_trivial_destructor.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/utilities.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/pair.hpp>
|
||||
#include <boost/interprocess/containers/container/vector.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/value_init.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess_container {
|
||||
|
||||
namespace containers_detail {
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
class flat_tree
|
||||
{
|
||||
typedef boost::interprocess_container::vector<Value, Alloc> vector_t;
|
||||
typedef Alloc allocator_t;
|
||||
|
||||
public:
|
||||
class value_compare
|
||||
: private Compare
|
||||
{
|
||||
typedef Value first_argument_type;
|
||||
typedef Value second_argument_type;
|
||||
typedef bool return_type;
|
||||
public:
|
||||
value_compare(const Compare &pred)
|
||||
: Compare(pred)
|
||||
{}
|
||||
|
||||
bool operator()(const Value& lhs, const Value& rhs) const
|
||||
{
|
||||
KeyOfValue key_extract;
|
||||
return Compare::operator()(key_extract(lhs), key_extract(rhs));
|
||||
}
|
||||
|
||||
const Compare &get_comp() const
|
||||
{ return *this; }
|
||||
|
||||
Compare &get_comp()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
private:
|
||||
struct Data
|
||||
//Inherit from value_compare to do EBO
|
||||
: public value_compare
|
||||
{
|
||||
public:
|
||||
Data(const Compare &comp,
|
||||
const vector_t &vect)
|
||||
: value_compare(comp), m_vect(vect){}
|
||||
|
||||
Data(const value_compare &comp,
|
||||
const vector_t &vect)
|
||||
: value_compare(comp), m_vect(vect){}
|
||||
|
||||
Data(const Compare &comp,
|
||||
const allocator_t &alloc)
|
||||
: value_compare(comp), m_vect(alloc){}
|
||||
public:
|
||||
vector_t m_vect;
|
||||
};
|
||||
|
||||
Data m_data;
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(flat_tree)
|
||||
|
||||
typedef typename vector_t::value_type value_type;
|
||||
typedef typename vector_t::pointer pointer;
|
||||
typedef typename vector_t::const_pointer const_pointer;
|
||||
typedef typename vector_t::reference reference;
|
||||
typedef typename vector_t::const_reference const_reference;
|
||||
typedef Key key_type;
|
||||
typedef Compare key_compare;
|
||||
typedef typename vector_t::allocator_type allocator_type;
|
||||
typedef allocator_type stored_allocator_type;
|
||||
typedef typename allocator_type::size_type size_type;
|
||||
typedef typename allocator_type::difference_type difference_type;
|
||||
typedef typename vector_t::iterator iterator;
|
||||
typedef typename vector_t::const_iterator const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
|
||||
// allocation/deallocation
|
||||
flat_tree(const Compare& comp = Compare(),
|
||||
const allocator_type& a = allocator_type())
|
||||
: m_data(comp, a)
|
||||
{ }
|
||||
|
||||
flat_tree(const flat_tree& x)
|
||||
: m_data(x.m_data, x.m_data.m_vect)
|
||||
{ }
|
||||
|
||||
flat_tree(BOOST_INTERPROCESS_RV_REF(flat_tree) x)
|
||||
: m_data(boost::interprocess::move(x.m_data))
|
||||
{ }
|
||||
|
||||
~flat_tree()
|
||||
{ }
|
||||
|
||||
flat_tree& operator=(const flat_tree& x)
|
||||
{ m_data = x.m_data; return *this; }
|
||||
|
||||
flat_tree& operator=(BOOST_INTERPROCESS_RV_REF(flat_tree) mx)
|
||||
{ m_data = boost::interprocess::move(mx.m_data); return *this; }
|
||||
|
||||
public:
|
||||
// accessors:
|
||||
Compare key_comp() const
|
||||
{ return this->m_data.get_comp(); }
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{ return this->m_data.m_vect.get_allocator(); }
|
||||
|
||||
const stored_allocator_type &get_stored_allocator() const
|
||||
{ return this->m_data.m_vect.get_stored_allocator(); }
|
||||
|
||||
stored_allocator_type &get_stored_allocator()
|
||||
{ return this->m_data.m_vect.get_stored_allocator(); }
|
||||
|
||||
iterator begin()
|
||||
{ return this->m_data.m_vect.begin(); }
|
||||
|
||||
const_iterator begin() const
|
||||
{ return this->cbegin(); }
|
||||
|
||||
const_iterator cbegin() const
|
||||
{ return this->m_data.m_vect.begin(); }
|
||||
|
||||
iterator end()
|
||||
{ return this->m_data.m_vect.end(); }
|
||||
|
||||
const_iterator end() const
|
||||
{ return this->cend(); }
|
||||
|
||||
const_iterator cend() const
|
||||
{ return this->m_data.m_vect.end(); }
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{ return reverse_iterator(this->end()); }
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{ return this->crbegin(); }
|
||||
|
||||
const_reverse_iterator crbegin() const
|
||||
{ return const_reverse_iterator(this->cend()); }
|
||||
|
||||
reverse_iterator rend()
|
||||
{ return reverse_iterator(this->begin()); }
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{ return this->crend(); }
|
||||
|
||||
const_reverse_iterator crend() const
|
||||
{ return const_reverse_iterator(this->cbegin()); }
|
||||
|
||||
bool empty() const
|
||||
{ return this->m_data.m_vect.empty(); }
|
||||
|
||||
size_type size() const
|
||||
{ return this->m_data.m_vect.size(); }
|
||||
|
||||
size_type max_size() const
|
||||
{ return this->m_data.m_vect.max_size(); }
|
||||
|
||||
void swap(flat_tree& other)
|
||||
{
|
||||
value_compare& mycomp = this->m_data;
|
||||
value_compare& othercomp = other.m_data;
|
||||
containers_detail::do_swap(mycomp, othercomp);
|
||||
vector_t & myvect = this->m_data.m_vect;
|
||||
vector_t & othervect = other.m_data.m_vect;
|
||||
myvect.swap(othervect);
|
||||
}
|
||||
|
||||
public:
|
||||
// insert/erase
|
||||
std::pair<iterator,bool> insert_unique(const value_type& val)
|
||||
{
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<iterator,bool> insert_unique(BOOST_INTERPROCESS_RV_REF(value_type) val)
|
||||
{
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move(val));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
iterator insert_equal(const value_type& val)
|
||||
{
|
||||
iterator i = this->upper_bound(KeyOfValue()(val));
|
||||
i = this->m_data.m_vect.insert(i, val);
|
||||
return i;
|
||||
}
|
||||
|
||||
iterator insert_equal(BOOST_INTERPROCESS_RV_REF(value_type) mval)
|
||||
{
|
||||
iterator i = this->upper_bound(KeyOfValue()(mval));
|
||||
i = this->m_data.m_vect.insert(i, boost::interprocess::move(mval));
|
||||
return i;
|
||||
}
|
||||
|
||||
iterator insert_unique(const_iterator pos, const value_type& val)
|
||||
{
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, val);
|
||||
}
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
iterator insert_unique(const_iterator pos, BOOST_INTERPROCESS_RV_REF(value_type) mval)
|
||||
{
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move(mval));
|
||||
}
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
iterator insert_equal(const_iterator pos, const value_type& val)
|
||||
{
|
||||
insert_commit_data data;
|
||||
priv_insert_equal_prepare(pos, val, data);
|
||||
return priv_insert_commit(data, val);
|
||||
}
|
||||
|
||||
iterator insert_equal(const_iterator pos, BOOST_INTERPROCESS_RV_REF(value_type) mval)
|
||||
{
|
||||
insert_commit_data data;
|
||||
priv_insert_equal_prepare(pos, mval, data);
|
||||
return priv_insert_commit(data, boost::interprocess::move(mval));
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void insert_unique(InIt first, InIt last)
|
||||
{
|
||||
for ( ; first != last; ++first)
|
||||
this->insert_unique(*first);
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void insert_equal(InIt first, InIt last)
|
||||
{
|
||||
typedef typename
|
||||
std::iterator_traits<InIt>::iterator_category ItCat;
|
||||
priv_insert_equal(first, last, ItCat());
|
||||
}
|
||||
|
||||
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_unique(Args&&... args)
|
||||
{
|
||||
value_type val(boost::interprocess::forward<Args>(args)...);
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret =
|
||||
priv_insert_unique_prepare(val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
|
||||
}
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint_unique(const_iterator hint, Args&&... args)
|
||||
{
|
||||
value_type val(boost::interprocess::forward<Args>(args)...);
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
|
||||
}
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_equal(Args&&... args)
|
||||
{
|
||||
value_type val(boost::interprocess::forward<Args>(args)...);
|
||||
iterator i = this->upper_bound(KeyOfValue()(val));
|
||||
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val));
|
||||
return i;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_hint_equal(const_iterator hint, Args&&... args)
|
||||
{
|
||||
value_type val(boost::interprocess::forward<Args>(args)...);
|
||||
insert_commit_data data;
|
||||
priv_insert_equal_prepare(hint, val, data);
|
||||
return priv_insert_commit(data, boost::interprocess::move<value_type>(val));
|
||||
}
|
||||
|
||||
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
iterator emplace_unique()
|
||||
{
|
||||
containers_detail::value_init<value_type> vval;
|
||||
value_type &val = vval.m_t;
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret =
|
||||
priv_insert_unique_prepare(val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
|
||||
}
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
iterator emplace_hint_unique(const_iterator hint)
|
||||
{
|
||||
containers_detail::value_init<value_type> vval;
|
||||
value_type &val = vval.m_t;
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
|
||||
if(ret.second){
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val));
|
||||
}
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
iterator emplace_equal()
|
||||
{
|
||||
containers_detail::value_init<value_type> vval;
|
||||
value_type &val = vval.m_t;
|
||||
iterator i = this->upper_bound(KeyOfValue()(val));
|
||||
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val));
|
||||
return i;
|
||||
}
|
||||
|
||||
iterator emplace_hint_equal(const_iterator hint)
|
||||
{
|
||||
containers_detail::value_init<value_type> vval;
|
||||
value_type &val = vval.m_t;
|
||||
insert_commit_data data;
|
||||
priv_insert_equal_prepare(hint, val, data);
|
||||
return priv_insert_commit(data, boost::interprocess::move<value_type>(val));
|
||||
}
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
|
||||
{ \
|
||||
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
|
||||
insert_commit_data data; \
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
|
||||
if(ret.second){ \
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
|
||||
} \
|
||||
return ret.first; \
|
||||
} \
|
||||
\
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
iterator emplace_hint_unique(const_iterator hint, \
|
||||
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
|
||||
{ \
|
||||
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
|
||||
insert_commit_data data; \
|
||||
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
|
||||
if(ret.second){ \
|
||||
ret.first = priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
|
||||
} \
|
||||
return ret.first; \
|
||||
} \
|
||||
\
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
|
||||
{ \
|
||||
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
|
||||
iterator i = this->upper_bound(KeyOfValue()(val)); \
|
||||
i = this->m_data.m_vect.insert(i, boost::interprocess::move<value_type>(val)); \
|
||||
return i; \
|
||||
} \
|
||||
\
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
iterator emplace_hint_equal(const_iterator hint, \
|
||||
BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
|
||||
{ \
|
||||
value_type val(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
|
||||
insert_commit_data data; \
|
||||
priv_insert_equal_prepare(hint, val, data); \
|
||||
return priv_insert_commit(data, boost::interprocess::move<value_type>(val)); \
|
||||
} \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{ return this->m_data.m_vect.erase(position); }
|
||||
|
||||
size_type erase(const key_type& k)
|
||||
{
|
||||
std::pair<iterator,iterator > itp = this->equal_range(k);
|
||||
size_type ret = static_cast<size_type>(itp.second-itp.first);
|
||||
if (ret){
|
||||
this->m_data.m_vect.erase(itp.first, itp.second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{ return this->m_data.m_vect.erase(first, last); }
|
||||
|
||||
void clear()
|
||||
{ this->m_data.m_vect.clear(); }
|
||||
|
||||
//! <b>Effects</b>: Tries to deallocate the excess of memory created
|
||||
// with previous allocations. The size of the vector is unchanged
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to size().
|
||||
void shrink_to_fit()
|
||||
{ this->m_data.m_vect.shrink_to_fit(); }
|
||||
|
||||
// set operations:
|
||||
iterator find(const key_type& k)
|
||||
{
|
||||
const Compare &key_comp = this->m_data.get_comp();
|
||||
iterator i = this->lower_bound(k);
|
||||
|
||||
if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
|
||||
i = this->end();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
const_iterator find(const key_type& k) const
|
||||
{
|
||||
const Compare &key_comp = this->m_data.get_comp();
|
||||
const_iterator i = this->lower_bound(k);
|
||||
|
||||
if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
|
||||
i = this->end();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
size_type count(const key_type& k) const
|
||||
{
|
||||
std::pair<const_iterator, const_iterator> p = this->equal_range(k);
|
||||
size_type n = p.second - p.first;
|
||||
return n;
|
||||
}
|
||||
|
||||
iterator lower_bound(const key_type& k)
|
||||
{ return this->priv_lower_bound(this->begin(), this->end(), k); }
|
||||
|
||||
const_iterator lower_bound(const key_type& k) const
|
||||
{ return this->priv_lower_bound(this->begin(), this->end(), k); }
|
||||
|
||||
iterator upper_bound(const key_type& k)
|
||||
{ return this->priv_upper_bound(this->begin(), this->end(), k); }
|
||||
|
||||
const_iterator upper_bound(const key_type& k) const
|
||||
{ return this->priv_upper_bound(this->begin(), this->end(), k); }
|
||||
|
||||
std::pair<iterator,iterator> equal_range(const key_type& k)
|
||||
{ return this->priv_equal_range(this->begin(), this->end(), k); }
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
|
||||
{ return this->priv_equal_range(this->begin(), this->end(), k); }
|
||||
|
||||
size_type capacity() const
|
||||
{ return this->m_data.m_vect.capacity(); }
|
||||
|
||||
void reserve(size_type count)
|
||||
{ this->m_data.m_vect.reserve(count); }
|
||||
|
||||
private:
|
||||
struct insert_commit_data
|
||||
{
|
||||
const_iterator position;
|
||||
};
|
||||
|
||||
// insert/erase
|
||||
void priv_insert_equal_prepare
|
||||
(const_iterator pos, const value_type& val, insert_commit_data &data)
|
||||
{
|
||||
// N1780
|
||||
// To insert val at pos:
|
||||
// if pos == end || val <= *pos
|
||||
// if pos == begin || val >= *(pos-1)
|
||||
// insert val before pos
|
||||
// else
|
||||
// insert val before upper_bound(val)
|
||||
// else if pos+1 == end || val <= *(pos+1)
|
||||
// insert val after pos
|
||||
// else
|
||||
// insert val before lower_bound(val)
|
||||
const value_compare &value_comp = this->m_data;
|
||||
|
||||
if(pos == this->cend() || !value_comp(*pos, val)){
|
||||
if (pos == this->cbegin() || !value_comp(val, pos[-1])){
|
||||
data.position = pos;
|
||||
}
|
||||
else{
|
||||
data.position =
|
||||
this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
|
||||
}
|
||||
}
|
||||
//Works, but increases code complexity
|
||||
//else if (++pos == this->end() || !value_comp(*pos, val)){
|
||||
// return this->m_data.m_vect.insert(pos, val);
|
||||
//}
|
||||
else{
|
||||
data.position =
|
||||
this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<iterator,bool> priv_insert_unique_prepare
|
||||
(const_iterator beg, const_iterator end, const value_type& val, insert_commit_data &commit_data)
|
||||
{
|
||||
const value_compare &value_comp = this->m_data;
|
||||
commit_data.position = this->priv_lower_bound(beg, end, KeyOfValue()(val));
|
||||
return std::pair<iterator,bool>
|
||||
( *reinterpret_cast<iterator*>(&commit_data.position)
|
||||
, commit_data.position == end || value_comp(val, *commit_data.position));
|
||||
}
|
||||
|
||||
std::pair<iterator,bool> priv_insert_unique_prepare
|
||||
(const value_type& val, insert_commit_data &commit_data)
|
||||
{ return priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); }
|
||||
|
||||
std::pair<iterator,bool> priv_insert_unique_prepare
|
||||
(const_iterator pos, const value_type& val, insert_commit_data &commit_data)
|
||||
{
|
||||
//N1780. Props to Howard Hinnant!
|
||||
//To insert val at pos:
|
||||
//if pos == end || val <= *pos
|
||||
// if pos == begin || val >= *(pos-1)
|
||||
// insert val before pos
|
||||
// else
|
||||
// insert val before upper_bound(val)
|
||||
//else if pos+1 == end || val <= *(pos+1)
|
||||
// insert val after pos
|
||||
//else
|
||||
// insert val before lower_bound(val)
|
||||
const value_compare &value_comp = this->m_data;
|
||||
|
||||
if(pos == this->cend() || value_comp(val, *pos)){
|
||||
if(pos != this->cbegin() && !value_comp(val, pos[-1])){
|
||||
if(value_comp(pos[-1], val)){
|
||||
commit_data.position = pos;
|
||||
return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), true);
|
||||
}
|
||||
else{
|
||||
return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), false);
|
||||
}
|
||||
}
|
||||
return this->priv_insert_unique_prepare(this->cbegin(), pos, val, commit_data);
|
||||
}
|
||||
|
||||
// Works, but increases code complexity
|
||||
//Next check
|
||||
//else if (value_comp(*pos, val) && !value_comp(pos[1], val)){
|
||||
// if(value_comp(val, pos[1])){
|
||||
// commit_data.position = pos+1;
|
||||
// return std::pair<iterator,bool>(pos+1, true);
|
||||
// }
|
||||
// else{
|
||||
// return std::pair<iterator,bool>(pos+1, false);
|
||||
// }
|
||||
//}
|
||||
else{
|
||||
//[... pos ... val ... ]
|
||||
//The hint is before the insertion position, so insert it
|
||||
//in the remaining range
|
||||
return this->priv_insert_unique_prepare(pos, this->end(), val, commit_data);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Convertible>
|
||||
iterator priv_insert_commit
|
||||
(insert_commit_data &commit_data, BOOST_INTERPROCESS_FWD_REF(Convertible) convertible)
|
||||
{
|
||||
return this->m_data.m_vect.insert
|
||||
( commit_data.position
|
||||
, boost::interprocess::forward<Convertible>(convertible));
|
||||
}
|
||||
|
||||
template <class RanIt>
|
||||
RanIt priv_lower_bound(RanIt first, RanIt last,
|
||||
const key_type & key) const
|
||||
{
|
||||
const Compare &key_comp = this->m_data.get_comp();
|
||||
KeyOfValue key_extract;
|
||||
difference_type len = last - first, half;
|
||||
RanIt middle;
|
||||
|
||||
while (len > 0) {
|
||||
half = len >> 1;
|
||||
middle = first;
|
||||
middle += half;
|
||||
|
||||
if (key_comp(key_extract(*middle), key)) {
|
||||
++middle;
|
||||
first = middle;
|
||||
len = len - half - 1;
|
||||
}
|
||||
else
|
||||
len = half;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class RanIt>
|
||||
RanIt priv_upper_bound(RanIt first, RanIt last,
|
||||
const key_type & key) const
|
||||
{
|
||||
const Compare &key_comp = this->m_data.get_comp();
|
||||
KeyOfValue key_extract;
|
||||
difference_type len = last - first, half;
|
||||
RanIt middle;
|
||||
|
||||
while (len > 0) {
|
||||
half = len >> 1;
|
||||
middle = first;
|
||||
middle += half;
|
||||
|
||||
if (key_comp(key, key_extract(*middle))) {
|
||||
len = half;
|
||||
}
|
||||
else{
|
||||
first = ++middle;
|
||||
len = len - half - 1;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class RanIt>
|
||||
std::pair<RanIt, RanIt>
|
||||
priv_equal_range(RanIt first, RanIt last, const key_type& key) const
|
||||
{
|
||||
const Compare &key_comp = this->m_data.get_comp();
|
||||
KeyOfValue key_extract;
|
||||
difference_type len = last - first, half;
|
||||
RanIt middle, left, right;
|
||||
|
||||
while (len > 0) {
|
||||
half = len >> 1;
|
||||
middle = first;
|
||||
middle += half;
|
||||
|
||||
if (key_comp(key_extract(*middle), key)){
|
||||
first = middle;
|
||||
++first;
|
||||
len = len - half - 1;
|
||||
}
|
||||
else if (key_comp(key, key_extract(*middle))){
|
||||
len = half;
|
||||
}
|
||||
else {
|
||||
left = this->priv_lower_bound(first, middle, key);
|
||||
first += len;
|
||||
right = this->priv_upper_bound(++middle, first, key);
|
||||
return std::pair<RanIt, RanIt>(left, right);
|
||||
}
|
||||
}
|
||||
return std::pair<RanIt, RanIt>(first, first);
|
||||
}
|
||||
|
||||
template <class FwdIt>
|
||||
void priv_insert_equal(FwdIt first, FwdIt last, std::forward_iterator_tag)
|
||||
{
|
||||
size_type len = static_cast<size_type>(std::distance(first, last));
|
||||
this->reserve(this->size()+len);
|
||||
this->priv_insert_equal(first, last, std::input_iterator_tag());
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void priv_insert_equal(InIt first, InIt last, std::input_iterator_tag)
|
||||
{
|
||||
for ( ; first != last; ++first)
|
||||
this->insert_equal(*first);
|
||||
}
|
||||
|
||||
/*
|
||||
template <class FwdIt>
|
||||
void priv_insert_unique(FwdIt first, FwdIt last, std::forward_iterator_tag)
|
||||
{
|
||||
size_type len = static_cast<size_type>(std::distance(first, last));
|
||||
this->reserve(this->size()+len);
|
||||
priv_insert_unique(first, last, std::input_iterator_tag());
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void priv_insert_unique(InIt first, InIt last, std::input_iterator_tag)
|
||||
{
|
||||
for ( ; first != last; ++first)
|
||||
this->insert_unique(*first);
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
inline bool
|
||||
operator==(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
|
||||
const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
|
||||
{
|
||||
return x.size() == y.size() &&
|
||||
std::equal(x.begin(), x.end(), y.begin());
|
||||
}
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
inline bool
|
||||
operator<(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
|
||||
const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
|
||||
{
|
||||
return std::lexicographical_compare(x.begin(), x.end(),
|
||||
y.begin(), y.end());
|
||||
}
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
inline bool
|
||||
operator!=(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
|
||||
const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
|
||||
{ return !(x == y); }
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
inline bool
|
||||
operator>(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
|
||||
const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
|
||||
{ return y < x; }
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
inline bool
|
||||
operator<=(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
|
||||
const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
|
||||
{ return !(y < x); }
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
inline bool
|
||||
operator>=(const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
|
||||
const flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
|
||||
{ return !(x < y); }
|
||||
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
class Compare, class Alloc>
|
||||
inline void
|
||||
swap(flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& x,
|
||||
flat_tree<Key,Value,KeyOfValue,Compare,Alloc>& y)
|
||||
{ x.swap(y); }
|
||||
|
||||
} //namespace containers_detail {
|
||||
|
||||
} //namespace interprocess_container {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!has_trivial_destructor_after_move<> == true_type
|
||||
//!specialization for optimizations
|
||||
template <class K, class V, class KOV,
|
||||
class C, class A>
|
||||
struct has_trivial_destructor_after_move<boost::interprocess_container::containers_detail::flat_tree<K, V, KOV, C, A> >
|
||||
{
|
||||
static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINERS_FLAT_TREE_HPP
|
||||
@@ -0,0 +1,492 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
// (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_CONTAINERS_DETAIL_ITERATORS_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
|
||||
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
#include <boost/interprocess/containers/container/detail/variadic_templates_tools.hpp>
|
||||
#else
|
||||
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
|
||||
#endif
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_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;
|
||||
}
|
||||
|
||||
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->() 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;
|
||||
}
|
||||
|
||||
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); }
|
||||
|
||||
const T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
const T* operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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->() 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 E>
|
||||
class emplace_iterator
|
||||
: public std::iterator
|
||||
<std::random_access_iterator_tag, T, std::ptrdiff_t, const T*, const T &>
|
||||
{
|
||||
typedef emplace_iterator this_type;
|
||||
|
||||
public:
|
||||
explicit emplace_iterator(E&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;
|
||||
}
|
||||
|
||||
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 std::ptrdiff_t operator- (const this_type& i, const this_type& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
this_type& operator+=(std::ptrdiff_t off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
this_type operator+(std::ptrdiff_t off) const
|
||||
{
|
||||
this_type other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend this_type operator+(std::ptrdiff_t off, const this_type& right)
|
||||
{ return right + off; }
|
||||
|
||||
this_type& operator-=(std::ptrdiff_t off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
this_type operator-(std::ptrdiff_t off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
const T& operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
const T* operator->() const
|
||||
{ return &(dereference()); }
|
||||
|
||||
void construct_in_place(T* ptr)
|
||||
{ (*m_pe)(ptr); }
|
||||
|
||||
private:
|
||||
std::ptrdiff_t m_num;
|
||||
E * 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(std::ptrdiff_t n)
|
||||
{ m_num -= n; }
|
||||
|
||||
std::ptrdiff_t distance_to(const this_type &other)const
|
||||
{ return m_num - other.m_num; }
|
||||
};
|
||||
|
||||
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
template<class T, class ...Args>
|
||||
struct emplace_functor
|
||||
{
|
||||
typedef typename containers_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
emplace_functor(Args&&... args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
void operator()(T *ptr)
|
||||
{ emplace_functor::inplace_impl(ptr, index_tuple_t()); }
|
||||
|
||||
template<int ...IdxPack>
|
||||
void inplace_impl(T* ptr, const containers_detail::index_tuple<IdxPack...>&)
|
||||
{ ::new(ptr) T(boost::interprocess::forward<Args>(containers_detail::get<IdxPack>(args_))...); }
|
||||
|
||||
containers_detail::tuple<Args&&...> args_;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class T>
|
||||
struct emplace_functor
|
||||
{
|
||||
emplace_functor()
|
||||
{}
|
||||
void operator()(T *ptr)
|
||||
{ new(ptr) T(); }
|
||||
};
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template <class T, BOOST_PP_ENUM_PARAMS(n, class P) > \
|
||||
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_CONTAINERS_PP_PARAM_LIST, _) ) \
|
||||
: BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \
|
||||
\
|
||||
void operator()(T *ptr) \
|
||||
{ \
|
||||
new(ptr)T (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \
|
||||
} \
|
||||
BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \
|
||||
}; \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
#endif
|
||||
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_ITERATORS_HPP
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
//
|
||||
// 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_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
|
||||
#define BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
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:
|
||||
enum { 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 containers_detail {
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_MPL_HPP
|
||||
|
||||
@@ -0,0 +1,554 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/utilities.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/transform_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
template<class VoidPointer>
|
||||
class basic_multiallocation_slist
|
||||
{
|
||||
public:
|
||||
typedef VoidPointer void_pointer;
|
||||
|
||||
private:
|
||||
static VoidPointer &priv_get_ref(const VoidPointer &p)
|
||||
{ return *static_cast<void_pointer*>(containers_detail::get_pointer(p)); }
|
||||
|
||||
basic_multiallocation_slist(basic_multiallocation_slist &);
|
||||
basic_multiallocation_slist &operator=(basic_multiallocation_slist &);
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_slist)
|
||||
|
||||
//!This iterator is returned by "allocate_many" functions so that
|
||||
//!the user can access the multiple buffers allocated in a single call
|
||||
class iterator
|
||||
: public std::iterator<std::input_iterator_tag, char>
|
||||
{
|
||||
friend class basic_multiallocation_slist<void_pointer>;
|
||||
void unspecified_bool_type_func() const {}
|
||||
typedef void (iterator::*unspecified_bool_type)() const;
|
||||
|
||||
iterator(void_pointer node_range)
|
||||
: next_node_(node_range)
|
||||
{}
|
||||
|
||||
public:
|
||||
typedef char value_type;
|
||||
typedef value_type & reference;
|
||||
typedef value_type * pointer;
|
||||
|
||||
iterator()
|
||||
: next_node_(0)
|
||||
{}
|
||||
|
||||
iterator &operator=(const iterator &other)
|
||||
{ next_node_ = other.next_node_; return *this; }
|
||||
|
||||
public:
|
||||
iterator& operator++()
|
||||
{
|
||||
next_node_ = *static_cast<void_pointer*>(containers_detail::get_pointer(next_node_));
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int)
|
||||
{
|
||||
iterator result(*this);
|
||||
++*this;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator== (const iterator& other) const
|
||||
{ return next_node_ == other.next_node_; }
|
||||
|
||||
bool operator!= (const iterator& other) const
|
||||
{ return !operator== (other); }
|
||||
|
||||
reference operator*() const
|
||||
{ return *static_cast<char*>(containers_detail::get_pointer(next_node_)); }
|
||||
|
||||
operator unspecified_bool_type() const
|
||||
{ return next_node_? &iterator::unspecified_bool_type_func : 0; }
|
||||
|
||||
pointer operator->() const
|
||||
{ return &(*(*this)); }
|
||||
|
||||
private:
|
||||
void_pointer next_node_;
|
||||
};
|
||||
|
||||
private:
|
||||
iterator it_;
|
||||
|
||||
public:
|
||||
basic_multiallocation_slist()
|
||||
: it_(iterator())
|
||||
{}
|
||||
|
||||
basic_multiallocation_slist(void_pointer p)
|
||||
: it_(p ? iterator_to(p) : iterator())
|
||||
{}
|
||||
|
||||
basic_multiallocation_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
|
||||
: it_(iterator())
|
||||
{ this->swap(other); }
|
||||
|
||||
basic_multiallocation_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other)
|
||||
{
|
||||
basic_multiallocation_slist tmp(boost::interprocess::move(other));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{ return !it_; }
|
||||
|
||||
iterator before_begin() const
|
||||
{ return iterator(void_pointer(const_cast<void*>(static_cast<const void*>(&it_.next_node_)))); }
|
||||
|
||||
iterator begin() const
|
||||
{ return it_; }
|
||||
|
||||
iterator end() const
|
||||
{ return iterator(); }
|
||||
|
||||
void clear()
|
||||
{ this->it_.next_node_ = void_pointer(0); }
|
||||
|
||||
iterator insert_after(iterator it, void_pointer m)
|
||||
{
|
||||
priv_get_ref(m) = priv_get_ref(it.next_node_);
|
||||
priv_get_ref(it.next_node_) = m;
|
||||
return iterator(m);
|
||||
}
|
||||
|
||||
void push_front(void_pointer m)
|
||||
{
|
||||
priv_get_ref(m) = this->it_.next_node_;
|
||||
this->it_.next_node_ = m;
|
||||
}
|
||||
|
||||
void pop_front()
|
||||
{ ++it_; }
|
||||
|
||||
void *front() const
|
||||
{ return containers_detail::get_pointer(it_.next_node_); }
|
||||
|
||||
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
|
||||
{
|
||||
if (after_this != before_begin && after_this != before_end && before_begin != before_end) {
|
||||
void_pointer next_b = priv_get_ref(before_begin.next_node_);
|
||||
void_pointer next_e = priv_get_ref(before_end.next_node_);
|
||||
void_pointer next_p = priv_get_ref(after_this.next_node_);
|
||||
priv_get_ref(before_begin.next_node_) = next_e;
|
||||
priv_get_ref(before_end.next_node_) = next_p;
|
||||
priv_get_ref(after_this.next_node_) = next_b;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(basic_multiallocation_slist &other_chain)
|
||||
{
|
||||
std::swap(this->it_, other_chain.it_);
|
||||
}
|
||||
|
||||
static iterator iterator_to(void_pointer p)
|
||||
{ return iterator(p); }
|
||||
|
||||
void_pointer extract_data()
|
||||
{
|
||||
void_pointer ret = empty() ? void_pointer(0) : void_pointer(&*it_);
|
||||
it_ = iterator();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class basic_multiallocation_cached_slist
|
||||
{
|
||||
private:
|
||||
basic_multiallocation_slist<VoidPointer> slist_;
|
||||
typename basic_multiallocation_slist<VoidPointer>::iterator last_;
|
||||
|
||||
basic_multiallocation_cached_slist(basic_multiallocation_cached_slist &);
|
||||
basic_multiallocation_cached_slist &operator=(basic_multiallocation_cached_slist &);
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_slist)
|
||||
|
||||
typedef typename basic_multiallocation_slist<VoidPointer>::void_pointer void_pointer;
|
||||
typedef typename basic_multiallocation_slist<VoidPointer>::iterator iterator;
|
||||
|
||||
basic_multiallocation_cached_slist()
|
||||
: slist_(), last_(slist_.before_begin())
|
||||
{}
|
||||
/*
|
||||
basic_multiallocation_cached_slist(iterator first_node)
|
||||
: slist_(first_node), last_(slist_.before_begin())
|
||||
{
|
||||
iterator end;
|
||||
while(first_node != end){
|
||||
++last_;
|
||||
}
|
||||
}*/
|
||||
|
||||
basic_multiallocation_cached_slist(void_pointer p1, void_pointer p2)
|
||||
: slist_(p1), last_(p2 ? iterator_to(p2) : slist_.before_begin())
|
||||
{}
|
||||
|
||||
basic_multiallocation_cached_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
|
||||
: slist_(), last_(slist_.before_begin())
|
||||
{ this->swap(other); }
|
||||
|
||||
basic_multiallocation_cached_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other)
|
||||
{
|
||||
basic_multiallocation_cached_slist tmp(boost::interprocess::move(other));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{ return slist_.empty(); }
|
||||
|
||||
iterator before_begin() const
|
||||
{ return slist_.before_begin(); }
|
||||
|
||||
iterator begin() const
|
||||
{ return slist_.begin(); }
|
||||
|
||||
iterator end() const
|
||||
{ return slist_.end(); }
|
||||
|
||||
iterator last() const
|
||||
{ return last_; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
slist_.clear();
|
||||
last_ = slist_.before_begin();
|
||||
}
|
||||
|
||||
iterator insert_after(iterator it, void_pointer m)
|
||||
{
|
||||
slist_.insert_after(it, m);
|
||||
if(it == last_){
|
||||
last_ = slist_.iterator_to(m);
|
||||
}
|
||||
return iterator_to(m);
|
||||
}
|
||||
|
||||
void push_front(void_pointer m)
|
||||
{ this->insert_after(this->before_begin(), m); }
|
||||
|
||||
void push_back(void_pointer m)
|
||||
{ this->insert_after(last_, m); }
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
if(last_ == slist_.begin()){
|
||||
last_ = slist_.before_begin();
|
||||
}
|
||||
slist_.pop_front();
|
||||
}
|
||||
|
||||
void *front() const
|
||||
{ return slist_.front(); }
|
||||
|
||||
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
|
||||
{
|
||||
if(before_begin == before_end)
|
||||
return;
|
||||
if(after_this == last_){
|
||||
last_ = before_end;
|
||||
}
|
||||
slist_.splice_after(after_this, before_begin, before_end);
|
||||
}
|
||||
|
||||
void swap(basic_multiallocation_cached_slist &x)
|
||||
{
|
||||
slist_.swap(x.slist_);
|
||||
using std::swap;
|
||||
swap(last_, x.last_);
|
||||
if(last_ == x.before_begin()){
|
||||
last_ = this->before_begin();
|
||||
}
|
||||
if(x.last_ == this->before_begin()){
|
||||
x.last_ = x.before_begin();
|
||||
}
|
||||
}
|
||||
|
||||
static iterator iterator_to(void_pointer p)
|
||||
{ return basic_multiallocation_slist<VoidPointer>::iterator_to(p); }
|
||||
|
||||
std::pair<void_pointer, void_pointer> extract_data()
|
||||
{
|
||||
if(this->empty()){
|
||||
return std::pair<void_pointer, void_pointer>(void_pointer(0), void_pointer(0));
|
||||
}
|
||||
else{
|
||||
void_pointer p1 = slist_.extract_data();
|
||||
void_pointer p2 = void_pointer(&*last_);
|
||||
last_ = iterator();
|
||||
return std::pair<void_pointer, void_pointer>(p1, p2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class MultiallocatorCachedSlist>
|
||||
class basic_multiallocation_cached_counted_slist
|
||||
{
|
||||
private:
|
||||
MultiallocatorCachedSlist cached_slist_;
|
||||
std::size_t size_;
|
||||
|
||||
basic_multiallocation_cached_counted_slist(basic_multiallocation_cached_counted_slist &);
|
||||
basic_multiallocation_cached_counted_slist &operator=(basic_multiallocation_cached_counted_slist &);
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_counted_slist)
|
||||
|
||||
typedef typename MultiallocatorCachedSlist::void_pointer void_pointer;
|
||||
typedef typename MultiallocatorCachedSlist::iterator iterator;
|
||||
|
||||
basic_multiallocation_cached_counted_slist()
|
||||
: cached_slist_(), size_(0)
|
||||
{}
|
||||
|
||||
basic_multiallocation_cached_counted_slist(void_pointer p1, void_pointer p2, std::size_t n)
|
||||
: cached_slist_(p1, p2), size_(n)
|
||||
{}
|
||||
|
||||
basic_multiallocation_cached_counted_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
|
||||
: cached_slist_(), size_(0)
|
||||
{ this->swap(other); }
|
||||
|
||||
basic_multiallocation_cached_counted_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other)
|
||||
{
|
||||
basic_multiallocation_cached_counted_slist tmp(boost::interprocess::move(other));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_multiallocation_cached_counted_slist (MultiallocatorCachedSlist mem, std::size_t n)
|
||||
: cached_slist_(boost::interprocess::move(mem)), size_(n)
|
||||
{}
|
||||
|
||||
bool empty() const
|
||||
{ return cached_slist_.empty(); }
|
||||
|
||||
std::size_t size() const
|
||||
{ return size_; }
|
||||
|
||||
iterator before_begin() const
|
||||
{ return cached_slist_.before_begin(); }
|
||||
|
||||
iterator begin() const
|
||||
{ return cached_slist_.begin(); }
|
||||
|
||||
iterator end() const
|
||||
{ return cached_slist_.end(); }
|
||||
|
||||
iterator last() const
|
||||
{ return cached_slist_.last(); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
cached_slist_.clear();
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
iterator insert_after(iterator it, void_pointer m)
|
||||
{
|
||||
iterator ret = cached_slist_.insert_after(it, m);
|
||||
++size_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void push_front(void_pointer m)
|
||||
{ this->insert_after(this->before_begin(), m); }
|
||||
|
||||
void push_back(void_pointer m)
|
||||
{ this->insert_after(this->before_begin(), m); }
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
cached_slist_.pop_front();
|
||||
--size_;
|
||||
}
|
||||
|
||||
void *front() const
|
||||
{ return cached_slist_.front(); }
|
||||
|
||||
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end)
|
||||
{
|
||||
std::size_t n = static_cast<std::size_t>(std::distance(before_begin, before_end));
|
||||
this->splice_after(after_this, x, before_begin, before_end, n);
|
||||
}
|
||||
|
||||
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end, std::size_t n)
|
||||
{
|
||||
cached_slist_.splice_after(after_this, before_begin, before_end);
|
||||
size_ += n;
|
||||
x.size_ -= n;
|
||||
}
|
||||
|
||||
void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x)
|
||||
{
|
||||
cached_slist_.splice_after(after_this, x.before_begin(), x.last());
|
||||
size_ += x.size_;
|
||||
x.size_ = 0;
|
||||
}
|
||||
|
||||
void swap(basic_multiallocation_cached_counted_slist &x)
|
||||
{
|
||||
cached_slist_.swap(x.cached_slist_);
|
||||
using std::swap;
|
||||
swap(size_, x.size_);
|
||||
}
|
||||
|
||||
static iterator iterator_to(void_pointer p)
|
||||
{ return MultiallocatorCachedSlist::iterator_to(p); }
|
||||
|
||||
std::pair<void_pointer, void_pointer> extract_data()
|
||||
{
|
||||
size_ = 0;
|
||||
return cached_slist_.extract_data();
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct cast_functor
|
||||
{
|
||||
typedef typename containers_detail::add_reference<T>::type result_type;
|
||||
result_type operator()(char &ptr) const
|
||||
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
|
||||
};
|
||||
|
||||
|
||||
template<class MultiallocationChain, class T>
|
||||
class transform_multiallocation_chain
|
||||
{
|
||||
private:
|
||||
|
||||
MultiallocationChain holder_;
|
||||
typedef typename MultiallocationChain::void_pointer void_pointer;
|
||||
typedef typename boost::pointer_to_other
|
||||
<void_pointer, T>::type pointer;
|
||||
|
||||
transform_multiallocation_chain(transform_multiallocation_chain &);
|
||||
transform_multiallocation_chain &operator=(transform_multiallocation_chain &);
|
||||
|
||||
static pointer cast(void_pointer p)
|
||||
{
|
||||
return pointer(static_cast<T*>(containers_detail::get_pointer(p)));
|
||||
}
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(transform_multiallocation_chain)
|
||||
|
||||
typedef transform_iterator
|
||||
< typename MultiallocationChain::iterator
|
||||
, containers_detail::cast_functor <T> > iterator;
|
||||
|
||||
transform_multiallocation_chain(void_pointer p1, void_pointer p2, std::size_t n)
|
||||
: holder_(p1, p2, n)
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain()
|
||||
: holder_()
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
|
||||
: holder_()
|
||||
{ this->swap(other); }
|
||||
|
||||
transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(MultiallocationChain) other)
|
||||
: holder_(boost::interprocess::move(other))
|
||||
{}
|
||||
|
||||
transform_multiallocation_chain& operator=(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other)
|
||||
{
|
||||
transform_multiallocation_chain tmp(boost::interprocess::move(other));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void push_front(pointer mem)
|
||||
{ holder_.push_front(mem); }
|
||||
|
||||
void swap(transform_multiallocation_chain &other_chain)
|
||||
{ holder_.swap(other_chain.holder_); }
|
||||
/*
|
||||
void splice_after(iterator after_this, iterator before_begin, iterator before_end)
|
||||
{ holder_.splice_after(after_this.base(), before_begin.base(), before_end.base()); }
|
||||
*/
|
||||
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin, iterator before_end, std::size_t n)
|
||||
{ holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); }
|
||||
|
||||
void pop_front()
|
||||
{ holder_.pop_front(); }
|
||||
|
||||
pointer front() const
|
||||
{ return cast(holder_.front()); }
|
||||
|
||||
bool empty() const
|
||||
{ return holder_.empty(); }
|
||||
|
||||
iterator before_begin() const
|
||||
{ return iterator(holder_.before_begin()); }
|
||||
|
||||
iterator begin() const
|
||||
{ return iterator(holder_.begin()); }
|
||||
|
||||
iterator end() const
|
||||
{ return iterator(holder_.end()); }
|
||||
|
||||
iterator last() const
|
||||
{ return iterator(holder_.last()); }
|
||||
|
||||
std::size_t size() const
|
||||
{ return holder_.size(); }
|
||||
|
||||
void clear()
|
||||
{ holder_.clear(); }
|
||||
|
||||
iterator insert_after(iterator it, pointer m)
|
||||
{ return iterator(holder_.insert_after(it.base(), m)); }
|
||||
|
||||
static iterator iterator_to(pointer p)
|
||||
{ return iterator(MultiallocationChain::iterator_to(p)); }
|
||||
|
||||
std::pair<void_pointer, void_pointer> extract_data()
|
||||
{ return holder_.extract_data(); }
|
||||
|
||||
MultiallocationChain extract_multiallocation_chain()
|
||||
{
|
||||
return MultiallocationChain(boost::interprocess::move(holder_));
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
// namespace containers_detail {
|
||||
// namespace interprocess_container {
|
||||
// namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
|
||||
@@ -0,0 +1,499 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
|
||||
#define BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/version_type.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/utilities.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/mpl.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/destroyers.hpp>
|
||||
|
||||
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/algorithms.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
//!A deleter for scoped_ptr that deallocates the memory
|
||||
//!allocated for an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_deallocator
|
||||
{
|
||||
typedef typename Allocator::pointer pointer;
|
||||
typedef containers_detail::integral_constant<unsigned,
|
||||
boost::interprocess_container::containers_detail::
|
||||
version<Allocator>::value> alloc_version;
|
||||
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef containers_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); }
|
||||
|
||||
scoped_deallocator(scoped_deallocator &);
|
||||
scoped_deallocator& operator=(scoped_deallocator &);
|
||||
|
||||
public:
|
||||
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(scoped_deallocator)
|
||||
|
||||
pointer m_ptr;
|
||||
Allocator& m_alloc;
|
||||
|
||||
scoped_deallocator(pointer p, Allocator& a)
|
||||
: m_ptr(p), m_alloc(a)
|
||||
{}
|
||||
|
||||
~scoped_deallocator()
|
||||
{ if (m_ptr)priv_deallocate(alloc_version()); }
|
||||
|
||||
scoped_deallocator(BOOST_INTERPROCESS_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 A>
|
||||
class allocator_destroyer_and_chain_builder
|
||||
{
|
||||
typedef typename A::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)
|
||||
{
|
||||
value_type *vp = containers_detail::get_pointer(p);
|
||||
vp->~value_type();
|
||||
c_.push_front(vp);
|
||||
}
|
||||
};
|
||||
|
||||
template <class A>
|
||||
class allocator_multialloc_chain_node_deallocator
|
||||
{
|
||||
typedef typename A::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()
|
||||
{
|
||||
if(!c_.empty())
|
||||
a_.deallocate_individual(boost::interprocess::move(c_));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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>
|
||||
struct node_alloc_holder
|
||||
{
|
||||
typedef node_alloc_holder<A, ICont> self_t;
|
||||
typedef typename A::value_type value_type;
|
||||
typedef typename ICont::value_type Node;
|
||||
typedef typename A::template rebind<Node>::other NodeAlloc;
|
||||
typedef A ValAlloc;
|
||||
typedef typename NodeAlloc::pointer NodePtr;
|
||||
typedef containers_detail::scoped_deallocator<NodeAlloc> Deallocator;
|
||||
typedef typename NodeAlloc::size_type size_type;
|
||||
typedef typename NodeAlloc::difference_type difference_type;
|
||||
typedef containers_detail::integral_constant<unsigned, 1> allocator_v1;
|
||||
typedef containers_detail::integral_constant<unsigned, 2> allocator_v2;
|
||||
typedef containers_detail::integral_constant<unsigned,
|
||||
boost::interprocess_container::containers_detail::
|
||||
version<NodeAlloc>::value> alloc_version;
|
||||
typedef typename ICont::iterator icont_iterator;
|
||||
typedef typename ICont::const_iterator icont_citerator;
|
||||
typedef allocator_destroyer<NodeAlloc> Destroyer;
|
||||
|
||||
private:
|
||||
node_alloc_holder(node_alloc_holder&);
|
||||
node_alloc_holder & operator=(node_alloc_holder&);
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(node_alloc_holder)
|
||||
|
||||
node_alloc_holder(const ValAlloc &a)
|
||||
: members_(a)
|
||||
{}
|
||||
|
||||
node_alloc_holder(const node_alloc_holder &other)
|
||||
: members_(other.node_alloc())
|
||||
{}
|
||||
|
||||
node_alloc_holder(BOOST_INTERPROCESS_RV_REF(node_alloc_holder) other)
|
||||
: members_(boost::interprocess::move(other.node_alloc()))
|
||||
{ this->swap(other); }
|
||||
|
||||
template<class Pred>
|
||||
node_alloc_holder(const ValAlloc &a, const Pred &c)
|
||||
: members_(a, typename ICont::value_compare(c))
|
||||
{}
|
||||
|
||||
template<class Pred>
|
||||
node_alloc_holder(BOOST_INTERPROCESS_RV_REF(ValAlloc) a, const Pred &c)
|
||||
: members_(a, typename ICont::value_compare(c))
|
||||
{}
|
||||
|
||||
template<class Pred>
|
||||
node_alloc_holder(const node_alloc_holder &other, const Pred &c)
|
||||
: members_(other.node_alloc(), typename ICont::value_compare(c))
|
||||
{}
|
||||
|
||||
~node_alloc_holder()
|
||||
{ this->clear(alloc_version()); }
|
||||
|
||||
size_type max_size() const
|
||||
{ return this->node_alloc().max_size(); }
|
||||
|
||||
NodePtr allocate_one()
|
||||
{ return this->allocate_one(alloc_version()); }
|
||||
|
||||
NodePtr allocate_one(allocator_v1)
|
||||
{ return this->node_alloc().allocate(1); }
|
||||
|
||||
NodePtr allocate_one(allocator_v2)
|
||||
{ return this->node_alloc().allocate_one(); }
|
||||
|
||||
void deallocate_one(NodePtr p)
|
||||
{ return this->deallocate_one(p, alloc_version()); }
|
||||
|
||||
void deallocate_one(NodePtr p, allocator_v1)
|
||||
{ this->node_alloc().deallocate(p, 1); }
|
||||
|
||||
void deallocate_one(NodePtr p, allocator_v2)
|
||||
{ this->node_alloc().deallocate_one(p); }
|
||||
|
||||
template<class Convertible1, class Convertible2>
|
||||
static void construct(const NodePtr &ptr,
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
std::pair<Convertible1, Convertible2> &&
|
||||
#else
|
||||
boost::interprocess::rv<std::pair<Convertible1, Convertible2> > &
|
||||
#endif
|
||||
value)
|
||||
{
|
||||
typedef typename Node::hook_type hook_type;
|
||||
typedef typename Node::value_type::first_type first_type;
|
||||
typedef typename Node::value_type::second_type second_type;
|
||||
Node *nodeptr = containers_detail::get_pointer(ptr);
|
||||
|
||||
//Hook constructor does not throw
|
||||
new(static_cast<hook_type*>(nodeptr))hook_type();
|
||||
//Now construct pair members_holder
|
||||
value_type *valueptr = &nodeptr->get_data();
|
||||
new((void*)&valueptr->first) first_type(boost::interprocess::move(value.first));
|
||||
BOOST_TRY{
|
||||
new((void*)&valueptr->second) second_type(boost::interprocess::move(value.second));
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
valueptr->first.~first_type();
|
||||
static_cast<hook_type*>(nodeptr)->~hook_type();
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
static void destroy(const NodePtr &ptr)
|
||||
{ containers_detail::get_pointer(ptr)->~Node(); }
|
||||
|
||||
Deallocator create_node_and_deallocator()
|
||||
{
|
||||
return Deallocator(this->allocate_one(), this->node_alloc());
|
||||
}
|
||||
|
||||
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
template<class ...Args>
|
||||
static void construct(const NodePtr &ptr, Args &&...args)
|
||||
{ new((void*)containers_detail::get_pointer(ptr)) Node(boost::interprocess::forward<Args>(args)...); }
|
||||
|
||||
template<class ...Args>
|
||||
NodePtr create_node(Args &&...args)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
self_t::construct(p, boost::interprocess::forward<Args>(args)...);
|
||||
node_deallocator.release();
|
||||
return (p);
|
||||
}
|
||||
|
||||
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
static void construct(const NodePtr &ptr)
|
||||
{ new((void*)containers_detail::get_pointer(ptr)) Node(); }
|
||||
|
||||
NodePtr create_node()
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
self_t::construct(p);
|
||||
node_deallocator.release();
|
||||
return (p);
|
||||
}
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
|
||||
{ \
|
||||
new((void*)containers_detail::get_pointer(ptr)) \
|
||||
Node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
|
||||
} \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
|
||||
{ \
|
||||
NodePtr p = this->allocate_one(); \
|
||||
Deallocator node_deallocator(p, this->node_alloc()); \
|
||||
self_t::construct(p, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)); \
|
||||
node_deallocator.release(); \
|
||||
return (p); \
|
||||
} \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
#endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
template<class It>
|
||||
NodePtr create_node_from_it(It it)
|
||||
{
|
||||
NodePtr p = this->allocate_one();
|
||||
Deallocator node_deallocator(p, this->node_alloc());
|
||||
::boost::interprocess_container::construct_in_place(containers_detail::get_pointer(p), it);
|
||||
node_deallocator.release();
|
||||
return (p);
|
||||
}
|
||||
|
||||
void destroy_node(NodePtr node)
|
||||
{
|
||||
self_t::destroy(node);
|
||||
this->deallocate_one(node);
|
||||
}
|
||||
|
||||
void swap(node_alloc_holder &x)
|
||||
{
|
||||
NodeAlloc& this_alloc = this->node_alloc();
|
||||
NodeAlloc& other_alloc = x.node_alloc();
|
||||
|
||||
if (this_alloc != other_alloc){
|
||||
containers_detail::do_swap(this_alloc, other_alloc);
|
||||
}
|
||||
|
||||
this->icont().swap(x.icont());
|
||||
}
|
||||
|
||||
template<class FwdIterator, class Inserter>
|
||||
FwdIterator allocate_many_and_construct
|
||||
(FwdIterator beg, difference_type n, Inserter inserter)
|
||||
{
|
||||
if(n){
|
||||
typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
|
||||
|
||||
//Try to allocate memory in a single block
|
||||
multiallocation_chain mem(this->node_alloc().allocate_individual(n));
|
||||
int constructed = 0;
|
||||
Node *p = 0;
|
||||
BOOST_TRY{
|
||||
for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
|
||||
p = containers_detail::get_pointer(mem.front());
|
||||
mem.pop_front();
|
||||
//This can throw
|
||||
constructed = 0;
|
||||
boost::interprocess_container::construct_in_place(p, beg);
|
||||
++constructed;
|
||||
//This can throw in some containers (predicate might throw)
|
||||
inserter(*p);
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
if(constructed){
|
||||
this->destroy(p);
|
||||
}
|
||||
this->node_alloc().deallocate_individual(boost::interprocess::move(mem));
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
return beg;
|
||||
|
||||
}
|
||||
|
||||
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::interprocess::is_movable<typename NodeAlloc::multiallocation_chain>::value == true));
|
||||
if(!chain.empty())
|
||||
this->node_alloc().deallocate_individual(boost::interprocess::move(chain));
|
||||
}
|
||||
|
||||
icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v1)
|
||||
{ return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
|
||||
|
||||
icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v2)
|
||||
{
|
||||
allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
|
||||
return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder());
|
||||
}
|
||||
|
||||
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 destroyer
|
||||
{
|
||||
destroyer(node_alloc_holder &holder)
|
||||
: m_holder(holder)
|
||||
{}
|
||||
|
||||
void operator()(NodePtr n) const
|
||||
{ m_holder.destroy_node(n); }
|
||||
|
||||
node_alloc_holder &m_holder;
|
||||
};
|
||||
|
||||
struct members_holder
|
||||
: public NodeAlloc
|
||||
{
|
||||
private:
|
||||
members_holder(const members_holder&);
|
||||
|
||||
public:
|
||||
template<class ConvertibleToAlloc>
|
||||
members_holder(const ConvertibleToAlloc &c2alloc)
|
||||
: NodeAlloc(c2alloc)
|
||||
{}
|
||||
|
||||
template<class ConvertibleToAlloc, class Pred>
|
||||
members_holder(const ConvertibleToAlloc &c2alloc, const Pred &c)
|
||||
: NodeAlloc(c2alloc), m_icont(c)
|
||||
{}
|
||||
//The intrusive container
|
||||
ICont m_icont;
|
||||
} members_;
|
||||
|
||||
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_); }
|
||||
};
|
||||
|
||||
} //namespace containers_detail {
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif // BOOST_CONTAINERS_DETAIL_NODE_ALLOC_HPP_
|
||||
@@ -0,0 +1,189 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
//
|
||||
// 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_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
|
||||
#define BOOST_CONTAINERS_CONTAINERS_DETAIL_PAIR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/mpl.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
|
||||
|
||||
#include <utility> //std::pair
|
||||
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
|
||||
#ifndef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
#include <boost/interprocess/containers/container/detail/preprocessor.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair
|
||||
{
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(pair)
|
||||
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
|
||||
T1 first;
|
||||
T2 second;
|
||||
|
||||
//std::pair compatibility
|
||||
template <class D, class S>
|
||||
pair(const std::pair<D, S>& p)
|
||||
: first(p.first), second(p.second)
|
||||
{}
|
||||
|
||||
//To resolve ambiguity with the variadic constructor of 1 argument
|
||||
//and the previous constructor
|
||||
pair(std::pair<T1, T2>& x)
|
||||
: first(x.first), second(x.second)
|
||||
{}
|
||||
|
||||
template <class D, class S>
|
||||
pair(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p)
|
||||
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
|
||||
{}
|
||||
|
||||
pair()
|
||||
: first(), second()
|
||||
{}
|
||||
|
||||
pair(const pair<T1, T2>& x)
|
||||
: first(x.first), second(x.second)
|
||||
{}
|
||||
|
||||
//To resolve ambiguity with the variadic constructor of 1 argument
|
||||
//and the copy constructor
|
||||
pair(pair<T1, T2>& x)
|
||||
: first(x.first), second(x.second)
|
||||
{}
|
||||
|
||||
pair(BOOST_INTERPROCESS_RV_REF(pair) p)
|
||||
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
|
||||
{}
|
||||
|
||||
template <class D, class S>
|
||||
pair(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(pair, D, S) p)
|
||||
: first(boost::interprocess::move(p.first)), second(boost::interprocess::move(p.second))
|
||||
{}
|
||||
|
||||
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
template<class U, class ...Args>
|
||||
pair(U &&u, Args &&... args)
|
||||
: first(boost::interprocess::forward<U>(u))
|
||||
, second(boost::interprocess::forward<Args>(args)...)
|
||||
{}
|
||||
|
||||
#else
|
||||
|
||||
template<class U>
|
||||
pair( BOOST_CONTAINERS_PARAM(U, u)
|
||||
#ifndef BOOST_HAS_RVALUE_REFS
|
||||
, typename containers_detail::disable_if
|
||||
< containers_detail::is_same<U, boost::interprocess::rv<pair> > >::type* = 0
|
||||
#endif
|
||||
)
|
||||
: first(boost::interprocess::forward<U>(const_cast<U&>(u)))
|
||||
{}
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
pair(BOOST_CONTAINERS_PARAM(U, u) \
|
||||
,BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _)) \
|
||||
: first(boost::interprocess::forward<U>(const_cast<U&>(u))) \
|
||||
, second(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _)) \
|
||||
{} \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
#endif
|
||||
|
||||
pair& operator=(BOOST_INTERPROCESS_RV_REF(pair) p)
|
||||
{
|
||||
first = boost::interprocess::move(p.first);
|
||||
second = boost::interprocess::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
pair& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, T1, T2) p)
|
||||
{
|
||||
first = boost::interprocess::move(p.first);
|
||||
second = boost::interprocess::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class D, class S>
|
||||
pair& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(std::pair, D, S) p)
|
||||
{
|
||||
first = boost::interprocess::move(p.first);
|
||||
second = boost::interprocess::move(p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(pair& p)
|
||||
{ std::swap(*this, p); }
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(x.first < y.first ||
|
||||
(!(y.first < x.first) && x.second < y.second)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(!(x == y)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return y < x; }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(!(x < y)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
|
||||
{ return static_cast<bool>(!(y < x)); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline pair<T1, T2> make_pair(T1 x, T2 y)
|
||||
{ return pair<T1, T2>(x, y); }
|
||||
|
||||
template <class T1, class T2>
|
||||
inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
|
||||
{
|
||||
swap(x.first, y.first);
|
||||
swap(x.second, y.second);
|
||||
}
|
||||
|
||||
} //namespace containers_detail {
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_PAIR_HPP
|
||||
@@ -0,0 +1,101 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2008. 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_CONTAINERS_DETAIL_PREPROCESSOR_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
|
||||
#ifdef BOOST_CONTAINERS_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_CONTAINERS_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
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_CONTAINERS_PP_PARAM_LIST(z, n, data) \
|
||||
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#define BOOST_CONTAINERS_PARAM(U, u) \
|
||||
U && u \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_CONTAINERS_PARAM(U, u) \
|
||||
const U & u \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_CONTAINERS_AUX_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#define BOOST_CONTAINERS_AUX_PARAM_INC(z, n, data) \
|
||||
BOOST_PP_CAT(++m_p, n) \
|
||||
//!
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_CONTAINERS_AUX_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#define BOOST_CONTAINERS_PP_PARAM_FORWARD(z, n, data) \
|
||||
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
|
||||
//!
|
||||
|
||||
#define BOOST_CONTAINERS_PP_MEMBER_FORWARD(z, n, data) \
|
||||
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
|
||||
//!
|
||||
|
||||
#define BOOST_CONTAINERS_PP_MEMBER_IT_FORWARD(z, n, data) \
|
||||
BOOST_PP_CAT(*m_p, n) \
|
||||
//!
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#else
|
||||
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
#error "This file is not needed when perfect forwarding is available"
|
||||
#endif
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_PREPROCESSOR_HPP
|
||||
@@ -0,0 +1,176 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
// (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_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_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 &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 T &m_value;
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunction>
|
||||
class transform_iterator
|
||||
: public UnaryFunction
|
||||
, public std::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, typename containers_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 interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// (C) Copyright John Maddock 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// The alignment_of implementation comes from John Maddock's boost::alignment_of code
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
|
||||
#define BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
struct nat{};
|
||||
|
||||
//boost::alignment_of yields to 10K lines of preprocessed code, so we
|
||||
//need an alternative
|
||||
template <typename T> struct alignment_of;
|
||||
|
||||
template <typename T>
|
||||
struct alignment_of_hack
|
||||
{
|
||||
char c;
|
||||
T t;
|
||||
alignment_of_hack();
|
||||
};
|
||||
|
||||
template <unsigned A, unsigned S>
|
||||
struct alignment_logic
|
||||
{
|
||||
enum{ value = A < S ? A : S };
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct alignment_of
|
||||
{
|
||||
enum{ value = alignment_logic
|
||||
< sizeof(alignment_of_hack<T>) - sizeof(T)
|
||||
, sizeof(T)>::value };
|
||||
};
|
||||
|
||||
//This is not standard, but should work with all compilers
|
||||
union max_align
|
||||
{
|
||||
char char_;
|
||||
short short_;
|
||||
int int_;
|
||||
long long_;
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
long long long_long_;
|
||||
#endif
|
||||
float float_;
|
||||
double double_;
|
||||
long double long_double_;
|
||||
void * void_ptr_;
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_reference<T&>
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer<T*>
|
||||
{
|
||||
enum { 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 <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));
|
||||
};
|
||||
|
||||
} // namespace containers_detail
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_CONTAINER_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_DETAIL_UTILITIES_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
template <class SizeType>
|
||||
SizeType
|
||||
get_next_capacity(const SizeType max_size
|
||||
,const SizeType capacity
|
||||
,const SizeType n)
|
||||
{
|
||||
// if (n > max_size - capacity)
|
||||
// throw std::length_error("get_next_capacity");
|
||||
|
||||
const SizeType m3 = max_size/3;
|
||||
|
||||
if (capacity < m3)
|
||||
return capacity + max_value(3*(capacity+1)/5, n);
|
||||
|
||||
if (capacity < m3*2)
|
||||
return capacity + max_value((capacity+1)/2, n);
|
||||
|
||||
return max_size;
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
template<class SmartPtr>
|
||||
struct smart_ptr_type
|
||||
{
|
||||
typedef typename SmartPtr::value_type value_type;
|
||||
typedef value_type *pointer;
|
||||
static pointer get (const SmartPtr &smartptr)
|
||||
{ return smartptr.get();}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct smart_ptr_type<T*>
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef value_type *pointer;
|
||||
static pointer get (pointer ptr)
|
||||
{ return ptr;}
|
||||
};
|
||||
|
||||
//!Overload for smart pointers to avoid ADL problems with get_pointer
|
||||
template<class Ptr>
|
||||
inline typename smart_ptr_type<Ptr>::pointer
|
||||
get_pointer(const Ptr &ptr)
|
||||
{ return smart_ptr_type<Ptr>::get(ptr); }
|
||||
|
||||
//!To avoid ADL problems with swap
|
||||
template <class T>
|
||||
inline void do_swap(T& x, T& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
}
|
||||
|
||||
template <std::size_t OrigSize, std::size_t RoundTo>
|
||||
struct ct_rounded_size
|
||||
{
|
||||
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
|
||||
};
|
||||
|
||||
} //namespace containers_detail {
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_UTILITIES_HPP
|
||||
@@ -0,0 +1,43 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
//
|
||||
// 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_CONTAINERS_DETAIL_VALUE_INIT_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
template<class T>
|
||||
struct value_init
|
||||
{
|
||||
value_init()
|
||||
: m_t()
|
||||
{}
|
||||
|
||||
T m_t;
|
||||
};
|
||||
|
||||
} //namespace containers_detail {
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_VALUE_INIT_HPP
|
||||
@@ -0,0 +1,153 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2008. 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_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/workaround.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
|
||||
#include <cstddef> //std::size_t
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess_container {
|
||||
namespace containers_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 interprocess_container { namespace containers_detail {
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
@@ -0,0 +1,89 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_DETAIL_VERSION_TYPE_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/mpl.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/type_traits.hpp>
|
||||
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess_container {
|
||||
namespace containers_detail {
|
||||
|
||||
//using namespace boost;
|
||||
|
||||
template <class T, unsigned V>
|
||||
struct version_type
|
||||
: public containers_detail::integral_constant<unsigned, V>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
version_type(const version_type<T, 0>&);
|
||||
};
|
||||
|
||||
namespace impl{
|
||||
|
||||
template <class T,
|
||||
bool = containers_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 containers_detail::integral_constant<unsigned, impl::version<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
} //namespace containers_detail {
|
||||
} //namespace interprocess_container {
|
||||
} //namespace boost{
|
||||
|
||||
#endif //#define BOOST_CONTAINERS_DETAIL_VERSION_TYPE_HPP
|
||||
@@ -0,0 +1,24 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_CONTAINERS_DETAIL_WORKAROUND_HPP
|
||||
#define BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_begin.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)\
|
||||
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
|
||||
#define BOOST_CONTAINERS_PERFECT_FORWARDING
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/containers/container/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_CONTAINERS_DETAIL_WORKAROUND_HPP
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1376
libraries/include/boost/interprocess/containers/container/list.hpp
Normal file
1376
libraries/include/boost/interprocess/containers/container/list.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1266
libraries/include/boost/interprocess/containers/container/map.hpp
Normal file
1266
libraries/include/boost/interprocess/containers/container/map.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1112
libraries/include/boost/interprocess/containers/container/set.hpp
Normal file
1112
libraries/include/boost/interprocess/containers/container/set.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1528
libraries/include/boost/interprocess/containers/container/slist.hpp
Normal file
1528
libraries/include/boost/interprocess/containers/container/slist.hpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2320
libraries/include/boost/interprocess/containers/container/string.hpp
Normal file
2320
libraries/include/boost/interprocess/containers/container/string.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1933
libraries/include/boost/interprocess/containers/container/vector.hpp
Normal file
1933
libraries/include/boost/interprocess/containers/container/vector.hpp
Normal file
File diff suppressed because it is too large
Load Diff
32
libraries/include/boost/interprocess/containers/deque.hpp
Normal file
32
libraries/include/boost/interprocess/containers/deque.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_DEQUE_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/deque.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::deque;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
|
||||
|
||||
32
libraries/include/boost/interprocess/containers/flat_map.hpp
Normal file
32
libraries/include/boost/interprocess/containers/flat_map.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_FLAT_MAP_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/flat_map.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::flat_map;
|
||||
using boost::interprocess_container::flat_multimap;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP
|
||||
32
libraries/include/boost/interprocess/containers/flat_set.hpp
Normal file
32
libraries/include/boost/interprocess/containers/flat_set.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_FLAT_SET_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/flat_set.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::flat_set;
|
||||
using boost::interprocess_container::flat_multiset;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP
|
||||
32
libraries/include/boost/interprocess/containers/list.hpp
Normal file
32
libraries/include/boost/interprocess/containers/list.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_LIST_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/list.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::list;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
|
||||
|
||||
32
libraries/include/boost/interprocess/containers/map.hpp
Normal file
32
libraries/include/boost/interprocess/containers/map.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_MAP_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_MAP_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/map.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::map;
|
||||
using boost::interprocess_container::multimap;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_MAP_HPP
|
||||
32
libraries/include/boost/interprocess/containers/pair.hpp
Normal file
32
libraries/include/boost/interprocess/containers/pair.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_PAIR_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/detail/pair.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::containers_detail::pair;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
|
||||
|
||||
32
libraries/include/boost/interprocess/containers/set.hpp
Normal file
32
libraries/include/boost/interprocess/containers/set.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_SET_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_SET_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/set.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::set;
|
||||
using boost::interprocess_container::multiset;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SET_HPP
|
||||
31
libraries/include/boost/interprocess/containers/slist.hpp
Normal file
31
libraries/include/boost/interprocess/containers/slist.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_SLIST_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/slist.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::slist;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP
|
||||
@@ -0,0 +1,31 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_STABLE_VECTOR_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/stable_vector.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::stable_vector;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
|
||||
32
libraries/include/boost/interprocess/containers/string.hpp
Normal file
32
libraries/include/boost/interprocess/containers/string.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_STRING_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_STRING_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/string.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::basic_string;
|
||||
using boost::interprocess_container::string;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_STRING_HPP
|
||||
32
libraries/include/boost/interprocess/containers/vector.hpp
Normal file
32
libraries/include/boost/interprocess/containers/vector.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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_VECTOR_HPP
|
||||
#define BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/containers/container/vector.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::vector;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. 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/interprocess/containers/container/detail/version_type.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using boost::interprocess_container::containers_detail::version_type;
|
||||
using boost::interprocess_container::containers_detail::version;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
|
||||
|
||||
73
libraries/include/boost/interprocess/creation_tags.hpp
Normal file
73
libraries/include/boost/interprocess/creation_tags.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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 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 detail {
|
||||
|
||||
enum create_enum_t
|
||||
{ DoCreate, DoOpen, DoOpenOrCreate };
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP
|
||||
|
||||
472
libraries/include/boost/interprocess/detail/atomic.hpp
Normal file
472
libraries/include/boost/interprocess/detail/atomic.hpp
Normal file
@@ -0,0 +1,472 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-2008
|
||||
// (C) Copyright Markus Schoepflin 2007
|
||||
//
|
||||
// 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 detail{
|
||||
|
||||
//! 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);
|
||||
|
||||
//! 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 detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace detail{
|
||||
|
||||
//! 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 detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail{
|
||||
|
||||
//! 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;
|
||||
asm volatile( "lock\n\t"
|
||||
"cmpxchg %3,%1"
|
||||
: "=a" (prev), "=m" (*(mem))
|
||||
: "0" (prev), "r" (with)
|
||||
: "memory", "cc");
|
||||
return prev;
|
||||
/*
|
||||
boost::uint32_t prev;
|
||||
|
||||
asm volatile ("lock; cmpxchgl %1, %2"
|
||||
: "=a" (prev)
|
||||
: "r" (with), "m" (*(mem)), "0"(cmp));
|
||||
asm volatile("" : : : "memory");
|
||||
|
||||
return prev;
|
||||
*/
|
||||
}
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "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;
|
||||
/*
|
||||
asm volatile( "lock\n\t; xaddl %0,%1"
|
||||
: "=r"(val), "=m"(*mem)
|
||||
: "0"(val), "m"(*mem));
|
||||
asm volatile("" : : : "memory");
|
||||
|
||||
return val;
|
||||
*/
|
||||
}
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "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 detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail{
|
||||
|
||||
//! 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 ("0:\n\t" // retry local label
|
||||
"lwarx %0,0,%2\n\t" // load prev and reserve
|
||||
"add %1,%0,%3\n\t" // temp = prev + val
|
||||
"stwcx. %1,0,%2\n\t" // conditionally store
|
||||
"bne- 0b" // start over if we lost
|
||||
// the reservation
|
||||
//XXX find a cleaner way to define the temp
|
||||
//it's not an output
|
||||
: "=&r" (prev), "=&r" (temp) // output, temp
|
||||
: "b" (mem), "r" (val) // inputs
|
||||
: "memory", "cc"); // clobbered
|
||||
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 ("0:\n\t" // retry local label
|
||||
"lwarx %0,0,%1\n\t" // load prev and reserve
|
||||
"cmpw %0,%3\n\t" // does it match cmp?
|
||||
"bne- 1f\n\t" // ...no, bail out
|
||||
"stwcx. %2,0,%1\n\t" // ...yes, conditionally
|
||||
// store with
|
||||
"bne- 0b\n\t" // start over if we lost
|
||||
// the reservation
|
||||
"1:" // exit local label
|
||||
|
||||
: "=&r"(prev) // output
|
||||
: "b" (mem), "r" (with), "r"(cmp) // inputs
|
||||
: "memory", "cc"); // clobbered
|
||||
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 detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail{
|
||||
|
||||
//! 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), with, cmp); }
|
||||
|
||||
//! 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 detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif (defined(sun) || defined(__sun))
|
||||
|
||||
#include <atomic.h>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace detail{
|
||||
|
||||
//! 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 detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__osf__) && defined(__DECCXX)
|
||||
|
||||
#include <machine/builtins.h>
|
||||
#include <c_asm.h>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace detail{
|
||||
|
||||
//! 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 detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#else
|
||||
|
||||
#error No atomic operations implemented for this platform, sorry!
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
|
||||
29
libraries/include/boost/interprocess/detail/cast_tags.hpp
Normal file
29
libraries/include/boost/interprocess/detail/cast_tags.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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 detail {
|
||||
|
||||
struct static_cast_tag {};
|
||||
struct const_cast_tag {};
|
||||
struct dynamic_cast_tag {};
|
||||
struct reinterpret_cast_tag {};
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace detail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
|
||||
|
||||
47
libraries/include/boost/interprocess/detail/config_begin.hpp
Normal file
47
libraries/include/boost/interprocess/detail/config_begin.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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
|
||||
#endif
|
||||
17
libraries/include/boost/interprocess/detail/config_end.hpp
Normal file
17
libraries/include/boost/interprocess/detail/config_end.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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
|
||||
|
||||
202
libraries/include/boost/interprocess/detail/file_wrapper.hpp
Normal file
202
libraries/include/boost/interprocess/detail/file_wrapper.hpp
Normal file
@@ -0,0 +1,202 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. 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_FILE_WRAPPER_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_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/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail{
|
||||
|
||||
class file_wrapper
|
||||
{
|
||||
/// @cond
|
||||
file_wrapper(file_wrapper&);
|
||||
file_wrapper & operator=(file_wrapper&);
|
||||
/// @endcond
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(file_wrapper)
|
||||
|
||||
//!Default constructor.
|
||||
//!Represents an empty file_wrapper.
|
||||
file_wrapper();
|
||||
|
||||
//!Creates a file object with name "name" and mode "mode", with the access mode "mode"
|
||||
//!If the file previously exists, throws an error.
|
||||
file_wrapper(create_only_t, const char *name, mode_t mode)
|
||||
{ this->priv_open_or_create(detail::DoCreate, name, mode); }
|
||||
|
||||
//!Tries to create a file with name "name" and mode "mode", with the
|
||||
//!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
|
||||
//!Otherwise throws an error.
|
||||
file_wrapper(open_or_create_t, const char *name, mode_t mode)
|
||||
{ this->priv_open_or_create(detail::DoOpenOrCreate, name, mode); }
|
||||
|
||||
//!Tries to open a file with name "name", with the access mode "mode".
|
||||
//!If the file does not previously exist, it throws an error.
|
||||
file_wrapper(open_only_t, const char *name, mode_t mode)
|
||||
{ this->priv_open_or_create(detail::DoOpen, name, mode); }
|
||||
|
||||
//!Moves the ownership of "moved"'s file to *this.
|
||||
//!After the call, "moved" does not represent any file.
|
||||
//!Does not throw
|
||||
file_wrapper(BOOST_INTERPROCESS_RV_REF(file_wrapper) moved)
|
||||
{ this->swap(moved); }
|
||||
|
||||
//!Moves the ownership of "moved"'s file to *this.
|
||||
//!After the call, "moved" does not represent any file.
|
||||
//!Does not throw
|
||||
file_wrapper &operator=(BOOST_INTERPROCESS_RV_REF(file_wrapper) moved)
|
||||
{
|
||||
file_wrapper tmp(boost::interprocess::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps to file_wrappers.
|
||||
//!Does not throw
|
||||
void swap(file_wrapper &other);
|
||||
|
||||
//!Erases a file from the system.
|
||||
//!Returns false on error. Never throws
|
||||
static bool remove(const char *name);
|
||||
|
||||
//!Sets the size of the file
|
||||
void truncate(offset_t length);
|
||||
|
||||
//!Closes the
|
||||
//!file
|
||||
~file_wrapper();
|
||||
|
||||
//!Returns the name of the file
|
||||
//!used in the constructor
|
||||
const char *get_name() const;
|
||||
|
||||
//!Returns the name of the file
|
||||
//!used in the constructor
|
||||
bool get_size(offset_t &size) const;
|
||||
|
||||
//!Returns access mode
|
||||
//!used in the constructor
|
||||
mode_t get_mode() const;
|
||||
|
||||
//!Get mapping handle
|
||||
//!to use with mapped_region
|
||||
mapping_handle_t get_mapping_handle() const;
|
||||
|
||||
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(detail::create_enum_t type, const char *filename, mode_t mode);
|
||||
|
||||
file_handle_t m_handle;
|
||||
mode_t m_mode;
|
||||
std::string m_filename;
|
||||
};
|
||||
|
||||
inline file_wrapper::file_wrapper()
|
||||
: m_handle(file_handle_t(detail::invalid_file()))
|
||||
{}
|
||||
|
||||
inline file_wrapper::~file_wrapper()
|
||||
{ this->priv_close(); }
|
||||
|
||||
inline const char *file_wrapper::get_name() const
|
||||
{ return m_filename.c_str(); }
|
||||
|
||||
inline bool file_wrapper::get_size(offset_t &size) const
|
||||
{ return get_file_size((file_handle_t)m_handle, size); }
|
||||
|
||||
inline void file_wrapper::swap(file_wrapper &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 file_wrapper::get_mapping_handle() const
|
||||
{ return mapping_handle_from_file_handle(m_handle); }
|
||||
|
||||
inline mode_t file_wrapper::get_mode() const
|
||||
{ return m_mode; }
|
||||
|
||||
inline bool file_wrapper::priv_open_or_create
|
||||
(detail::create_enum_t type,
|
||||
const char *filename,
|
||||
mode_t mode)
|
||||
{
|
||||
m_filename = filename;
|
||||
|
||||
if(mode != read_only && mode != read_write){
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Open file existing native API to obtain the handle
|
||||
switch(type){
|
||||
case detail::DoOpen:
|
||||
m_handle = open_existing_file(filename, mode);
|
||||
break;
|
||||
case detail::DoCreate:
|
||||
m_handle = create_new_file(filename, mode);
|
||||
break;
|
||||
case detail::DoOpenOrCreate:
|
||||
m_handle = create_or_open_file(filename, mode);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//Check for error
|
||||
if(m_handle == invalid_file()){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
|
||||
m_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool file_wrapper::remove(const char *filename)
|
||||
{ return delete_file(filename); }
|
||||
|
||||
inline void file_wrapper::truncate(offset_t length)
|
||||
{
|
||||
if(!truncate_file(m_handle, length)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void file_wrapper::priv_close()
|
||||
{
|
||||
if(m_handle != invalid_file()){
|
||||
close_file(m_handle);
|
||||
m_handle = invalid_file();
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace detail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
|
||||
@@ -0,0 +1,72 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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 <typeinfo> //typeid
|
||||
|
||||
//!\file
|
||||
//!Describes an abstract interface for placement construction and destruction.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
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(detail::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 detail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
|
||||
@@ -0,0 +1,31 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2008. 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 detail{
|
||||
|
||||
class interprocess_tester
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
static void dont_close_on_destruction(T &t)
|
||||
{ t.dont_close_on_destruction(); }
|
||||
};
|
||||
|
||||
} //namespace detail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
|
||||
|
||||
1041
libraries/include/boost/interprocess/detail/intersegment_ptr.hpp
Normal file
1041
libraries/include/boost/interprocess/detail/intersegment_ptr.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,743 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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/mem_algo/rbtree_best_fit.hpp>
|
||||
#include <boost/interprocess/sync/mutex_family.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/offset_ptr.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 <cassert>
|
||||
|
||||
//!\file
|
||||
//!Describes a named shared memory allocation user class.
|
||||
//!
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
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 std::ptrdiff_t 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 std::size_t 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, std::size_t 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;
|
||||
std::size_t new_size, old_size;
|
||||
try{
|
||||
ManagedMemory managed_memory(open_only, filename);
|
||||
old_size = 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, std::size_t 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, std::size_t)
|
||||
{
|
||||
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(std::size_t 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.
|
||||
std::size_t get_size () const
|
||||
{ return mp_header->get_size() + Offset; }
|
||||
|
||||
//!Returns the number of free bytes of the memory
|
||||
//!segment
|
||||
std::size_t 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 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*>(ptr) + 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 (std::size_t 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 (std::size_t 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 (std::size_t nbytes, std::size_t 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, std::size_t limit_size,
|
||||
std::size_t preferred_size,std::size_t &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(std::size_t nbytes, std::size_t alignment)
|
||||
{ return mp_header->allocate_aligned(nbytes, alignment); }
|
||||
|
||||
/// @cond
|
||||
|
||||
//Experimental. Don't use.
|
||||
|
||||
//!Allocates n_elements of elem_size bytes.
|
||||
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements)
|
||||
{ return mp_header->allocate_many(elem_bytes, num_elements); }
|
||||
|
||||
//!Allocates n_elements, each one of elem_sizes[i] bytes.
|
||||
multiallocation_chain allocate_many(const std::size_t *elem_sizes, std::size_t n_elements)
|
||||
{ return mp_header->allocate_many(elem_sizes, n_elements); }
|
||||
|
||||
//!Allocates n_elements of elem_size bytes.
|
||||
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate_many(elem_bytes, num_elements, nothrow); }
|
||||
|
||||
//!Allocates n_elements, each one of elem_sizes[i] bytes.
|
||||
multiallocation_chain allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate_many(elem_sizes, n_elements, nothrow); }
|
||||
|
||||
//!Allocates n_elements, each one of elem_sizes[i] bytes.
|
||||
void deallocate_many(multiallocation_chain chain)
|
||||
{ return mp_header->deallocate_many(boost::interprocess::move(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*, std::size_t> 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); }
|
||||
|
||||
//!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 detail::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 std::size_t 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(std::size_t 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(std::size_t 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.
|
||||
std::size_t get_num_named_objects()
|
||||
{ return mp_header->get_num_named_objects(); }
|
||||
|
||||
//!Returns the number of unique objects stored
|
||||
//!in the managed segment.
|
||||
std::size_t 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->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->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*, std::size_t> 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
|
||||
{
|
||||
public:
|
||||
create_open_func(BasicManagedMemoryImpl * const frontend, detail::create_enum_t type)
|
||||
: m_frontend(frontend), m_type(type){}
|
||||
|
||||
bool operator()(void *addr, std::size_t size, bool created) const
|
||||
{
|
||||
if(((m_type == detail::DoOpen) && created) ||
|
||||
((m_type == detail::DoCreate) && !created))
|
||||
return false;
|
||||
|
||||
if(created)
|
||||
return m_frontend->create_impl(addr, size);
|
||||
else
|
||||
return m_frontend->open_impl (addr, size);
|
||||
}
|
||||
|
||||
private:
|
||||
BasicManagedMemoryImpl *m_frontend;
|
||||
detail::create_enum_t m_type;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2007. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
|
||||
#define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
|
||||
|
||||
#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/creation_tags.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/interprocess/detail/multi_segment_services.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/containers/list.hpp>//list
|
||||
#include <boost/interprocess/mapped_region.hpp> //mapped_region
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> //managed_open_or_create_impl
|
||||
#include <new>
|
||||
#include <boost/interprocess/containers/string.hpp>
|
||||
#include <boost/interprocess/streams/vectorstream.hpp>
|
||||
#include <memory>
|
||||
|
||||
//!\file
|
||||
//!Describes a named shared memory object allocation user class.
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//!A basic shared memory named object creation class. Initializes the
|
||||
//!shared memory segment. Inherits all basic functionality from
|
||||
//!basic_managed_memory_impl<CharType, MemoryAlgorithm, IndexType>
|
||||
template
|
||||
<
|
||||
class CharType,
|
||||
class MemoryAlgorithm,
|
||||
template<class IndexConfig> class IndexType
|
||||
>
|
||||
class basic_managed_multi_shared_memory
|
||||
: public detail::basic_managed_memory_impl
|
||||
<CharType, MemoryAlgorithm, IndexType>
|
||||
{
|
||||
|
||||
typedef basic_managed_multi_shared_memory
|
||||
<CharType, MemoryAlgorithm, IndexType> self_t;
|
||||
typedef typename MemoryAlgorithm::void_pointer void_pointer;
|
||||
typedef typename detail::
|
||||
managed_open_or_create_impl<shared_memory_object> managed_impl;
|
||||
typedef typename void_pointer::segment_group_id segment_group_id;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Some internal helper structs/functors
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//!This class defines an operator() that creates a shared memory
|
||||
//!of the requested size. The rest of the parameters are
|
||||
//!passed in the constructor. The class a template parameter
|
||||
//!to be used with create_from_file/create_from_istream functions
|
||||
//!of basic_named_object classes
|
||||
|
||||
// class segment_creator
|
||||
// {
|
||||
// public:
|
||||
// segment_creator(shared_memory &shmem,
|
||||
// const char *mem_name,
|
||||
// const void *addr)
|
||||
// : m_shmem(shmem), m_mem_name(mem_name), m_addr(addr){}
|
||||
//
|
||||
// void *operator()(std::size_t size)
|
||||
// {
|
||||
// if(!m_shmem.create(m_mem_name, size, m_addr))
|
||||
// return 0;
|
||||
// return m_shmem.get_address();
|
||||
// }
|
||||
// private:
|
||||
// shared_memory &m_shmem;
|
||||
// const char *m_mem_name;
|
||||
// const void *m_addr;
|
||||
// };
|
||||
|
||||
class group_services
|
||||
: public multi_segment_services
|
||||
{
|
||||
public:
|
||||
typedef std::pair<void *, std::size_t> result_type;
|
||||
typedef basic_managed_multi_shared_memory frontend_t;
|
||||
typedef typename
|
||||
basic_managed_multi_shared_memory::void_pointer void_pointer;
|
||||
typedef typename void_pointer::segment_group_id segment_group_id;
|
||||
group_services(frontend_t *const frontend)
|
||||
: mp_frontend(frontend), m_group(0), m_min_segment_size(0){}
|
||||
|
||||
virtual std::pair<void *, std::size_t> create_new_segment(std::size_t alloc_size)
|
||||
{
|
||||
//We should allocate an extra byte so that the
|
||||
//[base_addr + alloc_size] byte belongs to this segment
|
||||
alloc_size += 1;
|
||||
|
||||
//If requested size is less than minimum, update that
|
||||
alloc_size = (m_min_segment_size > alloc_size) ?
|
||||
m_min_segment_size : alloc_size;
|
||||
if(mp_frontend->priv_new_segment(create_open_func::DoCreate,
|
||||
alloc_size, 0)){
|
||||
shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin();
|
||||
return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1);
|
||||
}
|
||||
return result_type(static_cast<void *>(0), 0);
|
||||
}
|
||||
|
||||
virtual bool update_segments ()
|
||||
{ return true; }
|
||||
|
||||
virtual ~group_services(){}
|
||||
|
||||
void set_group(segment_group_id group)
|
||||
{ m_group = group; }
|
||||
|
||||
segment_group_id get_group() const
|
||||
{ return m_group; }
|
||||
|
||||
void set_min_segment_size(std::size_t min_segment_size)
|
||||
{ m_min_segment_size = min_segment_size; }
|
||||
|
||||
std::size_t get_min_segment_size() const
|
||||
{ return m_min_segment_size; }
|
||||
|
||||
private:
|
||||
|
||||
frontend_t * const mp_frontend;
|
||||
segment_group_id m_group;
|
||||
std::size_t m_min_segment_size;
|
||||
};
|
||||
|
||||
//!Functor to execute atomically when opening or creating a shared memory
|
||||
//!segment.
|
||||
struct create_open_func
|
||||
{
|
||||
enum type_t { DoCreate, DoOpen, DoOpenOrCreate };
|
||||
typedef typename
|
||||
basic_managed_multi_shared_memory::void_pointer void_pointer;
|
||||
|
||||
create_open_func(self_t * const frontend,
|
||||
type_t type, std::size_t segment_number)
|
||||
: mp_frontend(frontend), m_type(type), m_segment_number(segment_number){}
|
||||
|
||||
bool operator()(void *addr, std::size_t size, bool created) const
|
||||
{
|
||||
if(((m_type == DoOpen) && created) ||
|
||||
((m_type == DoCreate) && !created))
|
||||
return false;
|
||||
segment_group_id group = mp_frontend->m_group_services.get_group();
|
||||
bool mapped = false;
|
||||
bool impl_done = false;
|
||||
|
||||
//Associate this newly created segment as the
|
||||
//segment id = 0 of this group
|
||||
void_pointer::insert_mapping
|
||||
( group
|
||||
, static_cast<char*>(addr) - managed_impl::ManagedOpenOrCreateUserOffset
|
||||
, size + managed_impl::ManagedOpenOrCreateUserOffset);
|
||||
//Check if this is the master segment
|
||||
if(!m_segment_number){
|
||||
//Create or open the Interprocess machinery
|
||||
if((impl_done = created ?
|
||||
mp_frontend->create_impl(addr, size) : mp_frontend->open_impl(addr, size))){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else{
|
||||
return true;
|
||||
}
|
||||
|
||||
//This is the cleanup part
|
||||
//---------------
|
||||
if(impl_done){
|
||||
mp_frontend->close_impl();
|
||||
}
|
||||
if(mapped){
|
||||
bool ret = void_pointer::erase_last_mapping(group);
|
||||
assert(ret);(void)ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
self_t * const mp_frontend;
|
||||
type_t m_type;
|
||||
std::size_t m_segment_number;
|
||||
};
|
||||
|
||||
//!Functor to execute atomically when closing a shared memory segment.
|
||||
struct close_func
|
||||
{
|
||||
typedef typename
|
||||
basic_managed_multi_shared_memory::void_pointer void_pointer;
|
||||
|
||||
close_func(self_t * const frontend)
|
||||
: mp_frontend(frontend){}
|
||||
|
||||
void operator()(const mapped_region ®ion, bool last) const
|
||||
{
|
||||
if(last) mp_frontend->destroy_impl();
|
||||
else mp_frontend->close_impl();
|
||||
}
|
||||
self_t * const mp_frontend;
|
||||
};
|
||||
|
||||
typedef detail::basic_managed_memory_impl
|
||||
<CharType, MemoryAlgorithm, IndexType> base_t;
|
||||
|
||||
//Friend declarations
|
||||
friend struct basic_managed_multi_shared_memory::create_open_func;
|
||||
friend struct basic_managed_multi_shared_memory::close_func;
|
||||
friend class basic_managed_multi_shared_memory::group_services;
|
||||
|
||||
typedef list<managed_impl> shmem_list_t;
|
||||
|
||||
basic_managed_multi_shared_memory *get_this_pointer()
|
||||
{ return this; }
|
||||
|
||||
public:
|
||||
|
||||
basic_managed_multi_shared_memory(create_only_t,
|
||||
const char *name,
|
||||
std::size_t size)
|
||||
: m_group_services(get_this_pointer())
|
||||
{
|
||||
priv_open_or_create(create_open_func::DoCreate,name, size);
|
||||
}
|
||||
|
||||
basic_managed_multi_shared_memory(open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size)
|
||||
: m_group_services(get_this_pointer())
|
||||
{
|
||||
priv_open_or_create(create_open_func::DoOpenOrCreate, name, size);
|
||||
}
|
||||
|
||||
basic_managed_multi_shared_memory(open_only_t, const char *name)
|
||||
: m_group_services(get_this_pointer())
|
||||
{
|
||||
priv_open_or_create(create_open_func::DoOpen, name, 0);
|
||||
}
|
||||
|
||||
~basic_managed_multi_shared_memory()
|
||||
{ this->priv_close(); }
|
||||
|
||||
private:
|
||||
bool priv_open_or_create(typename create_open_func::type_t type,
|
||||
const char *name,
|
||||
std::size_t size)
|
||||
{
|
||||
if(!m_shmem_list.empty())
|
||||
return false;
|
||||
typename void_pointer::segment_group_id group = 0;
|
||||
BOOST_TRY{
|
||||
m_root_name = name;
|
||||
//Insert multi segment services and get a group identifier
|
||||
group = void_pointer::new_segment_group(&m_group_services);
|
||||
size = void_pointer::round_size(size);
|
||||
m_group_services.set_group(group);
|
||||
m_group_services.set_min_segment_size(size);
|
||||
|
||||
if(group){
|
||||
if(this->priv_new_segment(type, size, 0)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(const std::bad_alloc&){
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
if(group){
|
||||
void_pointer::delete_group(group);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool priv_new_segment(typename create_open_func::type_t type,
|
||||
std::size_t size,
|
||||
const void *addr)
|
||||
{
|
||||
BOOST_TRY{
|
||||
//Get the number of groups of this multi_segment group
|
||||
std::size_t segment_id = m_shmem_list.size();
|
||||
//Format the name of the shared memory: append segment number.
|
||||
boost::interprocess::basic_ovectorstream<boost::interprocess::string> formatter;
|
||||
//Pre-reserve string size
|
||||
std::size_t str_size = m_root_name.length()+10;
|
||||
if(formatter.vector().size() < str_size){
|
||||
//This can throw.
|
||||
formatter.reserve(str_size);
|
||||
}
|
||||
//Format segment's name
|
||||
formatter << m_root_name
|
||||
<< static_cast<unsigned int>(segment_id) << std::ends;
|
||||
//This functor will be executed when constructing
|
||||
create_open_func func(this, type, segment_id);
|
||||
const char *name = formatter.vector().c_str();
|
||||
//This can throw.
|
||||
managed_impl mshm;
|
||||
|
||||
switch(type){
|
||||
case create_open_func::DoCreate:
|
||||
{
|
||||
managed_impl shm(create_only, name, size, read_write, addr, func);
|
||||
mshm = boost::interprocess::move(shm);
|
||||
}
|
||||
break;
|
||||
|
||||
case create_open_func::DoOpen:
|
||||
{
|
||||
managed_impl shm(open_only, name,read_write, addr, func);
|
||||
mshm = boost::interprocess::move(shm);
|
||||
}
|
||||
break;
|
||||
|
||||
case create_open_func::DoOpenOrCreate:
|
||||
{
|
||||
managed_impl shm(open_or_create, name, size, read_write, addr, func);
|
||||
mshm = boost::interprocess::move(shm);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
//This can throw.
|
||||
m_shmem_list.push_back(boost::interprocess::move(mshm));
|
||||
return true;
|
||||
}
|
||||
BOOST_CATCH(const std::bad_alloc&){
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return false;
|
||||
}
|
||||
|
||||
//!Frees resources. Never throws.
|
||||
void priv_close()
|
||||
{
|
||||
if(!m_shmem_list.empty()){
|
||||
bool ret;
|
||||
//Obtain group identifier
|
||||
segment_group_id group = m_group_services.get_group();
|
||||
//Erase main segment and its resources
|
||||
shmem_list_t::iterator itbeg = m_shmem_list.begin(),
|
||||
itend = m_shmem_list.end(),
|
||||
it = itbeg;
|
||||
//(*itbeg)->close_with_func(close_func(this));
|
||||
//Delete group. All mappings are erased too.
|
||||
ret = void_pointer::delete_group(group);
|
||||
assert(ret);
|
||||
m_shmem_list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
shmem_list_t m_shmem_list;
|
||||
group_services m_group_services;
|
||||
std::string m_root_name;
|
||||
};
|
||||
|
||||
typedef basic_managed_multi_shared_memory
|
||||
< char
|
||||
, rbtree_best_fit<mutex_family, intersegment_ptr<void> >
|
||||
, iset_index>
|
||||
managed_multi_shared_memory;
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
|
||||
|
||||
@@ -0,0 +1,426 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. 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/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/detail/move.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
namespace detail{ class interprocess_tester; }
|
||||
/// @endcond
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class DeviceAbstraction, bool FileBased = true>
|
||||
class managed_open_or_create_impl
|
||||
{
|
||||
//Non-copyable
|
||||
managed_open_or_create_impl(managed_open_or_create_impl &);
|
||||
managed_open_or_create_impl &operator=(managed_open_or_create_impl &);
|
||||
|
||||
enum
|
||||
{
|
||||
UninitializedSegment,
|
||||
InitializingSegment,
|
||||
InitializedSegment,
|
||||
CorruptedSegment
|
||||
};
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(managed_open_or_create_impl)
|
||||
|
||||
static const std::size_t
|
||||
ManagedOpenOrCreateUserOffset =
|
||||
detail::ct_rounded_size
|
||||
< sizeof(boost::uint32_t)
|
||||
, detail::alignment_of<detail::max_align>::value>::value;
|
||||
|
||||
managed_open_or_create_impl()
|
||||
{}
|
||||
|
||||
managed_open_or_create_impl(create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
mode_t mode = read_write,
|
||||
const void *addr = 0)
|
||||
{
|
||||
m_name = name;
|
||||
priv_open_or_create
|
||||
( detail::DoCreate
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
managed_open_or_create_impl(open_only_t,
|
||||
const char *name,
|
||||
mode_t mode = read_write,
|
||||
const void *addr = 0)
|
||||
{
|
||||
m_name = name;
|
||||
priv_open_or_create
|
||||
( detail::DoOpen
|
||||
, 0
|
||||
, mode
|
||||
, addr
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
|
||||
managed_open_or_create_impl(open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
mode_t mode = read_write,
|
||||
const void *addr = 0)
|
||||
{
|
||||
m_name = name;
|
||||
priv_open_or_create
|
||||
( detail::DoOpenOrCreate
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
m_name = name;
|
||||
priv_open_or_create
|
||||
(detail::DoCreate
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(open_only_t,
|
||||
const char *name,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
m_name = name;
|
||||
priv_open_or_create
|
||||
( detail::DoOpen
|
||||
, 0
|
||||
, mode
|
||||
, addr
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
m_name = name;
|
||||
priv_open_or_create
|
||||
( detail::DoOpenOrCreate
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
managed_open_or_create_impl(BOOST_INTERPROCESS_RV_REF(managed_open_or_create_impl) moved)
|
||||
{ this->swap(moved); }
|
||||
|
||||
managed_open_or_create_impl &operator=(BOOST_INTERPROCESS_RV_REF(managed_open_or_create_impl) moved)
|
||||
{
|
||||
managed_open_or_create_impl tmp(boost::interprocess::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_name.swap(other.m_name);
|
||||
this->m_mapped_region.swap(other.m_mapped_region);
|
||||
}
|
||||
|
||||
const char *get_name() const
|
||||
{ return m_name.c_str(); }
|
||||
|
||||
bool flush()
|
||||
{ return m_mapped_region.flush(); }
|
||||
|
||||
|
||||
const mapped_region &get_mapped_region() const
|
||||
{ return m_mapped_region; }
|
||||
|
||||
private:
|
||||
|
||||
//These are templatized to allow explicit instantiations
|
||||
template<bool dummy>
|
||||
static void write_whole_device(DeviceAbstraction &, std::size_t, detail::false_)
|
||||
{} //Empty
|
||||
|
||||
template<bool dummy>
|
||||
static void write_whole_device(DeviceAbstraction &dev, std::size_t size, detail::true_)
|
||||
{
|
||||
file_handle_t hnd = detail::file_handle_from_mapping_handle(dev.get_mapping_handle());
|
||||
|
||||
if(size <= ManagedOpenOrCreateUserOffset){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
|
||||
size -= ManagedOpenOrCreateUserOffset;
|
||||
|
||||
if(!detail::set_file_pointer(hnd, ManagedOpenOrCreateUserOffset, file_begin)){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
|
||||
//We will write zeros in the file
|
||||
for(std::size_t remaining = size, write_size = 0
|
||||
;remaining > 0
|
||||
;remaining -= write_size){
|
||||
const std::size_t DataSize = 512;
|
||||
static char data [DataSize];
|
||||
write_size = DataSize < remaining ? DataSize : remaining;
|
||||
if(!detail::write_file(hnd, data, write_size)){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//These are templatized to allow explicit instantiations
|
||||
template<bool dummy>
|
||||
static void truncate_device(DeviceAbstraction &, std::size_t, detail::false_)
|
||||
{} //Empty
|
||||
|
||||
template<bool dummy>
|
||||
static void truncate_device(DeviceAbstraction &dev, std::size_t size, detail::true_)
|
||||
{ dev.truncate(size); }
|
||||
|
||||
//These are templatized to allow explicit instantiations
|
||||
template<bool dummy>
|
||||
static void create_device(DeviceAbstraction &dev, const char *name, std::size_t size, detail::false_)
|
||||
{
|
||||
DeviceAbstraction tmp(create_only, name, read_write, size);
|
||||
tmp.swap(dev);
|
||||
}
|
||||
|
||||
template<bool dummy>
|
||||
static void create_device(DeviceAbstraction &dev, const char *name, std::size_t, detail::true_)
|
||||
{
|
||||
DeviceAbstraction tmp(create_only, name, read_write);
|
||||
tmp.swap(dev);
|
||||
}
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
void priv_open_or_create
|
||||
(detail::create_enum_t type, std::size_t size,
|
||||
mode_t mode, const void *addr,
|
||||
ConstructFunc construct_func)
|
||||
{
|
||||
typedef detail::bool_<FileBased> file_like_t;
|
||||
(void)mode;
|
||||
error_info err;
|
||||
bool created = false;
|
||||
bool ronly = false;
|
||||
bool cow = false;
|
||||
DeviceAbstraction dev;
|
||||
|
||||
if(type != detail::DoOpen && size < ManagedOpenOrCreateUserOffset){
|
||||
throw interprocess_exception(error_info(size_error));
|
||||
}
|
||||
|
||||
if(type == detail::DoOpen && mode == read_write){
|
||||
DeviceAbstraction tmp(open_only, m_name.c_str(), read_write);
|
||||
tmp.swap(dev);
|
||||
created = false;
|
||||
}
|
||||
else if(type == detail::DoOpen && mode == read_only){
|
||||
DeviceAbstraction tmp(open_only, m_name.c_str(), read_only);
|
||||
tmp.swap(dev);
|
||||
created = false;
|
||||
ronly = true;
|
||||
}
|
||||
else if(type == detail::DoOpen && mode == copy_on_write){
|
||||
DeviceAbstraction tmp(open_only, m_name.c_str(), read_only);
|
||||
tmp.swap(dev);
|
||||
created = false;
|
||||
cow = true;
|
||||
}
|
||||
else if(type == detail::DoCreate){
|
||||
create_device<FileBased>(dev, m_name.c_str(), size, file_like_t());
|
||||
created = true;
|
||||
}
|
||||
else if(type == detail::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, m_name.c_str(), size, 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, m_name.c_str(), read_write);
|
||||
dev.swap(tmp);
|
||||
created = false;
|
||||
completed = true;
|
||||
}
|
||||
catch(interprocess_exception &ex){
|
||||
if(ex.get_error_code() != not_found_error){
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
detail::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 = detail::atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment);
|
||||
|
||||
if(previous == UninitializedSegment){
|
||||
try{
|
||||
write_whole_device<FileBased>(dev, size, file_like_t());
|
||||
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(...){
|
||||
detail::atomic_write32(patomic_word, CorruptedSegment);
|
||||
throw;
|
||||
}
|
||||
detail::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(!detail::get_file_size(detail::file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
detail::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 = detail::atomic_read32(patomic_word);
|
||||
|
||||
while(value == InitializingSegment || value == UninitializedSegment){
|
||||
detail::thread_yield();
|
||||
value = detail::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);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class detail::interprocess_tester;
|
||||
void dont_close_on_destruction()
|
||||
{ detail::interprocess_tester::dont_close_on_destruction(m_mapped_region); }
|
||||
|
||||
mapped_region m_mapped_region;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
template<class DeviceAbstraction>
|
||||
inline void swap(managed_open_or_create_impl<DeviceAbstraction> &x
|
||||
,managed_open_or_create_impl<DeviceAbstraction> &y)
|
||||
{ x.swap(y); }
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
|
||||
110
libraries/include/boost/interprocess/detail/math_functions.hpp
Normal file
110
libraries/include/boost/interprocess/detail/math_functions.hpp
Normal file
@@ -0,0 +1,110 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Stephen Cleary 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2007-2008.
|
||||
//
|
||||
// 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 detail {
|
||||
|
||||
// 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 detail
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
40
libraries/include/boost/interprocess/detail/min_max.hpp
Normal file
40
libraries/include/boost/interprocess/detail/min_max.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
//
|
||||
// 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
|
||||
|
||||
747
libraries/include/boost/interprocess/detail/move.hpp
Normal file
747
libraries/include/boost/interprocess/detail/move.hpp
Normal file
@@ -0,0 +1,747 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
|
||||
// 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/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of this file come from Adobe's Move library:
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
// or a copy at http://stlab.adobe.com/licenses.html)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MOVE_HPP
|
||||
#define BOOST_INTERPROCESS_MOVE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <algorithm> //copy, copy_backward
|
||||
#include <memory> //uninitialized_copy
|
||||
#include <iterator> //std::iterator
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/has_trivial_destructor.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace move_detail {
|
||||
|
||||
template <class T>
|
||||
struct identity
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
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:
|
||||
enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
|
||||
};
|
||||
|
||||
} //namespace move_detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#if !defined(BOOST_HAS_RVALUE_REFS) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// struct rv
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
class rv : public T
|
||||
{
|
||||
rv();
|
||||
~rv();
|
||||
rv(rv const&);
|
||||
void operator=(rv const&);
|
||||
|
||||
public:
|
||||
//T &get() { return *this; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move_detail::is_rv
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace move_detail {
|
||||
|
||||
template <class T>
|
||||
struct is_rv
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_rv< rv<T> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} //namespace move_detail {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// is_movable
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
class is_movable
|
||||
{
|
||||
public:
|
||||
static const bool value = move_detail::is_convertible<T, rv<T>&>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class is_movable< rv<T> >
|
||||
{
|
||||
public:
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move()
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
typename boost::disable_if<is_movable<T>, T&>::type move(T& x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename enable_if<is_movable<T>, rv<T>&>::type move(T& x)
|
||||
{
|
||||
return reinterpret_cast<rv<T>& >(x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename enable_if<is_movable<T>, rv<T>&>::type move(const rv<T>& x)
|
||||
{
|
||||
return const_cast<rv<T>& >(x);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// forward()
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
typename enable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
|
||||
forward(const typename move_detail::identity<T>::type &x)
|
||||
{
|
||||
return const_cast<T&>(x);
|
||||
}
|
||||
|
||||
/*
|
||||
template <class T>
|
||||
typename enable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
|
||||
forward(typename move_detail::identity<T>::type &x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename disable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
|
||||
forward(typename move_detail::identity<T>::type &x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
*/
|
||||
template <class T>
|
||||
typename disable_if<boost::interprocess::move_detail::is_rv<T>, const T &>::type
|
||||
forward(const typename move_detail::identity<T>::type &x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(TYPE)\
|
||||
operator boost::interprocess::rv<TYPE>&() \
|
||||
{ return reinterpret_cast<boost::interprocess::rv<TYPE>& >(*this); }\
|
||||
//
|
||||
|
||||
|
||||
#define BOOST_INTERPROCESS_RV_REF(TYPE)\
|
||||
boost::interprocess::rv< TYPE >& \
|
||||
//
|
||||
|
||||
#define BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
|
||||
boost::interprocess::rv< TYPE<ARG1, ARG2> >& \
|
||||
//
|
||||
|
||||
#define BOOST_INTERPROCESS_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
|
||||
boost::interprocess::rv< TYPE<ARG1, ARG2, ARG3> >& \
|
||||
//
|
||||
|
||||
#define BOOST_INTERPROCESS_FWD_REF(TYPE)\
|
||||
const TYPE & \
|
||||
//
|
||||
} //namespace interprocess {
|
||||
} //namespace boost
|
||||
|
||||
#else //BOOST_HAS_RVALUE_REFS
|
||||
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// is_movable
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! For compilers with rvalue references, this traits class returns true
|
||||
//! if T && is convertible to T.
|
||||
//!
|
||||
//! For other compilers returns true if T is convertible to <i>boost::interprocess::rv<T>&</i>
|
||||
template<class T>
|
||||
class is_movable
|
||||
{
|
||||
public:
|
||||
static const bool value = move_detail::is_convertible<T&&, T>::value;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
|
||||
//! This function provides a way to convert a reference into a rvalue reference
|
||||
//! in compilers with rvalue reference. For other compilers converts T & into
|
||||
//! <i>boost::interprocess::rv<T> &</i> so that move emulation is activated.
|
||||
template <class T> inline
|
||||
rvalue_reference move (input_reference);
|
||||
#else
|
||||
template <class T> inline
|
||||
typename remove_reference<T>::type&& move(T&& t)
|
||||
{ return t; }
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// forward
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
|
||||
//! This function provides limited form of forwarding that is usually enough for
|
||||
//! in-place construction and avoids the exponential overloading necessary for
|
||||
//! perfect forwarding in C++03.
|
||||
//!
|
||||
//! For compilers with rvalue references this function provides perfect forwarding.
|
||||
//!
|
||||
//! Otherwise:
|
||||
//! * If input_reference binds to const boost::interprocess::rv<T> & then it output_reference is
|
||||
//! boost::rev<T> &
|
||||
//!
|
||||
//! * Else, input_reference is equal to output_reference is equal to input_reference.
|
||||
template <class T> inline output_reference forward(input_reference);
|
||||
#else
|
||||
template <class T> inline
|
||||
T&& forward (typename move_detail::identity<T>::type&& t)
|
||||
{ return t; }
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! This macro expands to nothing for compilers with rvalue references.
|
||||
//! Otherwise expands to:
|
||||
//! \code
|
||||
//! operator boost::interprocess::rv<TYPE>&()
|
||||
//! { return static_cast<boost::interprocess::rv<TYPE>& >(*this); }
|
||||
//! \endcode
|
||||
#define BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(TYPE)\
|
||||
//
|
||||
|
||||
#define BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
|
||||
TYPE<ARG1, ARG2> && \
|
||||
//
|
||||
|
||||
#define BOOST_INTERPROCESS_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
|
||||
TYPE<ARG1, ARG2, ARG3> && \
|
||||
//
|
||||
|
||||
//! This macro expands to <i>T&&</i> for compilers with rvalue references.
|
||||
//! Otherwise expands to <i>boost::interprocess::rv<T> &</i>.
|
||||
#define BOOST_INTERPROCESS_RV_REF(TYPE)\
|
||||
TYPE && \
|
||||
//
|
||||
|
||||
//! This macro expands to <i>T&&</i> for compilers with rvalue references.
|
||||
//! Otherwise expands to <i>const T &</i>.
|
||||
#define BOOST_INTERPROCESS_FWD_REF(TYPE)\
|
||||
TYPE && \
|
||||
//
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //BOOST_HAS_RVALUE_REFS
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Class template move_iterator is an iterator adaptor with the same behavior
|
||||
//! as the underlying iterator except that its dereference operator implicitly
|
||||
//! converts the value returned by the underlying iterator's dereference operator
|
||||
//! to an rvalue reference. Some generic algorithms can be called with move
|
||||
//! iterators to replace copying with moving.
|
||||
template <class It>
|
||||
class move_iterator
|
||||
{
|
||||
public:
|
||||
typedef It iterator_type;
|
||||
typedef typename std::iterator_traits<iterator_type>::value_type value_type;
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
|
||||
typedef value_type && reference;
|
||||
#else
|
||||
typedef typename boost::mpl::if_
|
||||
< boost::interprocess::is_movable<value_type>
|
||||
, boost::interprocess::rv<value_type>&
|
||||
, value_type & >::type reference;
|
||||
#endif
|
||||
typedef typename std::iterator_traits<iterator_type>::pointer pointer;
|
||||
typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
|
||||
typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category;
|
||||
|
||||
move_iterator()
|
||||
{}
|
||||
|
||||
explicit move_iterator(It i)
|
||||
: m_it(i)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
move_iterator(const move_iterator<U>& u)
|
||||
: m_it(u.base())
|
||||
{}
|
||||
|
||||
iterator_type base() const
|
||||
{ return m_it; }
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
return *m_it;
|
||||
#else
|
||||
return boost::interprocess::move(*m_it);
|
||||
#endif
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{ return m_it; }
|
||||
|
||||
move_iterator& operator++()
|
||||
{ ++m_it; return *this; }
|
||||
|
||||
move_iterator<iterator_type> operator++(int)
|
||||
{ move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
|
||||
|
||||
move_iterator& operator--()
|
||||
{ --m_it; return *this; }
|
||||
|
||||
move_iterator<iterator_type> operator--(int)
|
||||
{ move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
|
||||
|
||||
move_iterator<iterator_type> operator+ (difference_type n) const
|
||||
{ return move_iterator<iterator_type>(m_it + n); }
|
||||
|
||||
move_iterator& operator+=(difference_type n)
|
||||
{ m_it += n; return *this; }
|
||||
|
||||
move_iterator<iterator_type> operator- (difference_type n) const
|
||||
{ return move_iterator<iterator_type>(m_it - n); }
|
||||
|
||||
move_iterator& operator-=(difference_type n)
|
||||
{ m_it -= n; return *this; }
|
||||
|
||||
reference operator[](difference_type n) const
|
||||
{
|
||||
#if defined(BOOST_HAS_RVALUE_REFS)
|
||||
return m_it[n];
|
||||
#else
|
||||
return boost::interprocess::move(m_it[n]);
|
||||
#endif
|
||||
}
|
||||
|
||||
friend bool operator==(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() == y.base(); }
|
||||
|
||||
friend bool operator!=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() != y.base(); }
|
||||
|
||||
friend bool operator< (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() < y.base(); }
|
||||
|
||||
friend bool operator<=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() <= y.base(); }
|
||||
|
||||
friend bool operator> (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() > y.base(); }
|
||||
|
||||
friend bool operator>=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() >= y.base(); }
|
||||
|
||||
friend difference_type operator-(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() - y.base(); }
|
||||
|
||||
friend move_iterator operator+(difference_type n, const move_iterator& x)
|
||||
{ return move_iterator(x.base() + n); }
|
||||
|
||||
private:
|
||||
It m_it;
|
||||
};
|
||||
|
||||
|
||||
//is_move_iterator
|
||||
namespace move_detail {
|
||||
|
||||
template <class I>
|
||||
struct is_move_iterator
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class I>
|
||||
struct is_move_iterator< ::boost::interprocess::move_iterator<I> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} //namespace move_detail {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: move_iterator<It>(i).
|
||||
template<class It>
|
||||
move_iterator<It> make_move_iterator(const It &it)
|
||||
{ return move_iterator<It>(it); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// back_move_insert_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//! A move insert iterator that move constructs elements at the
|
||||
//! back of a container
|
||||
template <typename C> // C models Container
|
||||
class back_move_insert_iterator
|
||||
: public std::iterator<std::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
C* container_m;
|
||||
|
||||
public:
|
||||
typedef C container_type;
|
||||
|
||||
explicit back_move_insert_iterator(C& x) : container_m(&x) { }
|
||||
|
||||
back_move_insert_iterator& operator=(typename C::reference x)
|
||||
{ container_m->push_back(boost::interprocess::move(x)); return *this; }
|
||||
|
||||
back_move_insert_iterator& operator*() { return *this; }
|
||||
back_move_insert_iterator& operator++() { return *this; }
|
||||
back_move_insert_iterator& operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: back_move_insert_iterator<C>(x).
|
||||
template <typename C> // C models Container
|
||||
inline back_move_insert_iterator<C> back_move_inserter(C& x)
|
||||
{
|
||||
return back_move_insert_iterator<C>(x);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// front_move_insert_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! A move insert iterator that move constructs elements int the
|
||||
//! front of a container
|
||||
template <typename C> // C models Container
|
||||
class front_move_insert_iterator
|
||||
: public std::iterator<std::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
C* container_m;
|
||||
|
||||
public:
|
||||
typedef C container_type;
|
||||
|
||||
explicit front_move_insert_iterator(C& x) : container_m(&x) { }
|
||||
|
||||
front_move_insert_iterator& operator=(typename C::reference x)
|
||||
{ container_m->push_front(boost::interprocess::move(x)); return *this; }
|
||||
|
||||
front_move_insert_iterator& operator*() { return *this; }
|
||||
front_move_insert_iterator& operator++() { return *this; }
|
||||
front_move_insert_iterator& operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: front_move_insert_iterator<C>(x).
|
||||
template <typename C> // C models Container
|
||||
inline front_move_insert_iterator<C> front_move_inserter(C& x)
|
||||
{
|
||||
return front_move_insert_iterator<C>(x);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// insert_move_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template <typename C> // C models Container
|
||||
class move_insert_iterator
|
||||
: public std::iterator<std::output_iterator_tag, void, void, void, void>
|
||||
{
|
||||
C* container_m;
|
||||
typename C::iterator pos_;
|
||||
|
||||
public:
|
||||
typedef C container_type;
|
||||
|
||||
explicit move_insert_iterator(C& x, typename C::iterator pos)
|
||||
: container_m(&x), pos_(pos)
|
||||
{}
|
||||
|
||||
move_insert_iterator& operator=(typename C::reference x)
|
||||
{
|
||||
pos_ = container_m->insert(pos_, boost::interprocess::move(x));
|
||||
++pos_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
move_insert_iterator& operator*() { return *this; }
|
||||
move_insert_iterator& operator++() { return *this; }
|
||||
move_insert_iterator& operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: move_insert_iterator<C>(x, it).
|
||||
template <typename C> // C models Container
|
||||
inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it)
|
||||
{
|
||||
return move_insert_iterator<C>(x, it);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
|
||||
//! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
|
||||
//! performs *(result + n) = boost::interprocess::move (*(first + n)).
|
||||
//!
|
||||
//! <b>Effects</b>: result + (last - first).
|
||||
//!
|
||||
//! <b>Requires</b>: result shall not be in the range [first,last).
|
||||
//!
|
||||
//! <b>Complexity</b>: Exactly last - first move assignments.
|
||||
template <typename I, // I models InputIterator
|
||||
typename O> // O models OutputIterator
|
||||
O move(I f, I l, O result)
|
||||
{
|
||||
while (f != l) {
|
||||
*result = boost::interprocess::move(*f);
|
||||
++f; ++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move_backward
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! <b>Effects</b>: Moves elements in the range [first,last) into the range
|
||||
//! [result - (last-first),result) starting from last - 1 and proceeding to
|
||||
//! first. For each positive integer n <= (last - first),
|
||||
//! performs *(result - n) = boost::interprocess::move(*(last - n)).
|
||||
//!
|
||||
//! <b>Requires</b>: result shall not be in the range [first,last).
|
||||
//!
|
||||
//! <b>Returns</b>: result - (last - first).
|
||||
//!
|
||||
//! <b>Complexity</b>: Exactly last - first assignments.
|
||||
template <typename I, // I models BidirectionalIterator
|
||||
typename O> // O models BidirectionalIterator
|
||||
O move_backward(I f, I l, O result)
|
||||
{
|
||||
while (f != l) {
|
||||
--l; --result;
|
||||
*result = boost::interprocess::move(*l);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uninitialized_move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! \code
|
||||
//! for (; first != last; ++result, ++first)
|
||||
//! new (static_cast<void*>(&*result))
|
||||
//! typename iterator_traits<ForwardIterator>::value_type(boost::interprocess::move(*first));
|
||||
//! \endcode
|
||||
//!
|
||||
//! <b>Returns</b>: result
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move(I f, I l, F r
|
||||
/// @cond
|
||||
,typename enable_if<is_movable<typename std::iterator_traits<I>::value_type> >::type* = 0
|
||||
/// @endcond
|
||||
)
|
||||
{
|
||||
typedef typename std::iterator_traits<I>::value_type input_value_type;
|
||||
while (f != l) {
|
||||
::new(static_cast<void*>(&*r)) input_value_type(boost::interprocess::move(*f));
|
||||
++f; ++r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/// @cond
|
||||
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move(I f, I l, F r,
|
||||
typename disable_if<is_movable<typename std::iterator_traits<I>::value_type> >::type* = 0)
|
||||
{
|
||||
return std::uninitialized_copy(f, l, r);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uninitialized_copy_or_move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace move_detail {
|
||||
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move_move_iterator(I f, I l, F r,
|
||||
typename enable_if< is_movable<typename I::value_type> >::type* = 0)
|
||||
{
|
||||
return boost::interprocess::uninitialized_move(f, l, r);
|
||||
}
|
||||
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move_move_iterator(I f, I l, F r,
|
||||
typename disable_if< is_movable<typename I::value_type> >::type* = 0)
|
||||
{
|
||||
return std::uninitialized_copy(f.base(), l.base(), r);
|
||||
}
|
||||
|
||||
} //namespace move_detail {
|
||||
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_copy_or_move(I f, I l, F r,
|
||||
typename enable_if< move_detail::is_move_iterator<I> >::type* = 0)
|
||||
{
|
||||
return boost::interprocess::move_detail::uninitialized_move_move_iterator(f, l, r);
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! \code
|
||||
//! for (; first != last; ++result, ++first)
|
||||
//! new (static_cast<void*>(&*result))
|
||||
//! typename iterator_traits<ForwardIterator>::value_type(*first);
|
||||
//! \endcode
|
||||
//!
|
||||
//! <b>Returns</b>: result
|
||||
//!
|
||||
//! <b>Note</b>: This function is provided because
|
||||
//! <i>std::uninitialized_copy</i> from some STL implementations
|
||||
//! is not compatible with <i>move_iterator</i>
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_copy_or_move(I f, I l, F r
|
||||
/// @cond
|
||||
,typename disable_if< move_detail::is_move_iterator<I> >::type* = 0
|
||||
/// @endcond
|
||||
)
|
||||
{
|
||||
return std::uninitialized_copy(f, l, r);
|
||||
}
|
||||
|
||||
///has_trivial_destructor_after_move<> == true_type
|
||||
///specialization for optimizations
|
||||
template <class T>
|
||||
struct has_trivial_destructor_after_move
|
||||
: public boost::has_trivial_destructor<T>
|
||||
{};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_MOVE_HPP
|
||||
152
libraries/include/boost/interprocess/detail/mpl.hpp
Normal file
152
libraries/include/boost/interprocess/detail/mpl.hpp
Normal file
@@ -0,0 +1,152 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
//
|
||||
// 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 detail {
|
||||
|
||||
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:
|
||||
enum { 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 detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_MULTI_SEGMENT_SERVICES_HPP
|
||||
#define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
|
||||
/*!\file
|
||||
Describes a named shared memory allocation user class.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
class multi_segment_services
|
||||
{
|
||||
public:
|
||||
virtual std::pair<void *, std::size_t> create_new_segment(std::size_t mem) = 0;
|
||||
virtual bool update_segments () = 0;
|
||||
virtual ~multi_segment_services() = 0;
|
||||
};
|
||||
|
||||
inline multi_segment_services::~multi_segment_services()
|
||||
{}
|
||||
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
|
||||
348
libraries/include/boost/interprocess/detail/named_proxy.hpp
Normal file
348
libraries/include/boost/interprocess/detail/named_proxy.hpp
Normal file
@@ -0,0 +1,348 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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/interprocess/detail/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 detail {
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
template<class T, bool is_iterator, class ...Args>
|
||||
struct CtorNArg : public placement_destroy<T>
|
||||
{
|
||||
typedef detail::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, detail::true_, const index_tuple<IdxPack...>&)
|
||||
{ new((void*)mem)T(*boost::interprocess::forward<Args>(get<IdxPack>(args_))...); }
|
||||
|
||||
template<int ...IdxPack>
|
||||
void construct(void *mem, detail::false_, const index_tuple<IdxPack...>&)
|
||||
{ new((void*)mem)T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...); }
|
||||
|
||||
template<int ...IdxPack>
|
||||
void do_increment(detail::true_, const index_tuple<IdxPack...>&)
|
||||
{
|
||||
this->expansion_helper(++get<IdxPack>(args_)...);
|
||||
}
|
||||
|
||||
template<class ...ExpansionArgs>
|
||||
void expansion_helper(ExpansionArgs &&...)
|
||||
{}
|
||||
|
||||
template<int ...IdxPack>
|
||||
void do_increment(detail::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(boost::interprocess::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 detail::bool_<is_iterator> IsIterator;
|
||||
// typedef Ctor2Arg self_t;
|
||||
//
|
||||
// void do_increment(detail::false_)
|
||||
// { ++m_p1; ++m_p2; }
|
||||
//
|
||||
// void do_increment(detail::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, detail::true_)
|
||||
// { new((void*)mem)T(*m_p1, *m_p2); }
|
||||
//
|
||||
// void construct(void *mem, detail::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 detail::bool_<is_iterator> IsIterator; \
|
||||
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \
|
||||
\
|
||||
void do_increment(detail::true_) \
|
||||
{ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INC, _); } \
|
||||
\
|
||||
void do_increment(detail::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_AUX_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, detail::true_) \
|
||||
{ \
|
||||
new((void*)mem) T \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \
|
||||
} \
|
||||
\
|
||||
void construct(void *mem, detail::false_) \
|
||||
{ \
|
||||
new((void*)mem) T \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_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 detail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
||||
@@ -0,0 +1,506 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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 <string>
|
||||
|
||||
#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>
|
||||
# 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
|
||||
, 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 detail{
|
||||
|
||||
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, 0); }
|
||||
|
||||
inline const char *get_temporary_path()
|
||||
{ return std::getenv("TMP"); }
|
||||
|
||||
inline file_handle_t create_new_file
|
||||
(const char *name, mode_t mode = read_write, bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
(name, (unsigned int)mode, winapi::create_new, attr);
|
||||
}
|
||||
|
||||
inline file_handle_t create_or_open_file
|
||||
(const char *name, mode_t mode = read_write, bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
(name, (unsigned int)mode, winapi::open_always, attr);
|
||||
}
|
||||
|
||||
inline file_handle_t open_existing_file
|
||||
(const char *name, mode_t mode = read_write, bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
(name, (unsigned int)mode, winapi::open_existing, attr);
|
||||
}
|
||||
|
||||
inline bool delete_file(const char *name)
|
||||
{ return winapi::unlink_file(name); }
|
||||
|
||||
inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
||||
{
|
||||
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 = 0xffffffff;
|
||||
// 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 = 0xffffffff;
|
||||
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 = 0xffffffff;
|
||||
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 = 0xffffffff;
|
||||
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 = 0xffffffff;
|
||||
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
|
||||
if(winapi::delete_file(strFilePath.c_str()) == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//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);
|
||||
}
|
||||
|
||||
#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
|
||||
, invalid_mode = 0xffff
|
||||
} mode_t;
|
||||
|
||||
typedef enum { file_begin = SEEK_SET
|
||||
, file_end = SEEK_END
|
||||
, file_current = SEEK_CUR
|
||||
} file_pos_t;
|
||||
|
||||
namespace detail{
|
||||
|
||||
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, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0; }
|
||||
|
||||
inline const char *get_temporary_path()
|
||||
{
|
||||
const char *dir = std::getenv("TMPDIR");
|
||||
if(!dir){
|
||||
dir = std::getenv("TMP");
|
||||
if(!dir){
|
||||
dir = std::getenv("TEMP");
|
||||
if(!dir){
|
||||
dir = "/tmp";
|
||||
}
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
inline file_handle_t create_new_file
|
||||
(const char *name, mode_t mode = read_write, bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
return ::open(name, ((int)mode) | O_EXCL | O_CREAT, S_IRWXG | S_IRWXO | S_IRWXU);
|
||||
}
|
||||
|
||||
inline file_handle_t create_or_open_file
|
||||
(const char *name, mode_t mode = read_write, bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
return ::open(name, ((int)mode) | O_CREAT, S_IRWXG | S_IRWXO | S_IRWXU);
|
||||
}
|
||||
|
||||
inline file_handle_t open_existing_file
|
||||
(const char *name, mode_t mode = read_write, bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
return ::open(name, (int)mode, S_IRWXG | S_IRWXO | S_IRWXU);
|
||||
}
|
||||
|
||||
inline bool delete_file(const char *name)
|
||||
{ return ::unlink(name) == 0; }
|
||||
|
||||
inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
||||
{ return 0 == ::ftruncate(hnd, 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 == ::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); }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//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)
|
||||
|
||||
} //namespace detail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
||||
@@ -0,0 +1,171 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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>
|
||||
|
||||
#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>
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail{
|
||||
|
||||
#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(); }
|
||||
|
||||
//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();
|
||||
}
|
||||
|
||||
#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(); }
|
||||
|
||||
//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());
|
||||
}
|
||||
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
} //namespace detail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
||||
74
libraries/include/boost/interprocess/detail/pointer_type.hpp
Normal file
74
libraries/include/boost/interprocess/detail/pointer_type.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
// (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_POINTER_TYPE_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_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>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
struct two {char _[2];};
|
||||
|
||||
namespace pointer_type_imp {
|
||||
|
||||
template <class U> static two test(...);
|
||||
template <class U> static char test(typename U::pointer* = 0);
|
||||
|
||||
} //namespace pointer_type_imp {
|
||||
|
||||
template <class T>
|
||||
struct has_pointer_type
|
||||
{
|
||||
static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
namespace pointer_type_imp {
|
||||
|
||||
template <class T, class D, bool = has_pointer_type<D>::value>
|
||||
struct pointer_type
|
||||
{
|
||||
typedef typename D::pointer type;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
struct pointer_type<T, D, false>
|
||||
{
|
||||
typedef T* type;
|
||||
};
|
||||
|
||||
} //namespace pointer_type_imp {
|
||||
|
||||
template <class T, class D>
|
||||
struct pointer_type
|
||||
{
|
||||
typedef typename pointer_type_imp::pointer_type<T,
|
||||
typename detail::remove_reference<D>::type>::type type;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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/ptime.hpp>
|
||||
//#include <boost/date_time/microsec_time_clock.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.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
|
||||
|
||||
101
libraries/include/boost/interprocess/detail/preprocessor.hpp
Normal file
101
libraries/include/boost/interprocess/detail/preprocessor.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2008. 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>
|
||||
#include <boost/interprocess/detail/workaround.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
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#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
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#define BOOST_INTERPROCESS_PARAM(U, u) \
|
||||
U && u \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_PARAM(U, u) \
|
||||
const U & u \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_INC(z, n, data) \
|
||||
BOOST_PP_CAT(++m_p, n) \
|
||||
//!
|
||||
|
||||
#ifdef BOOST_HAS_RVALUE_REFS
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
|
||||
boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
|
||||
//!
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
|
||||
boost::interprocess::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) \
|
||||
//!
|
||||
|
||||
#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
|
||||
33
libraries/include/boost/interprocess/detail/ptime_wrk.hpp
Normal file
33
libraries/include/boost/interprocess/detail/ptime_wrk.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
|
||||
#define BOOST_INTERPROCESS_PTIME_WRK_HPP
|
||||
|
||||
//workaround to avoid winsock redefines when using date-time
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifndef WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef _WIN32
|
||||
|
||||
#include <boost/date_time/posix_time/ptime.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef _WIN32
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
|
||||
|
||||
@@ -0,0 +1,504 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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/pointer_to_other.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 <cstddef> //std::size_t
|
||||
#include <string> //char_traits
|
||||
#include <new> //std::nothrow
|
||||
#include <utility> //std::pair
|
||||
#include <cassert> //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 detail{
|
||||
|
||||
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
|
||||
struct block_header
|
||||
{
|
||||
std::size_t m_value_bytes;
|
||||
unsigned short m_num_char;
|
||||
unsigned char m_value_alignment;
|
||||
unsigned char m_alloc_type_sizeof_char;
|
||||
|
||||
block_header(std::size_t value_bytes
|
||||
,std::size_t value_alignment
|
||||
,std::size_t alloc_type
|
||||
,std::size_t sizeof_char
|
||||
,std::size_t num_char
|
||||
)
|
||||
: m_value_bytes(value_bytes)
|
||||
, m_num_char(num_char)
|
||||
, m_value_alignment(value_alignment)
|
||||
, m_alloc_type_sizeof_char
|
||||
( ((unsigned char)alloc_type << 5u) |
|
||||
((unsigned char)sizeof_char & 0x1F) )
|
||||
{};
|
||||
|
||||
|
||||
template<class T>
|
||||
block_header &operator= (const T& )
|
||||
{ return *this; }
|
||||
|
||||
std::size_t total_size() const
|
||||
{
|
||||
if(alloc_type() != anonymous_type){
|
||||
return name_offset() + (m_num_char+1)*sizeof_char();
|
||||
}
|
||||
else{
|
||||
return value_offset() + m_value_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t value_bytes() const
|
||||
{ return m_value_bytes; }
|
||||
|
||||
template<class Header>
|
||||
std::size_t total_size_with_header() const
|
||||
{
|
||||
return get_rounded_size
|
||||
( sizeof(Header)
|
||||
, detail::alignment_of<block_header>::value)
|
||||
+ total_size();
|
||||
}
|
||||
|
||||
std::size_t alloc_type() const
|
||||
{ return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; }
|
||||
|
||||
std::size_t 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()));
|
||||
}
|
||||
|
||||
std::size_t name_length() const
|
||||
{ return m_num_char; }
|
||||
|
||||
std::size_t name_offset() const
|
||||
{
|
||||
return value_offset() + get_rounded_size(m_value_bytes, sizeof_char());
|
||||
}
|
||||
|
||||
void *value() const
|
||||
{
|
||||
return const_cast<char*>((reinterpret_cast<const char*>(this) + value_offset()));
|
||||
}
|
||||
|
||||
std::size_t value_offset() const
|
||||
{
|
||||
return get_rounded_size(sizeof(block_header), m_value_alignment);
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool less_comp(const block_header &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 &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 *block_header_from_value(T *value)
|
||||
{ return block_header_from_value(value, sizeof(T), detail::alignment_of<T>::value); }
|
||||
|
||||
static block_header *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
|
||||
assert(hdr->m_value_alignment == algn);
|
||||
assert(hdr->m_value_bytes % sz == 0);
|
||||
return hdr;
|
||||
}
|
||||
|
||||
template<class Header>
|
||||
static block_header *from_first_header(Header *header)
|
||||
{
|
||||
block_header * hdr =
|
||||
reinterpret_cast<block_header*>(reinterpret_cast<char*>(header) +
|
||||
get_rounded_size(sizeof(Header), detail::alignment_of<block_header>::value));
|
||||
//Some sanity checks
|
||||
return hdr;
|
||||
}
|
||||
|
||||
template<class Header>
|
||||
static Header *to_first_header(block_header *bheader)
|
||||
{
|
||||
Header * hdr =
|
||||
reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
|
||||
get_rounded_size(sizeof(Header), detail::alignment_of<block_header>::value));
|
||||
//Some sanity checks
|
||||
return hdr;
|
||||
}
|
||||
};
|
||||
|
||||
inline void array_construct(void *mem, std::size_t num, detail::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>
|
||||
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;
|
||||
|
||||
intrusive_value_type_impl(){}
|
||||
|
||||
enum { BlockHdrAlignment = detail::alignment_of<block_header>::value };
|
||||
|
||||
block_header *get_block_header() const
|
||||
{
|
||||
return const_cast<block_header*>
|
||||
(reinterpret_cast<const block_header *>(reinterpret_cast<const char*>(this) +
|
||||
get_rounded_size(sizeof(*this), BlockHdrAlignment)));
|
||||
}
|
||||
|
||||
bool operator <(const intrusive_value_type_impl<Hook, CharType> & other) const
|
||||
{ return (this->get_block_header())->template less_comp<CharType>(*other.get_block_header()); }
|
||||
|
||||
bool operator ==(const intrusive_value_type_impl<Hook, CharType> & 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 *hdr)
|
||||
{
|
||||
return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
|
||||
get_rounded_size(sizeof(intrusive_value_type_impl), BlockHdrAlignment));
|
||||
}
|
||||
|
||||
CharType *name() const
|
||||
{ return get_block_header()->template name<CharType>(); }
|
||||
|
||||
std::size_t 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 detail::anonymous_instance_t *)
|
||||
: m_name(static_cast<CharType*>(0))
|
||||
{}
|
||||
|
||||
char_ptr_holder(const detail::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::
|
||||
pointer_to_other<VoidPointer, const CharT>::type const_char_ptr_t;
|
||||
typedef CharT char_type;
|
||||
|
||||
private:
|
||||
//Offset pointer to the object's name
|
||||
const_char_ptr_t mp_str;
|
||||
//Length of the name buffer (null NOT included)
|
||||
std::size_t m_len;
|
||||
public:
|
||||
|
||||
//!Constructor of the key
|
||||
index_key (const char_type *name, std::size_t length)
|
||||
: mp_str(name), 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
|
||||
(detail::get_pointer(mp_str)
|
||||
,detail::get_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
|
||||
(detail::get_pointer(mp_str),
|
||||
detail::get_pointer(right.mp_str), m_len) == 0;
|
||||
}
|
||||
|
||||
void name(const CharT *name)
|
||||
{ mp_str = name; }
|
||||
|
||||
void name_length(std::size_t len)
|
||||
{ m_len = len; }
|
||||
|
||||
const CharT *name() const
|
||||
{ return detail::get_pointer(mp_str); }
|
||||
|
||||
std::size_t 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*>(detail::get_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 detail::index_key<CharT, void_pointer> key_type;
|
||||
typedef detail::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 detail::intrusive_value_type_impl<HeaderBase, CharT> 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(); }
|
||||
|
||||
std::size_t 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;
|
||||
|
||||
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(); }
|
||||
|
||||
std::size_t name_length() const
|
||||
{ return m_val->first.name_length(); }
|
||||
|
||||
const void *value() const
|
||||
{
|
||||
return reinterpret_cast<block_header*>
|
||||
(detail::get_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 detail {
|
||||
|
||||
//These pointers are the ones the user will use to
|
||||
//indicate previous allocation types
|
||||
static const detail::anonymous_instance_t * anonymous_instance = 0;
|
||||
static const detail::unique_instance_t * unique_instance = 0;
|
||||
|
||||
namespace detail_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
|
||||
|
||||
166
libraries/include/boost/interprocess/detail/tmp_dir_helpers.hpp
Normal file
166
libraries/include/boost/interprocess/detail/tmp_dir_helpers.hpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2008. 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_WINDOWS)
|
||||
#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
|
||||
#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
|
||||
#include <sys/sysctl.h>
|
||||
#if defined(CTL_KERN) && defined (KERN_BOOTTIME)
|
||||
#define BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME
|
||||
#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME)
|
||||
inline void get_bootstamp(std::string &s, bool add = false)
|
||||
{
|
||||
char bootstamp[winapi::BootstampLength*2+1];
|
||||
std::size_t bootstamp_length = winapi::BootstampLength*2;
|
||||
winapi::get_boot_time_str(bootstamp, bootstamp_length);
|
||||
bootstamp[winapi::BootstampLength*2] = 0;
|
||||
if(add){
|
||||
s += bootstamp;
|
||||
}
|
||||
else{
|
||||
s = bootstamp;
|
||||
}
|
||||
}
|
||||
#elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
|
||||
inline void get_bootstamp(std::string &s, bool add = false)
|
||||
{
|
||||
// FreeBSD specific: sysctl "kern.boottime"
|
||||
int request[2] = { CTL_KERN, KERN_BOOTTIME };
|
||||
struct ::timeval result;
|
||||
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;
|
||||
long fields[2] = { result.tv_sec, result.tv_usec };
|
||||
for(std::size_t field = 0; field != 2; ++field){
|
||||
for(std::size_t i = 0; i != sizeof(long); ++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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
inline void tmp_filename(const char *filename, std::string &tmp_name)
|
||||
{
|
||||
const char *tmp_dir = get_temporary_path();
|
||||
if(!tmp_dir){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
tmp_name = tmp_dir;
|
||||
|
||||
//Remove final null.
|
||||
tmp_name += "/boost_interprocess/";
|
||||
#ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
get_bootstamp(tmp_name, true);
|
||||
tmp_name += '/';
|
||||
#endif
|
||||
tmp_name += filename;
|
||||
}
|
||||
|
||||
inline void create_tmp_dir_and_get_filename(const char *filename, std::string &tmp_name)
|
||||
{
|
||||
//First get the temp directory
|
||||
const char *tmp_path = get_temporary_path();
|
||||
if(!tmp_path){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Create Boost.Interprocess dir
|
||||
tmp_name = tmp_path;
|
||||
tmp_name += "/boost_interprocess";
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
//Create a new subdirectory with the bootstamp
|
||||
std::string root_tmp_name = tmp_name;
|
||||
tmp_name += '/';
|
||||
//Obtain bootstamp string
|
||||
std::string bootstamp;
|
||||
get_bootstamp(bootstamp);
|
||||
tmp_name += bootstamp;
|
||||
|
||||
//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
|
||||
delete_subdirectories(root_tmp_name, bootstamp.c_str());
|
||||
#endif
|
||||
|
||||
//Add filename
|
||||
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 detail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
|
||||
@@ -0,0 +1,180 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
// (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 &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 T &m_value;
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunction>
|
||||
class transform_iterator
|
||||
: public UnaryFunction
|
||||
, public std::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, typename 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 interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
||||
166
libraries/include/boost/interprocess/detail/type_traits.hpp
Normal file
166
libraries/include/boost/interprocess/detail/type_traits.hpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// (C) Copyright John Maddock 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// The alignment_of implementation comes from John Maddock's boost::alignment_of code
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#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 detail {
|
||||
|
||||
struct nat{};
|
||||
|
||||
//boost::alignment_of yields to 10K lines of preprocessed code, so we
|
||||
//need an alternative
|
||||
template <typename T> struct alignment_of;
|
||||
|
||||
template <typename T>
|
||||
struct alignment_of_hack
|
||||
{
|
||||
char c;
|
||||
T t;
|
||||
alignment_of_hack();
|
||||
};
|
||||
|
||||
template <unsigned A, unsigned S>
|
||||
struct alignment_logic
|
||||
{
|
||||
enum{ value = A < S ? A : S };
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct alignment_of
|
||||
{
|
||||
enum{ value = alignment_logic
|
||||
< sizeof(alignment_of_hack<T>) - sizeof(T)
|
||||
, sizeof(T)>::value };
|
||||
};
|
||||
|
||||
//This is not standard, but should work with all compilers
|
||||
union max_align
|
||||
{
|
||||
char char_;
|
||||
short short_;
|
||||
int int_;
|
||||
long long_;
|
||||
#ifdef BOOST_HAS_LONG_LONG
|
||||
long long long_long_;
|
||||
#endif
|
||||
float float_;
|
||||
double double_;
|
||||
long double long_double_;
|
||||
void * void_ptr_;
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_reference<T&>
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer<T*>
|
||||
{
|
||||
enum { 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 <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));
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
170
libraries/include/boost/interprocess/detail/utilities.hpp
Normal file
170
libraries/include/boost/interprocess/detail/utilities.hpp
Normal file
@@ -0,0 +1,170 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008.
|
||||
// (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/interprocess/detail/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/interprocess/detail/move.hpp>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail {
|
||||
|
||||
template<class SmartPtr>
|
||||
struct smart_ptr_type
|
||||
{
|
||||
typedef typename SmartPtr::value_type value_type;
|
||||
typedef value_type *pointer;
|
||||
static pointer get (const SmartPtr &smartptr)
|
||||
{ return smartptr.get();}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct smart_ptr_type<T*>
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef value_type *pointer;
|
||||
static pointer get (pointer ptr)
|
||||
{ return ptr;}
|
||||
};
|
||||
|
||||
//!Overload for smart pointers to avoid ADL problems with get_pointer
|
||||
template<class Ptr>
|
||||
inline typename smart_ptr_type<Ptr>::pointer
|
||||
get_pointer(const Ptr &ptr)
|
||||
{ return smart_ptr_type<Ptr>::get(ptr); }
|
||||
|
||||
//!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
|
||||
inline std::size_t get_rounded_size(std::size_t orig_size, std::size_t round_to)
|
||||
{
|
||||
return ((orig_size-1)/round_to+1)*round_to;
|
||||
}
|
||||
|
||||
//Truncates "orig_size" to a multiple of "multiple" bytes.
|
||||
inline std::size_t get_truncated_size(std::size_t orig_size, std::size_t multiple)
|
||||
{
|
||||
return orig_size/multiple*multiple;
|
||||
}
|
||||
|
||||
//Rounds "orig_size" by excess to round_to bytes. round_to must be power of two
|
||||
inline std::size_t get_rounded_size_po2(std::size_t orig_size, std::size_t 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
|
||||
inline std::size_t get_truncated_size_po2(std::size_t orig_size, std::size_t multiple)
|
||||
{
|
||||
return (orig_size & (~(multiple-1)));
|
||||
}
|
||||
|
||||
template <std::size_t OrigSize, std::size_t RoundTo>
|
||||
struct ct_rounded_size
|
||||
{
|
||||
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
|
||||
};
|
||||
|
||||
// Gennaro Prota wrote this. Thanks!
|
||||
template <int p, int n = 4>
|
||||
struct ct_max_pow2_less
|
||||
{
|
||||
enum { 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 detail {
|
||||
|
||||
//!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
|
||||
{
|
||||
enum { 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
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template <typename T> T*
|
||||
addressof(T& v)
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
||||
}
|
||||
|
||||
//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-2008. 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 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 interprocess { namespace detail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
889
libraries/include/boost/interprocess/detail/win32_api.hpp
Normal file
889
libraries/include/boost/interprocess/detail/win32_api.hpp
Normal file
@@ -0,0 +1,889 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_WIN32_SYNC_PRIMITIVES_HPP
|
||||
#define BOOST_INTERPROCESS_WIN32_SYNC_PRIMITIVES_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
# pragma comment( lib, "advapi32.lib" )
|
||||
#endif
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
# include <cstdarg>
|
||||
# include <boost/detail/interlocked.hpp>
|
||||
#else
|
||||
# error "This file can only be included in Windows OS"
|
||||
#endif
|
||||
|
||||
//The structures used in Interprocess with the
|
||||
//same binary interface as windows ones
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace winapi {
|
||||
|
||||
//Some used constants
|
||||
static const unsigned long infinite_time = 0xFFFFFFFF;
|
||||
static const unsigned long error_already_exists = 183L;
|
||||
static const unsigned long error_file_not_found = 2u;
|
||||
static const unsigned long error_no_more_files = 18u;
|
||||
|
||||
static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3;
|
||||
static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001;
|
||||
|
||||
static const unsigned long page_readonly = 0x02;
|
||||
static const unsigned long page_readwrite = 0x04;
|
||||
static const unsigned long page_writecopy = 0x08;
|
||||
|
||||
static const unsigned long standard_rights_required = 0x000F0000L;
|
||||
static const unsigned long section_query = 0x0001;
|
||||
static const unsigned long section_map_write = 0x0002;
|
||||
static const unsigned long section_map_read = 0x0004;
|
||||
static const unsigned long section_map_execute = 0x0008;
|
||||
static const unsigned long section_extend_size = 0x0010;
|
||||
static const unsigned long section_all_access = standard_rights_required |
|
||||
section_query |
|
||||
section_map_write |
|
||||
section_map_read |
|
||||
section_map_execute |
|
||||
section_extend_size;
|
||||
|
||||
static const unsigned long file_map_copy = section_query;
|
||||
static const unsigned long file_map_write = section_map_write;
|
||||
static const unsigned long file_map_read = section_map_read;
|
||||
static const unsigned long file_map_all_access = section_all_access;
|
||||
static const unsigned long delete_access = 0x00010000L;
|
||||
static const unsigned long file_flag_backup_semantics = 0x02000000;
|
||||
static const long file_flag_delete_on_close = 0x04000000;
|
||||
|
||||
//Native API constants
|
||||
static const unsigned long file_open_for_backup_intent = 0x00004000;
|
||||
static const int file_share_valid_flags = 0x00000007;
|
||||
static const long file_delete_on_close = 0x00001000L;
|
||||
static const long obj_case_insensitive = 0x00000040L;
|
||||
|
||||
static const unsigned long movefile_copy_allowed = 0x02;
|
||||
static const unsigned long movefile_delay_until_reboot = 0x04;
|
||||
static const unsigned long movefile_replace_existing = 0x01;
|
||||
static const unsigned long movefile_write_through = 0x08;
|
||||
static const unsigned long movefile_create_hardlink = 0x10;
|
||||
static const unsigned long movefile_fail_if_not_trackable = 0x20;
|
||||
|
||||
static const unsigned long file_share_read = 0x00000001;
|
||||
static const unsigned long file_share_write = 0x00000002;
|
||||
static const unsigned long file_share_delete = 0x00000004;
|
||||
|
||||
static const unsigned long file_attribute_readonly = 0x00000001;
|
||||
static const unsigned long file_attribute_hidden = 0x00000002;
|
||||
static const unsigned long file_attribute_system = 0x00000004;
|
||||
static const unsigned long file_attribute_directory = 0x00000010;
|
||||
static const unsigned long file_attribute_archive = 0x00000020;
|
||||
static const unsigned long file_attribute_device = 0x00000040;
|
||||
static const unsigned long file_attribute_normal = 0x00000080;
|
||||
static const unsigned long file_attribute_temporary = 0x00000100;
|
||||
|
||||
static const unsigned long generic_read = 0x80000000L;
|
||||
static const unsigned long generic_write = 0x40000000L;
|
||||
|
||||
static const unsigned long wait_object_0 = 0;
|
||||
static const unsigned long wait_abandoned = 0x00000080L;
|
||||
static const unsigned long wait_timeout = 258L;
|
||||
static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF;
|
||||
|
||||
static const unsigned long duplicate_close_source = (unsigned long)0x00000001;
|
||||
static const unsigned long duplicate_same_access = (unsigned long)0x00000002;
|
||||
|
||||
static const unsigned long format_message_allocate_buffer
|
||||
= (unsigned long)0x00000100;
|
||||
static const unsigned long format_message_ignore_inserts
|
||||
= (unsigned long)0x00000200;
|
||||
static const unsigned long format_message_from_string
|
||||
= (unsigned long)0x00000400;
|
||||
static const unsigned long format_message_from_hmodule
|
||||
= (unsigned long)0x00000800;
|
||||
static const unsigned long format_message_from_system
|
||||
= (unsigned long)0x00001000;
|
||||
static const unsigned long format_message_argument_array
|
||||
= (unsigned long)0x00002000;
|
||||
static const unsigned long format_message_max_width_mask
|
||||
= (unsigned long)0x000000FF;
|
||||
static const unsigned long lang_neutral = (unsigned long)0x00;
|
||||
static const unsigned long sublang_default = (unsigned long)0x01;
|
||||
static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF;
|
||||
static void * const invalid_handle_value = (void*)(long)(-1);
|
||||
static const unsigned long create_new = 1;
|
||||
static const unsigned long create_always = 2;
|
||||
static const unsigned long open_existing = 3;
|
||||
static const unsigned long open_always = 4;
|
||||
static const unsigned long truncate_existing = 5;
|
||||
|
||||
static const unsigned long file_begin = 0;
|
||||
static const unsigned long file_current = 1;
|
||||
static const unsigned long file_end = 2;
|
||||
|
||||
static const unsigned long lockfile_fail_immediately = 1;
|
||||
static const unsigned long lockfile_exclusive_lock = 2;
|
||||
static const unsigned long error_lock_violation = 33;
|
||||
static const unsigned long security_descriptor_revision = 1;
|
||||
|
||||
//Own defines
|
||||
static const long SystemTimeOfDayInfoLength = 48;
|
||||
static const long BootAndSystemstampLength = 16;
|
||||
static const long BootstampLength = 8;
|
||||
static const unsigned long MaxPath = 260;
|
||||
|
||||
|
||||
} //namespace winapi {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#if !defined( BOOST_USE_WINDOWS_H )
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace winapi {
|
||||
|
||||
struct interprocess_overlapped
|
||||
{
|
||||
unsigned long *internal;
|
||||
unsigned long *internal_high;
|
||||
union {
|
||||
struct {
|
||||
unsigned long offset;
|
||||
unsigned long offset_high;
|
||||
}dummy;
|
||||
void *pointer;
|
||||
};
|
||||
|
||||
void *h_event;
|
||||
};
|
||||
|
||||
struct interprocess_filetime
|
||||
{
|
||||
unsigned long dwLowDateTime;
|
||||
unsigned long dwHighDateTime;
|
||||
};
|
||||
|
||||
struct win32_find_data_t
|
||||
{
|
||||
unsigned long dwFileAttributes;
|
||||
interprocess_filetime ftCreationTime;
|
||||
interprocess_filetime ftLastAccessTime;
|
||||
interprocess_filetime ftLastWriteTime;
|
||||
unsigned long nFileSizeHigh;
|
||||
unsigned long nFileSizeLow;
|
||||
unsigned long dwReserved0;
|
||||
unsigned long dwReserved1;
|
||||
char cFileName[MaxPath];
|
||||
char cAlternateFileName[14];
|
||||
};
|
||||
|
||||
struct interprocess_security_attributes
|
||||
{
|
||||
unsigned long nLength;
|
||||
void *lpSecurityDescriptor;
|
||||
int bInheritHandle;
|
||||
};
|
||||
|
||||
struct system_info {
|
||||
union {
|
||||
unsigned long dwOemId; // Obsolete field...do not use
|
||||
struct {
|
||||
unsigned short wProcessorArchitecture;
|
||||
unsigned short wReserved;
|
||||
} dummy;
|
||||
};
|
||||
unsigned long dwPageSize;
|
||||
void * lpMinimumApplicationAddress;
|
||||
void * lpMaximumApplicationAddress;
|
||||
unsigned long * dwActiveProcessorMask;
|
||||
unsigned long dwNumberOfProcessors;
|
||||
unsigned long dwProcessorType;
|
||||
unsigned long dwAllocationGranularity;
|
||||
unsigned short wProcessorLevel;
|
||||
unsigned short wProcessorRevision;
|
||||
};
|
||||
|
||||
struct interprocess_memory_basic_information
|
||||
{
|
||||
void * BaseAddress;
|
||||
void * AllocationBase;
|
||||
unsigned long AllocationProtect;
|
||||
unsigned long RegionSize;
|
||||
unsigned long State;
|
||||
unsigned long Protect;
|
||||
unsigned long Type;
|
||||
};
|
||||
|
||||
typedef struct _interprocess_acl
|
||||
{
|
||||
unsigned char AclRevision;
|
||||
unsigned char Sbz1;
|
||||
unsigned short AclSize;
|
||||
unsigned short AceCount;
|
||||
unsigned short Sbz2;
|
||||
} interprocess_acl;
|
||||
|
||||
typedef struct _interprocess_security_descriptor
|
||||
{
|
||||
unsigned char Revision;
|
||||
unsigned char Sbz1;
|
||||
unsigned short Control;
|
||||
void *Owner;
|
||||
void *Group;
|
||||
interprocess_acl *Sacl;
|
||||
interprocess_acl *Dacl;
|
||||
} interprocess_security_descriptor;
|
||||
|
||||
enum file_information_class_t {
|
||||
file_directory_information = 1,
|
||||
file_full_directory_information,
|
||||
file_both_directory_information,
|
||||
file_basic_information,
|
||||
file_standard_information,
|
||||
file_internal_information,
|
||||
file_ea_information,
|
||||
file_access_information,
|
||||
file_name_information,
|
||||
file_rename_information,
|
||||
file_link_information,
|
||||
file_names_information,
|
||||
file_disposition_information,
|
||||
file_position_information,
|
||||
file_full_ea_information,
|
||||
file_mode_information,
|
||||
file_alignment_information,
|
||||
file_all_information,
|
||||
file_allocation_information,
|
||||
file_end_of_file_information,
|
||||
file_alternate_name_information,
|
||||
file_stream_information,
|
||||
file_pipe_information,
|
||||
file_pipe_local_information,
|
||||
file_pipe_remote_information,
|
||||
file_mailslot_query_information,
|
||||
file_mailslot_set_information,
|
||||
file_compression_information,
|
||||
file_copy_on_write_information,
|
||||
file_completion_information,
|
||||
file_move_cluster_information,
|
||||
file_quota_information,
|
||||
file_reparse_point_information,
|
||||
file_network_open_information,
|
||||
file_object_id_information,
|
||||
file_tracking_information,
|
||||
file_ole_directory_information,
|
||||
file_content_index_information,
|
||||
file_inherit_content_index_information,
|
||||
file_ole_information,
|
||||
file_maximum_information
|
||||
};
|
||||
|
||||
struct file_name_information_t {
|
||||
unsigned long FileNameLength;
|
||||
wchar_t FileName[1];
|
||||
};
|
||||
|
||||
struct file_rename_information_t {
|
||||
int Replace;
|
||||
void *RootDir;
|
||||
unsigned long FileNameLength;
|
||||
wchar_t FileName[1];
|
||||
};
|
||||
|
||||
struct unicode_string_t {
|
||||
unsigned short Length;
|
||||
unsigned short MaximumLength;
|
||||
wchar_t *Buffer;
|
||||
};
|
||||
|
||||
struct object_attributes_t {
|
||||
unsigned long Length;
|
||||
void * RootDirectory;
|
||||
unicode_string_t *ObjectName;
|
||||
unsigned long Attributes;
|
||||
void *SecurityDescriptor;
|
||||
void *SecurityQualityOfService;
|
||||
};
|
||||
|
||||
struct io_status_block_t {
|
||||
union {
|
||||
long Status;
|
||||
void *Pointer;
|
||||
};
|
||||
|
||||
unsigned long *Information;
|
||||
};
|
||||
|
||||
union system_timeofday_information
|
||||
{
|
||||
struct data_t
|
||||
{
|
||||
__int64 liKeBootTime;
|
||||
__int64 liKeSystemTime;
|
||||
__int64 liExpTimeZoneBias;
|
||||
unsigned long uCurrentTimeZoneId;
|
||||
unsigned long dwReserved;
|
||||
} data;
|
||||
unsigned char Reserved1[SystemTimeOfDayInfoLength];
|
||||
};
|
||||
|
||||
enum system_information_class {
|
||||
system_basic_information = 0,
|
||||
system_performance_information = 2,
|
||||
system_time_of_day_information = 3,
|
||||
system_process_information = 5,
|
||||
system_processor_performance_information = 8,
|
||||
system_interrupt_information = 23,
|
||||
system_exception_information = 33,
|
||||
system_registry_quota_information = 37,
|
||||
system_lookaside_information = 45
|
||||
};
|
||||
|
||||
enum object_information_class
|
||||
{
|
||||
object_basic_information,
|
||||
object_name_information,
|
||||
object_type_information,
|
||||
object_all_information,
|
||||
object_data_information
|
||||
};
|
||||
|
||||
struct object_name_information_t
|
||||
{
|
||||
unicode_string_t Name;
|
||||
wchar_t NameBuffer[1];
|
||||
};
|
||||
|
||||
//Some windows API declarations
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
|
||||
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError();
|
||||
extern "C" __declspec(dllimport) void * __stdcall GetCurrentProcess();
|
||||
extern "C" __declspec(dllimport) int __stdcall CloseHandle(void*);
|
||||
extern "C" __declspec(dllimport) int __stdcall DuplicateHandle
|
||||
( void *hSourceProcessHandle, void *hSourceHandle
|
||||
, void *hTargetProcessHandle, void **lpTargetHandle
|
||||
, unsigned long dwDesiredAccess, int bInheritHandle
|
||||
, unsigned long dwOptions);
|
||||
extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData);
|
||||
extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData);
|
||||
extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile);
|
||||
extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*);
|
||||
extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateMutexA(interprocess_security_attributes*, int, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall OpenMutexA(unsigned long, int, const char *);
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void *, unsigned long);
|
||||
extern "C" __declspec(dllimport) int __stdcall ReleaseMutex(void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall UnmapViewOfFile(void *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateSemaphoreA(interprocess_security_attributes*, long, long, const char *);
|
||||
extern "C" __declspec(dllimport) int __stdcall ReleaseSemaphore(void *, long, long *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall OpenSemaphoreA(unsigned long, int, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, interprocess_security_attributes*, unsigned long, unsigned long, unsigned long, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, std::size_t, void*);
|
||||
extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *);
|
||||
extern "C" __declspec(dllimport) int __stdcall MoveFileExA (const char *, const char *, unsigned long);
|
||||
extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *);
|
||||
extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t);
|
||||
extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size);
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA
|
||||
(unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId,
|
||||
unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize,
|
||||
std::va_list *Arguments);
|
||||
extern "C" __declspec(dllimport) void *__stdcall LocalFree (void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall CreateDirectoryA(const char *, interprocess_security_attributes*);
|
||||
extern "C" __declspec(dllimport) int __stdcall RemoveDirectoryA(const char *lpPathName);
|
||||
extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length, char *buffer);
|
||||
extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*);
|
||||
extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size);
|
||||
extern "C" __declspec(dllimport) int __stdcall SetEndOfFile(void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, __int64 distance, __int64 *new_file_pointer, unsigned long move_method);
|
||||
extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
|
||||
extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
|
||||
extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
|
||||
extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
|
||||
extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped);
|
||||
extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision);
|
||||
extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted);
|
||||
extern "C" __declspec(dllimport) void *__stdcall LoadLibraryA(const char *);
|
||||
extern "C" __declspec(dllimport) int __stdcall FreeLibrary(void *);
|
||||
extern "C" __declspec(dllimport) void *__stdcall GetProcAddress(void *, const char*);
|
||||
extern "C" __declspec(dllimport) void *__stdcall GetModuleHandleA(const char*);
|
||||
|
||||
//API function typedefs
|
||||
//Pointer to functions
|
||||
typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes);
|
||||
typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass );
|
||||
typedef long (__stdcall *NtQueryInformationFile_t)(void *,io_status_block_t *,void *, long, int);
|
||||
typedef long (__stdcall *NtOpenFile_t)(void*,unsigned long ,object_attributes_t*,io_status_block_t*,unsigned long,unsigned long);
|
||||
typedef long (__stdcall *NtClose_t) (void*);
|
||||
typedef long (__stdcall *RtlCreateUnicodeStringFromAsciiz_t)(unicode_string_t *, const char *);
|
||||
typedef void (__stdcall *RtlFreeUnicodeString_t)(unicode_string_t *);
|
||||
typedef void (__stdcall *RtlInitUnicodeString_t)( unicode_string_t *, const wchar_t * );
|
||||
typedef long (__stdcall *RtlAppendUnicodeToString_t)(unicode_string_t *Destination, const wchar_t *Source);
|
||||
typedef long (__stdcall * NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *);
|
||||
typedef long (__stdcall * NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *);
|
||||
typedef unsigned long (__stdcall * GetMappedFileName_t)(void *, void *, wchar_t *, unsigned long);
|
||||
|
||||
} //namespace winapi {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#else
|
||||
# include <windows.h>
|
||||
#endif //#if !defined( BOOST_USE_WINDOWS_H )
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace winapi {
|
||||
|
||||
static inline unsigned long format_message
|
||||
(unsigned long dwFlags, const void *lpSource,
|
||||
unsigned long dwMessageId, unsigned long dwLanguageId,
|
||||
char *lpBuffer, unsigned long nSize, std::va_list *Arguments)
|
||||
{
|
||||
return FormatMessageA
|
||||
(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
|
||||
}
|
||||
|
||||
//And now, wrapper functions
|
||||
static inline void * local_free(void *hmem)
|
||||
{ return LocalFree(hmem); }
|
||||
|
||||
static inline unsigned long make_lang_id(unsigned long p, unsigned long s)
|
||||
{ return ((((unsigned short)(s)) << 10) | (unsigned short)(p)); }
|
||||
|
||||
static inline void sched_yield()
|
||||
{ Sleep(1); }
|
||||
|
||||
static inline unsigned long get_current_thread_id()
|
||||
{ return GetCurrentThreadId(); }
|
||||
|
||||
static inline unsigned long get_current_process_id()
|
||||
{ return GetCurrentProcessId(); }
|
||||
|
||||
static inline unsigned int close_handle(void* handle)
|
||||
{ return CloseHandle(handle); }
|
||||
|
||||
static inline void * find_first_file(const char *lpFileName, win32_find_data_t *lpFindFileData)
|
||||
{ return FindFirstFileA(lpFileName, lpFindFileData); }
|
||||
|
||||
static inline bool find_next_file(void *hFindFile, win32_find_data_t *lpFindFileData)
|
||||
{ return FindNextFileA(hFindFile, lpFindFileData) != 0; }
|
||||
|
||||
static inline bool find_close(void *handle)
|
||||
{ return FindClose(handle) != 0; }
|
||||
|
||||
static inline bool duplicate_current_process_handle
|
||||
(void *hSourceHandle, void **lpTargetHandle)
|
||||
{
|
||||
return 0 != DuplicateHandle
|
||||
( GetCurrentProcess(), hSourceHandle, GetCurrentProcess()
|
||||
, lpTargetHandle, 0, 0
|
||||
, duplicate_same_access);
|
||||
}
|
||||
|
||||
static inline unsigned long get_last_error()
|
||||
{ return GetLastError(); }
|
||||
|
||||
static inline void get_system_time_as_file_time(interprocess_filetime *filetime)
|
||||
{ GetSystemTimeAsFileTime(filetime); }
|
||||
|
||||
static inline bool file_time_to_local_file_time
|
||||
(const interprocess_filetime *in, const interprocess_filetime *out)
|
||||
{ return 0 != FileTimeToLocalFileTime(in, out); }
|
||||
|
||||
static inline void *create_mutex(const char *name)
|
||||
{ return CreateMutexA(0, 0, name); }
|
||||
|
||||
static inline void *open_mutex(const char *name)
|
||||
{ return OpenMutexA(mutex_all_access, 0, name); }
|
||||
|
||||
static inline unsigned long wait_for_single_object(void *handle, unsigned long time)
|
||||
{ return WaitForSingleObject(handle, time); }
|
||||
|
||||
static inline int release_mutex(void *handle)
|
||||
{ return ReleaseMutex(handle); }
|
||||
|
||||
static inline int unmap_view_of_file(void *address)
|
||||
{ return UnmapViewOfFile(address); }
|
||||
|
||||
static inline void *create_semaphore(long initialCount, const char *name)
|
||||
{ return CreateSemaphoreA(0, initialCount, (long)(((unsigned long)(-1))>>1), name); }
|
||||
|
||||
static inline int release_semaphore(void *handle, long release_count, long *prev_count)
|
||||
{ return ReleaseSemaphore(handle, release_count, prev_count); }
|
||||
|
||||
static inline void *open_semaphore(const char *name)
|
||||
{ return OpenSemaphoreA(semaphore_all_access, 1, name); }
|
||||
|
||||
static inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name)
|
||||
{
|
||||
interprocess_security_attributes sa;
|
||||
interprocess_security_descriptor sd;
|
||||
|
||||
if(!InitializeSecurityDescriptor(&sd, security_descriptor_revision))
|
||||
return 0;
|
||||
if(!SetSecurityDescriptorDacl(&sd, true, 0, false))
|
||||
return 0;
|
||||
sa.lpSecurityDescriptor = &sd;
|
||||
sa.nLength = sizeof(interprocess_security_attributes);
|
||||
sa.bInheritHandle = false;
|
||||
return CreateFileMappingA (handle, &sa, access, high_size, low_size, name);
|
||||
//return CreateFileMappingA (handle, 0, access, high_size, low_size, name);
|
||||
}
|
||||
|
||||
static inline void * open_file_mapping (unsigned long access, const char *name)
|
||||
{ return OpenFileMappingA (access, 0, name); }
|
||||
|
||||
static inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned long highoffset, unsigned long lowoffset, std::size_t numbytes, void *base_addr)
|
||||
{ return MapViewOfFileEx(handle, file_access, highoffset, lowoffset, numbytes, base_addr); }
|
||||
|
||||
static inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes = 0)
|
||||
{ return CreateFileA(name, access, file_share_read | file_share_write | file_share_delete, 0, creation_flags, attributes, 0); }
|
||||
|
||||
static inline bool delete_file(const char *name)
|
||||
{ return 0 != DeleteFileA(name); }
|
||||
|
||||
static inline bool move_file_ex(const char *source_filename, const char *destination_filename, unsigned long flags)
|
||||
{ return 0 != MoveFileExA(source_filename, destination_filename, flags); }
|
||||
|
||||
static inline void get_system_info(system_info *info)
|
||||
{ GetSystemInfo(info); }
|
||||
|
||||
static inline int flush_view_of_file(void *base_addr, std::size_t numbytes)
|
||||
{ return FlushViewOfFile(base_addr, numbytes); }
|
||||
|
||||
static inline bool get_file_size(void *handle, __int64 &size)
|
||||
{ return 0 != GetFileSizeEx(handle, &size); }
|
||||
|
||||
static inline bool create_directory(const char *name, interprocess_security_attributes* security)
|
||||
{ return 0 != CreateDirectoryA(name, security); }
|
||||
|
||||
static inline bool remove_directory(const char *lpPathName)
|
||||
{ return 0 != RemoveDirectoryA(lpPathName); }
|
||||
|
||||
static inline unsigned long get_temp_path(unsigned long length, char *buffer)
|
||||
{ return GetTempPathA(length, buffer); }
|
||||
|
||||
static inline int set_end_of_file(void *handle)
|
||||
{ return 0 != SetEndOfFile(handle); }
|
||||
|
||||
static inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method)
|
||||
{ return 0 != SetFilePointerEx(handle, distance, new_file_pointer, move_method); }
|
||||
|
||||
static inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
|
||||
{ return 0 != LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped); }
|
||||
|
||||
static inline bool unlock_file_ex(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
|
||||
{ return 0 != UnlockFileEx(hnd, reserved, size_low, size_high, overlapped); }
|
||||
|
||||
static inline bool write_file(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped)
|
||||
{ return 0 != WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); }
|
||||
|
||||
static inline long interlocked_increment(long volatile *addr)
|
||||
{ return BOOST_INTERLOCKED_INCREMENT(addr); }
|
||||
|
||||
static inline long interlocked_decrement(long volatile *addr)
|
||||
{ return BOOST_INTERLOCKED_DECREMENT(addr); }
|
||||
|
||||
static inline long interlocked_compare_exchange(long volatile *addr, long val1, long val2)
|
||||
{ return BOOST_INTERLOCKED_COMPARE_EXCHANGE(addr, val1, val2); }
|
||||
|
||||
static inline long interlocked_exchange_add(long volatile* addend, long value)
|
||||
{ return BOOST_INTERLOCKED_EXCHANGE_ADD(const_cast<long*>(addend), value); }
|
||||
|
||||
static inline long interlocked_exchange(long volatile* addend, long value)
|
||||
{ return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); }
|
||||
|
||||
//Forward functions
|
||||
static inline void *load_library(const char *name)
|
||||
{ return LoadLibraryA(name); }
|
||||
|
||||
static inline bool free_library(void *module)
|
||||
{ return 0 != FreeLibrary(module); }
|
||||
|
||||
static inline void *get_proc_address(void *module, const char *name)
|
||||
{ return GetProcAddress(module, name); }
|
||||
|
||||
static inline void *get_current_process()
|
||||
{ return GetCurrentProcess(); }
|
||||
|
||||
static inline void *get_module_handle(const char *name)
|
||||
{ return GetModuleHandleA(name); }
|
||||
|
||||
static inline void initialize_object_attributes
|
||||
( object_attributes_t *pobject_attr, unicode_string_t *name
|
||||
, unsigned long attr, void *rootdir, void *security_descr)
|
||||
|
||||
{
|
||||
pobject_attr->Length = sizeof(object_attributes_t);
|
||||
pobject_attr->RootDirectory = rootdir;
|
||||
pobject_attr->Attributes = attr;
|
||||
pobject_attr->ObjectName = name;
|
||||
pobject_attr->SecurityDescriptor = security_descr;
|
||||
pobject_attr->SecurityQualityOfService = 0;
|
||||
}
|
||||
|
||||
static inline void rtl_init_empty_unicode_string(unicode_string_t *ucStr, wchar_t *buf, unsigned short bufSize)
|
||||
{
|
||||
ucStr->Buffer = buf;
|
||||
ucStr->Length = 0;
|
||||
ucStr->MaximumLength = bufSize;
|
||||
}
|
||||
|
||||
//Complex winapi based functions...
|
||||
|
||||
//pszFilename must have room for at least MaxPath+1 characters
|
||||
static inline bool get_file_name_from_handle_function
|
||||
(void * hFile, wchar_t *pszFilename, std::size_t length, std::size_t &out_length)
|
||||
{
|
||||
if(length <= MaxPath){
|
||||
return false;
|
||||
}
|
||||
|
||||
void *hiPSAPI = load_library("PSAPI.DLL");
|
||||
if (0 == hiPSAPI)
|
||||
return 0;
|
||||
|
||||
class library_unloader
|
||||
{
|
||||
void *lib_;
|
||||
|
||||
public:
|
||||
library_unloader(void *module) : lib_(module){}
|
||||
~library_unloader(){ free_library(lib_); }
|
||||
} unloader(hiPSAPI);
|
||||
|
||||
// Pointer to function getMappedFileName() in PSAPI.DLL
|
||||
GetMappedFileName_t pfGMFN =
|
||||
(GetMappedFileName_t)get_proc_address(hiPSAPI, "GetMappedFileNameW");
|
||||
if (! pfGMFN){
|
||||
return 0; // Failed: unexpected error
|
||||
}
|
||||
|
||||
bool bSuccess = false;
|
||||
|
||||
// Create a file mapping object.
|
||||
void * hFileMap = create_file_mapping(hFile, page_readonly, 0, 1, 0);
|
||||
if(hFileMap)
|
||||
{
|
||||
// Create a file mapping to get the file name.
|
||||
void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 0, 1, 0);
|
||||
|
||||
if (pMem){
|
||||
out_length = pfGMFN(get_current_process(), pMem, pszFilename, MaxPath);
|
||||
if(out_length){
|
||||
bSuccess = true;
|
||||
}
|
||||
unmap_view_of_file(pMem);
|
||||
}
|
||||
close_handle(hFileMap);
|
||||
}
|
||||
|
||||
return(bSuccess);
|
||||
}
|
||||
|
||||
static inline bool get_system_time_of_day_information(system_timeofday_information &info)
|
||||
{
|
||||
NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t)
|
||||
get_proc_address(get_module_handle("ntdll.dll"), "NtQuerySystemInformation");
|
||||
unsigned long res;
|
||||
long status = pNtQuerySystemInformation(system_time_of_day_information, &info, sizeof(info), &res);
|
||||
if(status){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool get_boot_time(unsigned char (&bootstamp) [BootstampLength])
|
||||
{
|
||||
system_timeofday_information info;
|
||||
bool ret = get_system_time_of_day_information(info);
|
||||
if(!ret){
|
||||
return false;
|
||||
}
|
||||
std::memcpy(&bootstamp[0], &info.Reserved1, sizeof(bootstamp));
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool get_boot_and_system_time(unsigned char (&bootsystemstamp) [BootAndSystemstampLength])
|
||||
{
|
||||
system_timeofday_information info;
|
||||
bool ret = get_system_time_of_day_information(info);
|
||||
if(!ret){
|
||||
return false;
|
||||
}
|
||||
std::memcpy(&bootsystemstamp[0], &info.Reserved1, sizeof(bootsystemstamp));
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write BootstampLength chars
|
||||
{
|
||||
if(s < (BootstampLength*2))
|
||||
return false;
|
||||
system_timeofday_information info;
|
||||
bool ret = get_system_time_of_day_information(info);
|
||||
if(!ret){
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
for(std::size_t i = 0; i != static_cast<std::size_t>(BootstampLength); ++i){
|
||||
bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
|
||||
bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
|
||||
}
|
||||
s = BootstampLength*2;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars
|
||||
{
|
||||
if(s < (BootAndSystemstampLength*2))
|
||||
return false;
|
||||
system_timeofday_information info;
|
||||
bool ret = get_system_time_of_day_information(info);
|
||||
if(!ret){
|
||||
return false;
|
||||
}
|
||||
const wchar_t Characters [] =
|
||||
{ L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
|
||||
, L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
|
||||
std::size_t char_counter = 0;
|
||||
for(std::size_t i = 0; i != static_cast<std::size_t>(BootAndSystemstampLength); ++i){
|
||||
bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4];
|
||||
bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0x0F)];
|
||||
}
|
||||
s = BootAndSystemstampLength*2;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool unlink_file(const char *filename)
|
||||
{
|
||||
try{
|
||||
NtSetInformationFile_t pNtSetInformationFile =
|
||||
(NtSetInformationFile_t)get_proc_address(get_module_handle("ntdll.dll"), "NtSetInformationFile");
|
||||
if(!pNtSetInformationFile){
|
||||
return false;
|
||||
}
|
||||
|
||||
NtQueryObject_t pNtQueryObject =
|
||||
(NtQueryObject_t)get_proc_address(get_module_handle("ntdll.dll"), "NtQueryObject");
|
||||
|
||||
//First step: Obtain a handle to the file using Win32 rules. This resolves relative paths
|
||||
void *fh = create_file(filename, generic_read | delete_access, open_existing,
|
||||
file_flag_backup_semantics | file_flag_delete_on_close);
|
||||
if(fh == invalid_handle_value){
|
||||
return false;
|
||||
}
|
||||
|
||||
class handle_closer
|
||||
{
|
||||
void *handle_;
|
||||
public:
|
||||
handle_closer(void *handle) : handle_(handle){}
|
||||
~handle_closer(){ close_handle(handle_); }
|
||||
} handle_closer(fh);
|
||||
|
||||
const std::size_t CharArraySize = 32767; //Max name length
|
||||
|
||||
union mem_t
|
||||
{
|
||||
object_name_information_t name;
|
||||
struct ren_t
|
||||
{
|
||||
file_rename_information_t info;
|
||||
wchar_t buf[CharArraySize];
|
||||
} ren;
|
||||
};
|
||||
|
||||
class auto_ptr
|
||||
{
|
||||
public:
|
||||
explicit auto_ptr(mem_t *ptr) : ptr_(ptr){}
|
||||
~auto_ptr(){ delete ptr_; }
|
||||
mem_t *get() const{ return (ptr_); }
|
||||
mem_t *operator->() const{ return this->get(); }
|
||||
private:
|
||||
mem_t *ptr_;
|
||||
} pmem(new mem_t);
|
||||
|
||||
file_rename_information_t *pfri = (file_rename_information_t*)&pmem->ren.info;
|
||||
const std::size_t RenMaxNumChars =
|
||||
((char*)pmem.get() - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t);
|
||||
|
||||
//Obtain file name
|
||||
unsigned long size;
|
||||
if(pNtQueryObject(fh, object_name_information, pmem.get(), sizeof(mem_t), &size)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Copy filename to the rename member
|
||||
std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length);
|
||||
std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t);
|
||||
|
||||
//Second step: obtain the complete native-nt filename
|
||||
//if(!get_file_name_from_handle_function(fh, pfri->FileName, RenMaxNumChars, filename_string_length)){
|
||||
//return 0;
|
||||
//}
|
||||
|
||||
//Add trailing mark
|
||||
if((RenMaxNumChars-filename_string_length) < (SystemTimeOfDayInfoLength*2)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Search '\\' character to replace it
|
||||
for(std::size_t i = filename_string_length; i != 0; --filename_string_length){
|
||||
if(pmem->ren.info.FileName[--i] == L'\\')
|
||||
break;
|
||||
}
|
||||
|
||||
//Add random number
|
||||
std::size_t s = RenMaxNumChars - filename_string_length;
|
||||
if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){
|
||||
return false;
|
||||
}
|
||||
filename_string_length += s;
|
||||
|
||||
//Fill rename information (FileNameLength is in bytes)
|
||||
pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length));
|
||||
pfri->Replace = 1;
|
||||
pfri->RootDir = 0;
|
||||
|
||||
//Final step: change the name of the in-use file:
|
||||
io_status_block_t io;
|
||||
if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(mem_t::ren_t), file_rename_information)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace winapi
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_WIN32_SYNC_PRIMITIVES_HPP
|
||||
132
libraries/include/boost/interprocess/detail/workaround.hpp
Normal file
132
libraries/include/boost/interprocess/detail/workaround.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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
|
||||
|
||||
/*
|
||||
#if !defined(_MSC_EXTENSIONS)
|
||||
#error "Turn on Microsoft language extensions (_MSC_EXTENSIONS) to be able to call Windows API functions"
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#if ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
|
||||
//Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
|
||||
//Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work.
|
||||
# if !defined(__CYGWIN__) && !defined(__APPLE__)
|
||||
# define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_BARRIERS - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_BARRIERS
|
||||
# endif
|
||||
|
||||
#if ((_POSIX_SEMAPHORES - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
# if defined(__CYGWIN__)
|
||||
#define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
|
||||
# endif
|
||||
//#elif 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
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
#else
|
||||
//VMS and MACOS don't define it but the have shm_open/close interface
|
||||
# if defined(__vms)
|
||||
# if __CRTL_VER >= 70200000
|
||||
# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
# endif
|
||||
# define BOOST_INTERPROCESS_SYSTEM_V_SHARED_MEMORY_OBJECTS
|
||||
//Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
|
||||
//# elif defined (__APPLE__)
|
||||
//# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_TIMEOUTS - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
#endif
|
||||
|
||||
//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__)
|
||||
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_RESOURCES
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_RESOURCES)
|
||||
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
#if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_RESOURCES)
|
||||
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500)
|
||||
#define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)\
|
||||
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
|
||||
#define BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#endif
|
||||
|
||||
//Now declare some Boost.Interprocess features depending on the implementation
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
|
||||
|
||||
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
|
||||
|
||||
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
|
||||
#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
|
||||
233
libraries/include/boost/interprocess/errors.hpp
Normal file
233
libraries/include/boost/interprocess/errors.hpp
Normal file
@@ -0,0 +1,233 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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
|
||||
static 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
|
||||
static 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
|
||||
};
|
||||
|
||||
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 }
|
||||
#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)
|
||||
};
|
||||
|
||||
static 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
|
||||
145
libraries/include/boost/interprocess/exceptions.hpp
Normal file
145
libraries/include/boost/interprocess/exceptions.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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(error_code_t ec = other_error )
|
||||
: m_err(ec)
|
||||
{
|
||||
try { m_str = "boost::interprocess_exception::library_error"; }
|
||||
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)
|
||||
: m_err(err_info)
|
||||
{
|
||||
try{
|
||||
if(m_err.get_native_error() != 0){
|
||||
fill_system_message(m_err.get_native_error(), m_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:
|
||||
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
|
||||
188
libraries/include/boost/interprocess/file_mapping.hpp
Normal file
188
libraries/include/boost/interprocess/file_mapping.hpp
Normal file
@@ -0,0 +1,188 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_FILE_MAPPING_HPP
|
||||
#define BOOST_INTERPROCESS_FILE_MAPPING_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/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <string> //std::string
|
||||
|
||||
//!\file
|
||||
//!Describes file_mapping and mapped region classes
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!A class that wraps a file-mapping that can be used to
|
||||
//!create mapped regions from the mapped files
|
||||
class file_mapping
|
||||
{
|
||||
/// @cond
|
||||
//Non-copyable and non-assignable
|
||||
file_mapping(file_mapping &);
|
||||
file_mapping &operator=(file_mapping &);
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(file_mapping)
|
||||
|
||||
//!Constructs an empty file mapping.
|
||||
//!Does not throw
|
||||
file_mapping();
|
||||
|
||||
//!Opens a file mapping of file "filename", starting in offset
|
||||
//!"file_offset", and the mapping's size will be "size". The mapping
|
||||
//!can be opened for read-only "read_only" or read-write "read_write"
|
||||
//!modes. Throws interprocess_exception on error.
|
||||
file_mapping(const char *filename, mode_t mode);
|
||||
|
||||
//!Moves the ownership of "moved"'s file mapping object to *this.
|
||||
//!After the call, "moved" does not represent any file mapping object.
|
||||
//!Does not throw
|
||||
file_mapping(BOOST_INTERPROCESS_RV_REF(file_mapping) moved)
|
||||
: m_handle(file_handle_t(detail::invalid_file()))
|
||||
{ this->swap(moved); }
|
||||
|
||||
//!Moves the ownership of "moved"'s file mapping to *this.
|
||||
//!After the call, "moved" does not represent any file mapping.
|
||||
//!Does not throw
|
||||
file_mapping &operator=(BOOST_INTERPROCESS_RV_REF(file_mapping) moved)
|
||||
{
|
||||
file_mapping tmp(boost::interprocess::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps to file_mappings.
|
||||
//!Does not throw.
|
||||
void swap(file_mapping &other);
|
||||
|
||||
//!Returns access mode
|
||||
//!used in the constructor
|
||||
mode_t get_mode() const;
|
||||
|
||||
//!Obtains the mapping handle
|
||||
//!to be used with mapped_region
|
||||
mapping_handle_t get_mapping_handle() const;
|
||||
|
||||
//!Destroys the file mapping. All mapped regions created from this are still
|
||||
//!valid. Does not throw
|
||||
~file_mapping();
|
||||
|
||||
//!Returns the name of the file
|
||||
//!used in the constructor.
|
||||
const char *get_name() const;
|
||||
|
||||
//!Removes the file named "filename" even if it's been memory mapped.
|
||||
//!Returns true on success.
|
||||
//!The function might fail in some operating systems if the file is
|
||||
//!being used other processes and no deletion permission was shared.
|
||||
static bool remove(const char *filename);
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
//!Closes a previously opened file mapping. Never throws.
|
||||
void priv_close();
|
||||
file_handle_t m_handle;
|
||||
mode_t m_mode;
|
||||
std::string m_filename;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
inline file_mapping::file_mapping()
|
||||
: m_handle(file_handle_t(detail::invalid_file()))
|
||||
{}
|
||||
|
||||
inline file_mapping::~file_mapping()
|
||||
{ this->priv_close(); }
|
||||
|
||||
inline const char *file_mapping::get_name() const
|
||||
{ return m_filename.c_str(); }
|
||||
|
||||
inline void file_mapping::swap(file_mapping &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 file_mapping::get_mapping_handle() const
|
||||
{ return detail::mapping_handle_from_file_handle(m_handle); }
|
||||
|
||||
inline mode_t file_mapping::get_mode() const
|
||||
{ return m_mode; }
|
||||
|
||||
inline file_mapping::file_mapping
|
||||
(const char *filename, mode_t mode)
|
||||
: m_filename(filename)
|
||||
{
|
||||
//Check accesses
|
||||
if (mode != read_write && mode != read_only){
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Open file
|
||||
m_handle = detail::open_existing_file(filename, mode);
|
||||
|
||||
//Check for error
|
||||
if(m_handle == detail::invalid_file()){
|
||||
error_info err = system_error_code();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
inline bool file_mapping::remove(const char *filename)
|
||||
{ return detail::delete_file(filename); }
|
||||
|
||||
///@cond
|
||||
|
||||
inline void file_mapping::priv_close()
|
||||
{
|
||||
if(m_handle != detail::invalid_file()){
|
||||
detail::close_file(m_handle);
|
||||
m_handle = detail::invalid_file();
|
||||
}
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
//!A class that stores the name of a file
|
||||
//!and tries to remove it in its destructor
|
||||
//!Useful to remove temporary files in the presence
|
||||
//!of exceptions
|
||||
class remove_file_on_destroy
|
||||
{
|
||||
const char * m_name;
|
||||
public:
|
||||
remove_file_on_destroy(const char *name)
|
||||
: m_name(name)
|
||||
{}
|
||||
|
||||
~remove_file_on_destroy()
|
||||
{ detail::delete_file(m_name); }
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_FILE_MAPPING_HPP
|
||||
@@ -0,0 +1,78 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_FLAT_MAP_INDEX_HPP
|
||||
#define BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <boost/interprocess/containers/flat_map.hpp>
|
||||
#include <boost/interprocess/allocators/allocator.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes index adaptor of boost::map container, to use it
|
||||
//!as name/shared memory index
|
||||
|
||||
//[flat_map_index
|
||||
namespace boost { namespace interprocess {
|
||||
|
||||
//!Helper class to define typedefs from IndexTraits
|
||||
template <class MapConfig>
|
||||
struct flat_map_index_aux
|
||||
{
|
||||
typedef typename MapConfig::key_type key_type;
|
||||
typedef typename MapConfig::mapped_type mapped_type;
|
||||
typedef typename MapConfig::
|
||||
segment_manager_base segment_manager_base;
|
||||
typedef std::less<key_type> key_less;
|
||||
typedef std::pair<key_type, mapped_type> value_type;
|
||||
typedef allocator<value_type
|
||||
,segment_manager_base> allocator_type;
|
||||
typedef flat_map<key_type, mapped_type,
|
||||
key_less, allocator_type> index_t;
|
||||
};
|
||||
|
||||
//!Index type based in flat_map. Just derives from flat_map and
|
||||
//!defines the interface needed by managed memory segments.
|
||||
template <class MapConfig>
|
||||
class flat_map_index
|
||||
//Derive class from flat_map specialization
|
||||
: public flat_map_index_aux<MapConfig>::index_t
|
||||
{
|
||||
/// @cond
|
||||
typedef flat_map_index_aux<MapConfig> index_aux;
|
||||
typedef typename index_aux::index_t base_type;
|
||||
typedef typename index_aux::
|
||||
segment_manager_base segment_manager_base;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor. Takes a pointer to the segment manager. Can throw
|
||||
flat_map_index(segment_manager_base *segment_mngr)
|
||||
: base_type(typename index_aux::key_less(),
|
||||
typename index_aux::allocator_type(segment_mngr))
|
||||
{}
|
||||
|
||||
//!This reserves memory to optimize the insertion of n elements in the index
|
||||
void reserve(std::size_t n)
|
||||
{ base_type::reserve(n); }
|
||||
|
||||
//!This frees all unnecessary memory
|
||||
void shrink_to_fit()
|
||||
{ base_type::shrink_to_fit(); }
|
||||
};
|
||||
|
||||
}} //namespace boost { namespace interprocess
|
||||
//]
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP
|
||||
150
libraries/include/boost/interprocess/indexes/iset_index.hpp
Normal file
150
libraries/include/boost/interprocess/indexes/iset_index.hpp
Normal file
@@ -0,0 +1,150 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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(std::size_t)
|
||||
{ /*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> >
|
||||
{
|
||||
enum{ value = true };
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP
|
||||
@@ -0,0 +1,367 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_IUNORDERED_SET_INDEX_HPP
|
||||
#define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <boost/get_pointer.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/containers/vector.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/interprocess/allocators/allocator.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes index adaptor of boost::intrusive::unordered_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 iunordered_set_index_aux
|
||||
{
|
||||
typedef typename
|
||||
MapConfig::segment_manager_base segment_manager_base;
|
||||
|
||||
typedef typename
|
||||
segment_manager_base::void_pointer void_pointer;
|
||||
|
||||
typedef typename bi::make_unordered_set_base_hook
|
||||
< bi::void_pointer<void_pointer>
|
||||
>::type derivation_hook;
|
||||
|
||||
typedef typename MapConfig::template
|
||||
intrusive_value_type<derivation_hook>::type value_type;
|
||||
|
||||
typedef typename MapConfig::
|
||||
intrusive_compare_key_type intrusive_compare_key_type;
|
||||
|
||||
typedef std::equal_to<value_type> value_equal;
|
||||
|
||||
typedef typename MapConfig::char_type char_type;
|
||||
|
||||
struct equal_function
|
||||
{
|
||||
bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
|
||||
{
|
||||
return (i.m_len == b.name_length()) &&
|
||||
(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
|
||||
{
|
||||
return (i.m_len == b.name_length()) &&
|
||||
(std::char_traits<char_type>::compare
|
||||
(i.mp_str, b.name(), i.m_len) == 0);
|
||||
}
|
||||
|
||||
bool operator()(const value_type &b1, const value_type &b2) const
|
||||
{
|
||||
return (b1.name_length() == b2.name_length()) &&
|
||||
(std::char_traits<char_type>::compare
|
||||
(b1.name(), b2.name(), b1.name_length()) == 0);
|
||||
}
|
||||
};
|
||||
|
||||
struct hash_function
|
||||
: std::unary_function<value_type, std::size_t>
|
||||
{
|
||||
std::size_t operator()(const value_type &val) const
|
||||
{
|
||||
const char_type *beg = detail::get_pointer(val.name()),
|
||||
*end = beg + val.name_length();
|
||||
return boost::hash_range(beg, end);
|
||||
}
|
||||
|
||||
std::size_t operator()(const intrusive_compare_key_type &i) const
|
||||
{
|
||||
const char_type *beg = i.mp_str,
|
||||
*end = beg + i.m_len;
|
||||
return boost::hash_range(beg, end);
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename bi::make_unordered_set
|
||||
< value_type
|
||||
, bi::hash<hash_function>
|
||||
, bi::equal<equal_function>
|
||||
>::type index_t;
|
||||
typedef typename index_t::bucket_type bucket_type;
|
||||
typedef allocator
|
||||
<bucket_type, segment_manager_base> allocator_type;
|
||||
|
||||
struct allocator_holder
|
||||
{
|
||||
allocator_holder(segment_manager_base *mngr)
|
||||
: alloc(mngr)
|
||||
{}
|
||||
allocator_type alloc;
|
||||
bucket_type init_bucket;
|
||||
};
|
||||
};
|
||||
/// @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 iunordered_set_index
|
||||
//Derive class from map specialization
|
||||
: private iunordered_set_index_aux<MapConfig>::allocator_holder
|
||||
, public iunordered_set_index_aux<MapConfig>::index_t
|
||||
{
|
||||
/// @cond
|
||||
typedef iunordered_set_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 index_aux::equal_function equal_function;
|
||||
typedef typename index_aux::hash_function hash_function;
|
||||
typedef typename MapConfig::char_type char_type;
|
||||
typedef typename
|
||||
iunordered_set_index_aux<MapConfig>::allocator_type allocator_type;
|
||||
typedef typename
|
||||
iunordered_set_index_aux<MapConfig>::allocator_holder allocator_holder;
|
||||
/// @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;
|
||||
typedef typename index_type::bucket_ptr bucket_ptr;
|
||||
typedef typename index_type::bucket_type bucket_type;
|
||||
typedef typename index_type::bucket_traits bucket_traits;
|
||||
typedef typename index_type::size_type size_type;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef typename index_aux::
|
||||
segment_manager_base segment_manager_base;
|
||||
|
||||
enum { InitBufferSize = 64};
|
||||
|
||||
static bucket_ptr create_buckets(allocator_type &alloc, std::size_t num)
|
||||
{
|
||||
num = index_type::suggested_upper_bucket_count(num);
|
||||
bucket_ptr buckets = alloc.allocate(num);
|
||||
bucket_ptr buckets_init = buckets;
|
||||
for(std::size_t i = 0; i < num; ++i){
|
||||
new(get_pointer(buckets_init++))bucket_type();
|
||||
}
|
||||
return buckets;
|
||||
}
|
||||
|
||||
static std::size_t shrink_buckets
|
||||
( bucket_ptr buckets, std::size_t old_size
|
||||
, allocator_type &alloc, std::size_t new_size)
|
||||
{
|
||||
if(old_size <= new_size )
|
||||
return old_size;
|
||||
std::size_t received_size;
|
||||
if(!alloc.allocation_command
|
||||
(boost::interprocess::try_shrink_in_place | boost::interprocess::nothrow_allocation, old_size, new_size, received_size, buckets).first){
|
||||
return old_size;
|
||||
}
|
||||
|
||||
for( bucket_type *p = detail::get_pointer(buckets) + received_size
|
||||
, *pend = detail::get_pointer(buckets) + old_size
|
||||
; p != pend
|
||||
; ++p){
|
||||
p->~bucket_type();
|
||||
}
|
||||
|
||||
bucket_ptr shunk_p = alloc.allocation_command
|
||||
(boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, received_size, buckets).first;
|
||||
BOOST_ASSERT(buckets == shunk_p);
|
||||
|
||||
bucket_ptr buckets_init = buckets + received_size;
|
||||
for(std::size_t i = 0; i < (old_size - received_size); ++i){
|
||||
get_pointer(buckets_init++)->~bucket_type();
|
||||
}
|
||||
return received_size;
|
||||
}
|
||||
|
||||
static bucket_ptr expand_or_create_buckets
|
||||
( bucket_ptr old_buckets, const std::size_t old_num
|
||||
, allocator_type &alloc, const std::size_t new_num)
|
||||
{
|
||||
std::size_t received_size;
|
||||
std::pair<bucket_ptr, bool> ret =
|
||||
alloc.allocation_command
|
||||
(boost::interprocess::expand_fwd | boost::interprocess::allocate_new, new_num, new_num, received_size, old_buckets);
|
||||
if(ret.first == old_buckets){
|
||||
bucket_ptr buckets_init = old_buckets + old_num;
|
||||
for(std::size_t i = 0; i < (new_num - old_num); ++i){
|
||||
new(get_pointer(buckets_init++))bucket_type();
|
||||
}
|
||||
}
|
||||
else{
|
||||
bucket_ptr buckets_init = ret.first;
|
||||
for(std::size_t i = 0; i < new_num; ++i){
|
||||
new(get_pointer(buckets_init++))bucket_type();
|
||||
}
|
||||
}
|
||||
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
static void destroy_buckets
|
||||
(allocator_type &alloc, bucket_ptr buckets, std::size_t num)
|
||||
{
|
||||
bucket_ptr buckets_destroy = buckets;
|
||||
for(std::size_t i = 0; i < num; ++i){
|
||||
get_pointer(buckets_destroy++)->~bucket_type();
|
||||
}
|
||||
alloc.deallocate(buckets, num);
|
||||
}
|
||||
|
||||
iunordered_set_index<MapConfig>* get_this_pointer()
|
||||
{ return this; }
|
||||
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor. Takes a pointer to the
|
||||
//!segment manager. Can throw
|
||||
iunordered_set_index(segment_manager_base *mngr)
|
||||
: allocator_holder(mngr)
|
||||
, index_type(bucket_traits(&get_this_pointer()->init_bucket, 1))
|
||||
{}
|
||||
|
||||
~iunordered_set_index()
|
||||
{
|
||||
index_type::clear();
|
||||
if(index_type::bucket_pointer() != bucket_ptr(&this->init_bucket)){
|
||||
destroy_buckets(this->alloc, index_type::bucket_pointer(), index_type::bucket_count());
|
||||
}
|
||||
}
|
||||
|
||||
//!This reserves memory to optimize the insertion of n
|
||||
//!elements in the index
|
||||
void reserve(std::size_t new_n)
|
||||
{
|
||||
//Let's maintain a 1.0f load factor
|
||||
size_type old_n = this->bucket_count();
|
||||
if(new_n <= old_n)
|
||||
return;
|
||||
bucket_ptr old_p = this->bucket_pointer();
|
||||
new_n = index_type::suggested_upper_bucket_count(new_n);
|
||||
bucket_ptr new_p;
|
||||
//This can throw
|
||||
try{
|
||||
if(old_p != bucket_ptr(&this->init_bucket))
|
||||
new_p = expand_or_create_buckets(old_p, old_n, this->alloc, new_n);
|
||||
else
|
||||
new_p = create_buckets(this->alloc, new_n);
|
||||
}
|
||||
catch(...){
|
||||
return;
|
||||
}
|
||||
//Rehashing does not throw, since neither the hash nor the
|
||||
//comparison function can throw
|
||||
this->rehash(bucket_traits(new_p, new_n));
|
||||
if(new_p != old_p && old_p != bucket_ptr(&this->init_bucket)){
|
||||
destroy_buckets(this->alloc, old_p, old_n);
|
||||
}
|
||||
}
|
||||
|
||||
//!This tries to free unused memory
|
||||
//!previously allocated.
|
||||
void shrink_to_fit()
|
||||
{
|
||||
size_type cur_size = this->size();
|
||||
size_type cur_count = this->bucket_count();
|
||||
bucket_ptr old_p = this->bucket_pointer();
|
||||
|
||||
if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){
|
||||
this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1));
|
||||
destroy_buckets(this->alloc, old_p, cur_count);
|
||||
}
|
||||
else{
|
||||
size_type sug_count = 0; //gcc warning
|
||||
sug_count = index_type::suggested_upper_bucket_count(cur_size);
|
||||
|
||||
if(sug_count >= cur_count)
|
||||
return;
|
||||
|
||||
try{
|
||||
shrink_buckets(old_p, cur_count, this->alloc, sug_count);
|
||||
}
|
||||
catch(...){
|
||||
return;
|
||||
}
|
||||
|
||||
//Rehashing does not throw, since neither the hash nor the
|
||||
//comparison function can throw
|
||||
this->rehash(bucket_traits(old_p, sug_count));
|
||||
}
|
||||
}
|
||||
|
||||
iterator find(const intrusive_compare_key_type &key)
|
||||
{ return index_type::find(key, hash_function(), equal_function()); }
|
||||
|
||||
const_iterator find(const intrusive_compare_key_type &key) const
|
||||
{ return index_type::find(key, hash_function(), equal_function()); }
|
||||
|
||||
std::pair<iterator, bool>insert_check
|
||||
(const intrusive_compare_key_type &key, insert_commit_data &commit_data)
|
||||
{ return index_type::insert_check(key, hash_function(), equal_function(), commit_data); }
|
||||
|
||||
iterator insert_commit(value_type &val, insert_commit_data &commit_data)
|
||||
{
|
||||
iterator it = index_type::insert_commit(val, commit_data);
|
||||
size_type cur_size = this->size();
|
||||
if(cur_size > this->bucket_count()){
|
||||
try{
|
||||
this->reserve(cur_size);
|
||||
}
|
||||
catch(...){
|
||||
//Strong guarantee: if something goes wrong
|
||||
//we should remove the insertion.
|
||||
//
|
||||
//We can use the iterator because the hash function
|
||||
//can't throw and this means that "reserve" will
|
||||
//throw only because of the memory allocation:
|
||||
//the iterator has not been invalidated.
|
||||
index_type::erase(it);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
//!Trait class to detect if an index is an intrusive
|
||||
//!index
|
||||
template<class MapConfig>
|
||||
struct is_intrusive_index
|
||||
<boost::interprocess::iunordered_set_index<MapConfig> >
|
||||
{
|
||||
enum{ value = true };
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP
|
||||
100
libraries/include/boost/interprocess/indexes/map_index.hpp
Normal file
100
libraries/include/boost/interprocess/indexes/map_index.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_MAP_INDEX_HPP
|
||||
#define BOOST_INTERPROCESS_MAP_INDEX_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <boost/interprocess/containers/map.hpp>
|
||||
#include <boost/interprocess/allocators/private_adaptive_pool.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes index adaptor of boost::map container, to use it
|
||||
//!as name/shared memory index
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace detail{
|
||||
|
||||
//!Helper class to define typedefs from IndexTraits
|
||||
template <class MapConfig>
|
||||
struct map_index_aux
|
||||
{
|
||||
typedef typename MapConfig::key_type key_type;
|
||||
typedef typename MapConfig::mapped_type mapped_type;
|
||||
typedef std::less<key_type> key_less;
|
||||
typedef std::pair<const key_type, mapped_type> value_type;
|
||||
|
||||
typedef private_adaptive_pool
|
||||
<value_type,
|
||||
typename MapConfig::
|
||||
segment_manager_base> allocator_type;
|
||||
|
||||
typedef boost::interprocess::map
|
||||
<key_type, mapped_type,
|
||||
key_less, allocator_type> index_t;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
//!Index type based in boost::interprocess::map. Just derives from boost::interprocess::map
|
||||
//!and defines the interface needed by managed memory segments
|
||||
template <class MapConfig>
|
||||
class map_index
|
||||
//Derive class from map specialization
|
||||
: public detail::map_index_aux<MapConfig>::index_t
|
||||
{
|
||||
/// @cond
|
||||
typedef detail::map_index_aux<MapConfig> index_aux;
|
||||
typedef typename index_aux::index_t base_type;
|
||||
typedef typename MapConfig::
|
||||
segment_manager_base segment_manager_base;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor. Takes a pointer to the
|
||||
//!segment manager. Can throw
|
||||
map_index(segment_manager_base *segment_mngr)
|
||||
: base_type(typename index_aux::key_less(),
|
||||
segment_mngr){}
|
||||
|
||||
//!This reserves memory to optimize the insertion of n
|
||||
//!elements in the index
|
||||
void reserve(std::size_t)
|
||||
{ /*Does nothing, map has not reserve or rehash*/ }
|
||||
|
||||
//!This tries to free previously allocate
|
||||
//!unused memory.
|
||||
void shrink_to_fit()
|
||||
{ base_type::get_stored_allocator().deallocate_free_blocks(); }
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
//!Trait class to detect if an index is a node
|
||||
//!index. This allows more efficient operations
|
||||
//!when deallocating named objects.
|
||||
template<class MapConfig>
|
||||
struct is_node_index
|
||||
<boost::interprocess::map_index<MapConfig> >
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP
|
||||
68
libraries/include/boost/interprocess/indexes/null_index.hpp
Normal file
68
libraries/include/boost/interprocess/indexes/null_index.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_NULL_INDEX_HPP
|
||||
#define BOOST_INTERPROCESS_NULL_INDEX_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/offset_ptr.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a null index adaptor, so that if we don't want to construct
|
||||
//!named objects, we can use this null index type to save resources.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
//!Null index type
|
||||
//!used to save compilation time when
|
||||
//!named indexes are not needed.
|
||||
template <class MapConfig>
|
||||
class null_index
|
||||
{
|
||||
/// @cond
|
||||
typedef typename MapConfig::
|
||||
segment_manager_base segment_manager_base;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
typedef void * iterator;
|
||||
typedef const void * const_iterator;
|
||||
|
||||
//!begin() is equal
|
||||
//!to end()
|
||||
const_iterator begin() const
|
||||
{ return const_iterator(0); }
|
||||
|
||||
//!begin() is equal
|
||||
//!to end()
|
||||
iterator begin()
|
||||
{ return iterator(0); }
|
||||
|
||||
//!begin() is equal
|
||||
//!to end()
|
||||
const_iterator end() const
|
||||
{ return const_iterator(0); }
|
||||
|
||||
//!begin() is equal
|
||||
//!to end()
|
||||
iterator end()
|
||||
{ return iterator(0); }
|
||||
|
||||
//!Empty constructor
|
||||
null_index(segment_manager_base *){}
|
||||
};
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP
|
||||
@@ -0,0 +1,113 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_UNORDERED_MAP_INDEX_HPP
|
||||
#define BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/allocators/private_adaptive_pool.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes index adaptor of boost::unordered_map 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 unordered_map_index_aux
|
||||
{
|
||||
typedef typename MapConfig::key_type key_type;
|
||||
typedef typename MapConfig::mapped_type mapped_type;
|
||||
typedef std::equal_to<key_type> key_equal;
|
||||
typedef std::pair<const key_type, mapped_type> value_type;
|
||||
typedef private_adaptive_pool
|
||||
<value_type,
|
||||
typename MapConfig::
|
||||
segment_manager_base> allocator_type;
|
||||
struct hasher
|
||||
: std::unary_function<key_type, std::size_t>
|
||||
{
|
||||
std::size_t operator()(const key_type &val) const
|
||||
{
|
||||
typedef typename key_type::char_type char_type;
|
||||
const char_type *beg = detail::get_pointer(val.mp_str),
|
||||
*end = beg + val.m_len;
|
||||
return boost::hash_range(beg, end);
|
||||
}
|
||||
};
|
||||
typedef unordered_map<key_type, mapped_type, hasher,
|
||||
key_equal, allocator_type> index_t;
|
||||
};
|
||||
|
||||
///@endcond
|
||||
|
||||
//!Index type based in unordered_map. Just derives from unordered_map and
|
||||
//!defines the interface needed by managed memory segments
|
||||
template <class MapConfig>
|
||||
class unordered_map_index
|
||||
//Derive class from unordered_map specialization
|
||||
: public unordered_map_index_aux<MapConfig>::index_t
|
||||
{
|
||||
/// @cond
|
||||
typedef unordered_map_index_aux<MapConfig> index_aux;
|
||||
typedef typename index_aux::index_t base_type;
|
||||
typedef typename
|
||||
MapConfig::segment_manager_base segment_manager_base;
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor. Takes a pointer to the
|
||||
//!segment manager. Can throw
|
||||
unordered_map_index(segment_manager_base *segment_mngr)
|
||||
: base_type(0,
|
||||
typename index_aux::hasher(),
|
||||
typename index_aux::key_equal(),
|
||||
segment_mngr){}
|
||||
|
||||
//!This reserves memory to optimize the insertion of n
|
||||
//!elements in the index
|
||||
void reserve(std::size_t n)
|
||||
{ base_type::rehash(n); }
|
||||
|
||||
//!This tries to free previously allocate
|
||||
//!unused memory.
|
||||
void shrink_to_fit()
|
||||
{ base_type::rehash(base_type::size()); }
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
//!Trait class to detect if an index is a node
|
||||
//!index. This allows more efficient operations
|
||||
//!when deallocating named objects.
|
||||
template<class MapConfig>
|
||||
struct is_node_index
|
||||
<boost::interprocess::unordered_map_index<MapConfig> >
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP
|
||||
415
libraries/include/boost/interprocess/interprocess_fwd.hpp
Normal file
415
libraries/include/boost/interprocess/interprocess_fwd.hpp
Normal file
@@ -0,0 +1,415 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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;
|
||||
}}
|
||||
|
||||
namespace std {
|
||||
|
||||
template <class T>
|
||||
class allocator;
|
||||
|
||||
template <class T>
|
||||
struct less;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair;
|
||||
|
||||
template <class CharType>
|
||||
struct char_traits;
|
||||
|
||||
} //namespace std {
|
||||
|
||||
/// @endcond
|
||||
|
||||
namespace boost { namespace interprocess {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// shared_memory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class shared_memory_object;
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
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)
|
||||
|
||||
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;
|
||||
|
||||
#else
|
||||
|
||||
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_WINDOWS)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class message_queue;
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// CONTAINERS
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_FWD_HPP
|
||||
637
libraries/include/boost/interprocess/ipc/message_queue.hpp
Normal file
637
libraries/include/boost/interprocess/ipc/message_queue.hpp
Normal file
@@ -0,0 +1,637 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2008. 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_MESSAGE_QUEUE_HPP
|
||||
#define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/offset_ptr.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
|
||||
#include <algorithm> //std::lower_bound
|
||||
#include <cstddef> //std::size_t
|
||||
#include <cstring> //memcpy
|
||||
|
||||
|
||||
//!\file
|
||||
//!Describes an inter-process message queue. This class allows sending
|
||||
//!messages between processes and allows blocking, non-blocking and timed
|
||||
//!sending and receiving.
|
||||
|
||||
namespace boost{ namespace interprocess{
|
||||
|
||||
//!A class that allows sending messages
|
||||
//!between processes.
|
||||
class message_queue
|
||||
{
|
||||
/// @cond
|
||||
//Blocking modes
|
||||
enum block_t { blocking, timed, non_blocking };
|
||||
|
||||
message_queue();
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
//!Creates a process shared message queue with name "name". For this message queue,
|
||||
//!the maximum number of messages will be "max_num_msg" and the maximum message size
|
||||
//!will be "max_msg_size". Throws on error and if the queue was previously created.
|
||||
message_queue(create_only_t create_only,
|
||||
const char *name,
|
||||
std::size_t max_num_msg,
|
||||
std::size_t max_msg_size);
|
||||
|
||||
//!Opens or creates a process shared message queue with name "name".
|
||||
//!If the queue is created, the maximum number of messages will be "max_num_msg"
|
||||
//!and the maximum message size will be "max_msg_size". If queue was previously
|
||||
//!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters
|
||||
//!are ignored. Throws on error.
|
||||
message_queue(open_or_create_t open_or_create,
|
||||
const char *name,
|
||||
std::size_t max_num_msg,
|
||||
std::size_t max_msg_size);
|
||||
|
||||
//!Opens a previously created process shared message queue with name "name".
|
||||
//!If the was not previously created or there are no free resources,
|
||||
//!throws an error.
|
||||
message_queue(open_only_t open_only,
|
||||
const char *name);
|
||||
|
||||
//!Destroys *this and indicates that the calling process is finished using
|
||||
//!the resource. All opened message queues 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 message queue from the system
|
||||
//!use remove().
|
||||
~message_queue();
|
||||
|
||||
//!Sends a message stored in buffer "buffer" with size "buffer_size" in the
|
||||
//!message queue with priority "priority". If the message queue is full
|
||||
//!the sender is blocked. Throws interprocess_error on error.*/
|
||||
void send (const void *buffer, std::size_t buffer_size,
|
||||
unsigned int priority);
|
||||
|
||||
//!Sends a message stored in buffer "buffer" with size "buffer_size" through the
|
||||
//!message queue with priority "priority". If the message queue is full
|
||||
//!the sender is not blocked and returns false, otherwise returns true.
|
||||
//!Throws interprocess_error on error.
|
||||
bool try_send (const void *buffer, std::size_t buffer_size,
|
||||
unsigned int priority);
|
||||
|
||||
//!Sends a message stored in buffer "buffer" with size "buffer_size" in the
|
||||
//!message queue with priority "priority". If the message queue is full
|
||||
//!the sender retries until time "abs_time" is reached. Returns true if
|
||||
//!the message has been successfully sent. Returns false if timeout is reached.
|
||||
//!Throws interprocess_error on error.
|
||||
bool timed_send (const void *buffer, std::size_t buffer_size,
|
||||
unsigned int priority, const boost::posix_time::ptime& abs_time);
|
||||
|
||||
//!Receives a message from the message queue. The message is stored in buffer
|
||||
//!"buffer", which has size "buffer_size". The received message has size
|
||||
//!"recvd_size" and priority "priority". If the message queue is empty
|
||||
//!the receiver is blocked. Throws interprocess_error on error.
|
||||
void receive (void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size,unsigned int &priority);
|
||||
|
||||
//!Receives a message from the message queue. The message is stored in buffer
|
||||
//!"buffer", which has size "buffer_size". The received message has size
|
||||
//!"recvd_size" and priority "priority". If the message queue is empty
|
||||
//!the receiver is not blocked and returns false, otherwise returns true.
|
||||
//!Throws interprocess_error on error.
|
||||
bool try_receive (void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size,unsigned int &priority);
|
||||
|
||||
//!Receives a message from the message queue. The message is stored in buffer
|
||||
//!"buffer", which has size "buffer_size". The received message has size
|
||||
//!"recvd_size" and priority "priority". If the message queue is empty
|
||||
//!the receiver retries until time "abs_time" is reached. Returns true if
|
||||
//!the message has been successfully sent. Returns false if timeout is reached.
|
||||
//!Throws interprocess_error on error.
|
||||
bool timed_receive (void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size,unsigned int &priority,
|
||||
const boost::posix_time::ptime &abs_time);
|
||||
|
||||
//!Returns the maximum number of messages allowed by the queue. The message
|
||||
//!queue must be opened or created previously. Otherwise, returns 0.
|
||||
//!Never throws
|
||||
std::size_t get_max_msg() const;
|
||||
|
||||
//!Returns the maximum size of message allowed by the queue. The message
|
||||
//!queue must be opened or created previously. Otherwise, returns 0.
|
||||
//!Never throws
|
||||
std::size_t get_max_msg_size() const;
|
||||
|
||||
//!Returns the number of messages currently stored.
|
||||
//!Never throws
|
||||
std::size_t get_num_msg();
|
||||
|
||||
//!Removes the message queue from the system.
|
||||
//!Returns false on error. Never throws
|
||||
static bool remove(const char *name);
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef boost::posix_time::ptime ptime;
|
||||
bool do_receive(block_t block,
|
||||
void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size, unsigned int &priority,
|
||||
const ptime &abs_time);
|
||||
|
||||
bool do_send(block_t block,
|
||||
const void *buffer, std::size_t buffer_size,
|
||||
unsigned int priority, const ptime &abs_time);
|
||||
|
||||
//!Returns the needed memory size for the shared message queue.
|
||||
//!Never throws
|
||||
static std::size_t get_mem_size(std::size_t max_msg_size, std::size_t max_num_msg);
|
||||
|
||||
detail::managed_open_or_create_impl<shared_memory_object> m_shmem;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace detail {
|
||||
|
||||
//!This header is the prefix of each message in the queue
|
||||
class msg_hdr_t
|
||||
{
|
||||
public:
|
||||
std::size_t len; // Message length
|
||||
unsigned int priority;// Message priority
|
||||
//!Returns the data buffer associated with this this message
|
||||
void * data(){ return this+1; } //
|
||||
};
|
||||
|
||||
//!This functor is the predicate to order stored messages by priority
|
||||
class priority_functor
|
||||
{
|
||||
public:
|
||||
bool operator()(const offset_ptr<msg_hdr_t> &msg1,
|
||||
const offset_ptr<msg_hdr_t> &msg2) const
|
||||
{ return msg1->priority < msg2->priority; }
|
||||
};
|
||||
|
||||
//!This header is placed in the beginning of the shared memory and contains
|
||||
//!the data to control the queue. This class initializes the shared memory
|
||||
//!in the following way: in ascending memory address with proper alignment
|
||||
//!fillings:
|
||||
//!
|
||||
//!-> mq_hdr_t:
|
||||
//! Main control block that controls the rest of the elements
|
||||
//!
|
||||
//!-> offset_ptr<msg_hdr_t> index [max_num_msg]
|
||||
//! An array of pointers with size "max_num_msg" called index. Each pointer
|
||||
//! points to a preallocated message. The elements of this array are
|
||||
//! reordered in runtime in the following way:
|
||||
//!
|
||||
//! When the current number of messages is "cur_num_msg", the first
|
||||
//! "cur_num_msg" pointers point to inserted messages and the rest
|
||||
//! point to free messages. The first "cur_num_msg" pointers are
|
||||
//! ordered by the priority of the pointed message and by insertion order
|
||||
//! if two messages have the same priority. So the next message to be
|
||||
//! used in a "receive" is pointed by index [cur_num_msg-1] and the first free
|
||||
//! message ready to be used in a "send" operation is index [cur_num_msg].
|
||||
//! This transforms index in a fixed size priority queue with an embedded free
|
||||
//! message queue.
|
||||
//!
|
||||
//!-> struct message_t
|
||||
//! {
|
||||
//! msg_hdr_t header;
|
||||
//! char[max_msg_size] data;
|
||||
//! } messages [max_num_msg];
|
||||
//!
|
||||
//! An array of buffers of preallocated messages, each one prefixed with the
|
||||
//! msg_hdr_t structure. Each of this message is pointed by one pointer of
|
||||
//! the index structure.
|
||||
class mq_hdr_t
|
||||
: public detail::priority_functor
|
||||
{
|
||||
typedef offset_ptr<msg_hdr_t> msg_hdr_ptr_t;
|
||||
public:
|
||||
//!Constructor. This object must be constructed in the beginning of the
|
||||
//!shared memory of the size returned by the function "get_mem_size".
|
||||
//!This constructor initializes the needed resources and creates
|
||||
//!the internal structures like the priority index. This can throw.*/
|
||||
mq_hdr_t(std::size_t max_num_msg, std::size_t max_msg_size)
|
||||
: m_max_num_msg(max_num_msg),
|
||||
m_max_msg_size(max_msg_size),
|
||||
m_cur_num_msg(0)
|
||||
{ this->initialize_memory(); }
|
||||
|
||||
//!Returns the inserted message with top priority
|
||||
msg_hdr_t * top_msg()
|
||||
{ return mp_index[m_cur_num_msg-1].get(); }
|
||||
|
||||
//!Returns true if the message queue is full
|
||||
bool is_full() const
|
||||
{ return m_cur_num_msg == m_max_num_msg; }
|
||||
|
||||
//!Returns true if the message queue is empty
|
||||
bool is_empty() const
|
||||
{ return !m_cur_num_msg; }
|
||||
|
||||
//!Frees the top priority message and saves it in the free message list
|
||||
void free_top_msg()
|
||||
{ --m_cur_num_msg; }
|
||||
|
||||
//!Returns the first free msg of the free message queue
|
||||
msg_hdr_t * free_msg()
|
||||
{ return mp_index[m_cur_num_msg].get(); }
|
||||
|
||||
//!Inserts the first free message in the priority queue
|
||||
void queue_free_msg()
|
||||
{
|
||||
//Get free msg
|
||||
msg_hdr_ptr_t free = mp_index[m_cur_num_msg];
|
||||
//Get priority queue's range
|
||||
msg_hdr_ptr_t *it = &mp_index[0], *it_end = &mp_index[m_cur_num_msg];
|
||||
//Check where the free message should be placed
|
||||
it = std::lower_bound(it, it_end, free, static_cast<priority_functor&>(*this));
|
||||
//Make room in that position
|
||||
std::copy_backward(it, it_end, it_end+1);
|
||||
//Insert the free message in the correct position
|
||||
*it = free;
|
||||
++m_cur_num_msg;
|
||||
}
|
||||
|
||||
//!Returns the number of bytes needed to construct a message queue with
|
||||
//!"max_num_size" maximum number of messages and "max_msg_size" maximum
|
||||
//!message size. Never throws.
|
||||
static std::size_t get_mem_size
|
||||
(std::size_t max_msg_size, std::size_t max_num_msg)
|
||||
{
|
||||
const std::size_t
|
||||
msg_hdr_align = detail::alignment_of<detail::msg_hdr_t>::value,
|
||||
index_align = detail::alignment_of<msg_hdr_ptr_t>::value,
|
||||
r_hdr_size = detail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
|
||||
r_index_size = detail::get_rounded_size(sizeof(msg_hdr_ptr_t)*max_num_msg, msg_hdr_align),
|
||||
r_max_msg_size = detail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(detail::msg_hdr_t);
|
||||
return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) +
|
||||
detail::managed_open_or_create_impl<shared_memory_object>::ManagedOpenOrCreateUserOffset;
|
||||
}
|
||||
|
||||
//!Initializes the memory structures to preallocate messages and constructs the
|
||||
//!message index. Never throws.
|
||||
void initialize_memory()
|
||||
{
|
||||
const std::size_t
|
||||
msg_hdr_align = detail::alignment_of<detail::msg_hdr_t>::value,
|
||||
index_align = detail::alignment_of<msg_hdr_ptr_t>::value,
|
||||
r_hdr_size = detail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
|
||||
r_index_size = detail::get_rounded_size(sizeof(msg_hdr_ptr_t)*m_max_num_msg, msg_hdr_align),
|
||||
r_max_msg_size = detail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(detail::msg_hdr_t);
|
||||
|
||||
//Pointer to the index
|
||||
msg_hdr_ptr_t *index = reinterpret_cast<msg_hdr_ptr_t*>
|
||||
(reinterpret_cast<char*>(this)+r_hdr_size);
|
||||
|
||||
//Pointer to the first message header
|
||||
detail::msg_hdr_t *msg_hdr = reinterpret_cast<detail::msg_hdr_t*>
|
||||
(reinterpret_cast<char*>(this)+r_hdr_size+r_index_size);
|
||||
|
||||
//Initialize the pointer to the index
|
||||
mp_index = index;
|
||||
|
||||
//Initialize the index so each slot points to a preallocated message
|
||||
for(std::size_t i = 0; i < m_max_num_msg; ++i){
|
||||
index[i] = msg_hdr;
|
||||
msg_hdr = reinterpret_cast<detail::msg_hdr_t*>
|
||||
(reinterpret_cast<char*>(msg_hdr)+r_max_msg_size);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
//Pointer to the index
|
||||
offset_ptr<msg_hdr_ptr_t> mp_index;
|
||||
//Maximum number of messages of the queue
|
||||
const std::size_t m_max_num_msg;
|
||||
//Maximum size of messages of the queue
|
||||
const std::size_t m_max_msg_size;
|
||||
//Current number of messages
|
||||
std::size_t m_cur_num_msg;
|
||||
//Mutex to protect data structures
|
||||
interprocess_mutex m_mutex;
|
||||
//Condition block receivers when there are no messages
|
||||
interprocess_condition m_cond_recv;
|
||||
//Condition block senders when the queue is full
|
||||
interprocess_condition m_cond_send;
|
||||
};
|
||||
|
||||
|
||||
//!This is the atomic functor to be executed when creating or opening
|
||||
//!shared memory. Never throws
|
||||
class initialization_func_t
|
||||
{
|
||||
public:
|
||||
initialization_func_t(std::size_t maxmsg = 0,
|
||||
std::size_t maxmsgsize = 0)
|
||||
: m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {}
|
||||
|
||||
bool operator()(void *address, std::size_t, bool created)
|
||||
{
|
||||
char *mptr;
|
||||
|
||||
if(created){
|
||||
mptr = reinterpret_cast<char*>(address);
|
||||
//Construct the message queue header at the beginning
|
||||
BOOST_TRY{
|
||||
new (mptr) mq_hdr_t(m_maxmsg, m_maxmsgsize);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
return false;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const std::size_t m_maxmsg;
|
||||
const std::size_t m_maxmsgsize;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
inline message_queue::~message_queue()
|
||||
{}
|
||||
|
||||
inline std::size_t message_queue::get_mem_size
|
||||
(std::size_t max_msg_size, std::size_t max_num_msg)
|
||||
{ return detail::mq_hdr_t::get_mem_size(max_msg_size, max_num_msg); }
|
||||
|
||||
inline message_queue::message_queue(create_only_t create_only,
|
||||
const char *name,
|
||||
std::size_t max_num_msg,
|
||||
std::size_t max_msg_size)
|
||||
//Create shared memory and execute functor atomically
|
||||
: m_shmem(create_only,
|
||||
name,
|
||||
get_mem_size(max_msg_size, max_num_msg),
|
||||
read_write,
|
||||
static_cast<void*>(0),
|
||||
//Prepare initialization functor
|
||||
detail::initialization_func_t (max_num_msg, max_msg_size))
|
||||
{}
|
||||
|
||||
inline message_queue::message_queue(open_or_create_t open_or_create,
|
||||
const char *name,
|
||||
std::size_t max_num_msg,
|
||||
std::size_t max_msg_size)
|
||||
//Create shared memory and execute functor atomically
|
||||
: m_shmem(open_or_create,
|
||||
name,
|
||||
get_mem_size(max_msg_size, max_num_msg),
|
||||
read_write,
|
||||
static_cast<void*>(0),
|
||||
//Prepare initialization functor
|
||||
detail::initialization_func_t (max_num_msg, max_msg_size))
|
||||
{}
|
||||
|
||||
inline message_queue::message_queue(open_only_t open_only,
|
||||
const char *name)
|
||||
//Create shared memory and execute functor atomically
|
||||
: m_shmem(open_only,
|
||||
name,
|
||||
read_write,
|
||||
static_cast<void*>(0),
|
||||
//Prepare initialization functor
|
||||
detail::initialization_func_t ())
|
||||
{}
|
||||
|
||||
inline void message_queue::send
|
||||
(const void *buffer, std::size_t buffer_size, unsigned int priority)
|
||||
{ this->do_send(blocking, buffer, buffer_size, priority, ptime()); }
|
||||
|
||||
inline bool message_queue::try_send
|
||||
(const void *buffer, std::size_t buffer_size, unsigned int priority)
|
||||
{ return this->do_send(non_blocking, buffer, buffer_size, priority, ptime()); }
|
||||
|
||||
inline bool message_queue::timed_send
|
||||
(const void *buffer, std::size_t buffer_size
|
||||
,unsigned int priority, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->send(buffer, buffer_size, priority);
|
||||
return true;
|
||||
}
|
||||
return this->do_send(timed, buffer, buffer_size, priority, abs_time);
|
||||
}
|
||||
|
||||
inline bool message_queue::do_send(block_t block,
|
||||
const void *buffer, std::size_t buffer_size,
|
||||
unsigned int priority, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
|
||||
//Check if buffer is smaller than maximum allowed
|
||||
if (buffer_size > p_hdr->m_max_msg_size) {
|
||||
throw interprocess_exception(size_error);
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
|
||||
//---------------------------------------------
|
||||
{
|
||||
//If the queue is full execute blocking logic
|
||||
if (p_hdr->is_full()) {
|
||||
|
||||
switch(block){
|
||||
case non_blocking :
|
||||
return false;
|
||||
break;
|
||||
|
||||
case blocking :
|
||||
do{
|
||||
p_hdr->m_cond_send.wait(lock);
|
||||
}
|
||||
while (p_hdr->is_full());
|
||||
break;
|
||||
|
||||
case timed :
|
||||
do{
|
||||
if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){
|
||||
if(p_hdr->is_full())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (p_hdr->is_full());
|
||||
break;
|
||||
default:
|
||||
throw interprocess_exception();
|
||||
}
|
||||
}
|
||||
|
||||
//Get the first free message from free message queue
|
||||
detail::msg_hdr_t *free_msg = p_hdr->free_msg();
|
||||
if (free_msg == 0) {
|
||||
throw interprocess_exception();
|
||||
}
|
||||
|
||||
//Copy control data to the free message
|
||||
free_msg->priority = priority;
|
||||
free_msg->len = buffer_size;
|
||||
|
||||
//Copy user buffer to the message
|
||||
std::memcpy(free_msg->data(), buffer, buffer_size);
|
||||
|
||||
// bool was_empty = p_hdr->is_empty();
|
||||
//Insert the first free message in the priority queue
|
||||
p_hdr->queue_free_msg();
|
||||
|
||||
//If this message changes the queue empty state, notify it to receivers
|
||||
// if (was_empty){
|
||||
p_hdr->m_cond_recv.notify_one();
|
||||
// }
|
||||
} // Lock end
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void message_queue::receive(void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size, unsigned int &priority)
|
||||
{ this->do_receive(blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
|
||||
|
||||
inline bool
|
||||
message_queue::try_receive(void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size, unsigned int &priority)
|
||||
{ return this->do_receive(non_blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
|
||||
|
||||
inline bool
|
||||
message_queue::timed_receive(void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size, unsigned int &priority,
|
||||
const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->receive(buffer, buffer_size, recvd_size, priority);
|
||||
return true;
|
||||
}
|
||||
return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time);
|
||||
}
|
||||
|
||||
inline bool
|
||||
message_queue::do_receive(block_t block,
|
||||
void *buffer, std::size_t buffer_size,
|
||||
std::size_t &recvd_size, unsigned int &priority,
|
||||
const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
|
||||
//Check if buffer is big enough for any message
|
||||
if (buffer_size < p_hdr->m_max_msg_size) {
|
||||
throw interprocess_exception(size_error);
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
|
||||
//---------------------------------------------
|
||||
{
|
||||
//If there are no messages execute blocking logic
|
||||
if (p_hdr->is_empty()) {
|
||||
switch(block){
|
||||
case non_blocking :
|
||||
return false;
|
||||
break;
|
||||
|
||||
case blocking :
|
||||
do{
|
||||
p_hdr->m_cond_recv.wait(lock);
|
||||
}
|
||||
while (p_hdr->is_empty());
|
||||
break;
|
||||
|
||||
case timed :
|
||||
do{
|
||||
if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){
|
||||
if(p_hdr->is_empty())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (p_hdr->is_empty());
|
||||
break;
|
||||
|
||||
//Paranoia check
|
||||
default:
|
||||
throw interprocess_exception();
|
||||
}
|
||||
}
|
||||
|
||||
//Thre is at least message ready to pick, get the top one
|
||||
detail::msg_hdr_t *top_msg = p_hdr->top_msg();
|
||||
|
||||
//Paranoia check
|
||||
if (top_msg == 0) {
|
||||
throw interprocess_exception();
|
||||
}
|
||||
|
||||
//Get data from the message
|
||||
recvd_size = top_msg->len;
|
||||
priority = top_msg->priority;
|
||||
|
||||
//Copy data to receiver's bufers
|
||||
std::memcpy(buffer, top_msg->data(), recvd_size);
|
||||
|
||||
// bool was_full = p_hdr->is_full();
|
||||
|
||||
//Free top message and put it in the free message list
|
||||
p_hdr->free_top_msg();
|
||||
|
||||
//If this reception changes the queue full state, notify senders
|
||||
// if (was_full){
|
||||
p_hdr->m_cond_send.notify_one();
|
||||
// }
|
||||
} //Lock end
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::size_t message_queue::get_max_msg() const
|
||||
{
|
||||
detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
|
||||
return p_hdr ? p_hdr->m_max_num_msg : 0; }
|
||||
|
||||
inline std::size_t message_queue::get_max_msg_size() const
|
||||
{
|
||||
detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
|
||||
return p_hdr ? p_hdr->m_max_msg_size : 0;
|
||||
}
|
||||
|
||||
inline std::size_t message_queue::get_num_msg()
|
||||
{
|
||||
detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
|
||||
if(p_hdr){
|
||||
//---------------------------------------------
|
||||
scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
|
||||
//---------------------------------------------
|
||||
return p_hdr->m_cur_num_msg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool message_queue::remove(const char *name)
|
||||
{ return shared_memory_object::remove(name); }
|
||||
|
||||
/// @endcond
|
||||
|
||||
}} //namespace boost{ namespace interprocess{
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user