no message

[SVN r37976]
This commit is contained in:
Ion Gaztañaga
2007-06-12 17:13:44 +00:00
parent 38773b309d
commit a678891c93
97 changed files with 4619 additions and 3921 deletions

View File

@@ -36,7 +36,7 @@ doxygen interprocess_doxygen
xml interprocess_xml : interprocess.qbk ;
boostbook standalone
boostbook interprocess
:
interprocess_xml
interprocess_doxygen

View File

@@ -29,7 +29,7 @@ and synchronization mechanisms and offers a wide range of them:
[*Boost.Interprocess] also offers higher-level interprocess mechanisms to allocate
dynamically portions of a shared memory or a memory mapped file (in general,
to allocate portions of a fixed size memory segment). Using these mechanisms,
[*Boost.Interprocess] offers the tools to construct C++ objects, including
[*Boost.Interprocess] offers useful tools to construct C++ objects, including
STL-like containers, in shared memory and memory mapped files:
* Dynamic creation of anonymous and named objects in a shared memory or memory
@@ -38,6 +38,29 @@ STL-like containers, in shared memory and memory mapped files:
* STL-like allocators ready for shared memory/memory-mapped files implementing
several memory allocation patterns (like pooling).
[section:introduction_building_interprocess Building Boost.Interprocess]
There is no need to compile anything to use [*Boost.Interprocess], since it's
a header only library. Just include your Boost header directory in your
compiler include path.
[endsect]
[section:tested_compilers Tested compilers]
[*Boost.Interprocess] has been tested in the following compilers/platforms:
* Visual 7.1/WinXP
* Visual 8.0/WinXP
* GCC 4.1.1/MinGW
* GCC 3.4.4/Cygwin
* Intel 9.1/WinXP
* GCC 4.1.2/Linux
* Codewarrior 9.4/WinXP
* GCC 3.4.3 Solaris 11
[endsect]
[endsect]
[section:quick_guide Quick Guide for the Impatient]
@@ -117,14 +140,10 @@ STL algorithms:
[section:qg_interprocess_map Creating maps in shared memory]
Just like a vector, [*Boost.Interprocess] allows creating maps in shared memory and memory
mapped files. [*Boost.Interprocess]'s map is
The construction of map is a bit tricky, because
For example, we can construct STL-like containers in shared memory.
To do this, we just need to create a an special (managed) shared memory segment,
declare a [*Boost.Interprocess] allocator and construct the vector in shared memory
just if it was any other object. Just execute this first process:
Just like a vector, [*Boost.Interprocess] allows creating maps in
shared memory and memory mapped files. The only difference is that
like standard associative containers, [*Boost.Interprocess]'s map needs
also the comparison functor when an allocator is passed in the constructor:
[import ../example/doc_map.cpp]
[doc_map]
@@ -962,11 +981,11 @@ opening or opening or creation of the underlying resource:
NamedUtility(create_only, ...)
//Open the synchronization utility. If it does not previously
//exist, throws an error.
//exist, it's created.
NamedUtility(open_or_create, ...)
//Open the synchronization utility. If it does not previously
//exist, create it.
//exist, throws an error.
NamedUtility(open_only, ...)
On the other hand the anonymous synchronization utility can only
@@ -1083,7 +1102,7 @@ Boost.Interprocess offers the following mutex types:
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
* [classref boost::interprocess::interprocess_mutex]: A recursive,
* [classref boost::interprocess::interprocess_recursive_mutex]: A recursive,
anonymous mutex that can be placed in shared memory or memory mapped files.
[c++]
@@ -3422,6 +3441,95 @@ memory segment using `get_segment_manager` member:
[endsect]
[section:managed_memory_segment_additional_features Additional functions]
Managed memory segments offer additional functions:
Obtain the size of the memory segment:
[c++]
managed_shm.get_size();
Obtain the number of free bytes of the segment:
[c++]
managed_shm.get_free_memory();
Clear to zero the free memory:
[c++]
managed_shm.zero_free_memory();
Returns true if all memory has been deallocated, false otherwise:
[c++]
managed_shm.all_memory_deallocated();
Tests internal structures of the managed segment and returns true
if no errors are detected:
[c++]
managed_shm.check_sanity();
Reserves memory to make the subsequent allocation of named or unique objects more
efficient. This function is only useful for pseudo-intrusive or non-node indexes (like
`flat_map_index`, `iunordered_set_index`). This function has no effect with the
default index (`iset_index`) or other indexes (`map_index`):
[c++]
managed_shm.reserve_named_objects(1000);
managed_shm.reserve_unique_objects(1000);
Returns the number of named and unique objects allocated in the segment:
[c++]
managed_shm.get_num_named_objects();
managed_shm.get_num_unique_objects();
Returns constant iterators to the range of named and unique objects stored in the
managed segment. [*Caution:] These functions are for debugging purposes
and they are [*not] thread-safe. If any other process creates or destroys
named/unique objects while a process iterates the named/unique objects the
results are undefined. Iterators are invalidated after each named/unique object
creation/erasure:
[c++]
typedef managed_shared_memory::const_named_iterator const_named_it;
const_named_it named_beg = managed_shm.named_begin();
const_named_it named_end = managed_shm.named_end();
typedef managed_shared_memory::const_unique_iterator const_unique_it;
const_unique_it unique_beg = managed_shm.unique_begin();
const_unique_it unique_end = managed_shm.unique_end();
for(; named_beg != named_end; ++named_beg){
//A pointer to the name of the named object
const managed_shared_memory::char_type *name = named_beg->name();
//The length of the name
std::size_t name_len = named_beg->name_length();
//A constant void pointer to the named object
const void *value = named_beg->value();
}
for(; unique_beg != unique_end; ++unique_beg){
//The typeid(T).name() of the unique object
const char *typeid_name = unique_beg->name();
//The length of the name
std::size_t name_len = unique_beg->name_length();
//A constant void pointer to the unique object
const void *value = unique_beg->value();
}
[endsect]
[endsect]
[section:allocator_introduction Introduction to Interprocess allocators]
@@ -5462,40 +5570,6 @@ pointer family as `segment_manager::void_pointer` typedef. This means that if `s
reason for this is that allocators are members of containers, and if we want to put
the container in a managed memory segment, the allocator should be ready for that.
If the user wants to optimize further allocator usage in [*Boost.Interprocess] node
containers, he can change the common allocator::construct function from:
[c++]
void construct(pointer ptr, const value_type &value);
to this one:
[c++]
template<class Convertible>
void construct(pointer ptr, const Convertible &value)
and define a specialization of `boost::interprocess::has_convertible_construct<...>`
defined in `<boost/interprocess/detail/utilities.hpp>` file:
[c++]
namespace boost{ namespace interprocess{
template<class T, class SegmentManager>
struct has_convertible_construct
<my_allocator<T, SegmentManager> >
{
enum { value = true };
};
}} //namespace boost{ namespace interprocess{
Using this optimization, [*Boost.Interprocess] node containers will just store one allocator instance
instead of 2, because nodes could be constructed from the value type directly.
[*Boost.Interprocess] STL-like allocators implement this optimization.
[endsect]
[section:custom_indexes Building custom indexes]
@@ -5863,7 +5937,7 @@ thank them:
* Thanks to [*Francis Andre] and [*Anders Hybertz] for their ideas and suggestions.
Many of them are not implemented yet but I hope to include them when library gets some stability.
* Thanks to [*Steve LoBasso], [*Glenn Schrader], [*Hiang Swee Chiang],
* Thanks to [*Matt Doyle], [*Steve LoBasso], [*Glenn Schrader], [*Hiang Swee Chiang],
[*Phil Endecott], [*Rene Rivera],
[*Harold Pirtle], [*Paul Ryan],
[*Shumin Wu], [*Michal Wozniak], [*Peter Johnson],
@@ -5935,6 +6009,20 @@ limitations under the License.
[section:changes Changes...]
[section:changes_interprocess_2007_06_11 Changes in Interprocess 2007-06-11...]
* Added iteration of named and unique objects in a segment manager.
* Fixed leak in [classref boost::interprocess::vector vector].
* Added support for Solaris.
* Optimized [classref boost::interprocess::segment_manager] to avoid
code bloat associated with templated instantiations.
* Removed the use of allocator::construct/destroy from containers.
* Correction of typos and documentation errors.
* Fixed bug for UNIX: No slash ('/') was being added as the first character
for shared memory names, leading to errors in some UNIX systems.
[endsect]
[section:changes_interprocess_2007_05_03 Changes in Interprocess 2007-05-03...]
* Fixed bug in VC-8.0: Broken function inlining in core offset_ptr functions.

View File

@@ -22,6 +22,7 @@ rule test_all
for local fileb in [ glob *.cpp ]
{
all_rules += [ link $(fileb) /boost/thread//boost_thread
# all_rules += [ compile $(fileb)
: # additional args
: # test-files
: # requirements

View File

@@ -11,6 +11,7 @@
#include <boost/interprocess/detail/workaround.hpp>
//[doc_cont
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
int main ()

View File

@@ -34,7 +34,7 @@ int main ()
//so the allocator must allocate that pair.
typedef int KeyType;
typedef float MappedType;
typedef std::pair<int, float> ValueType;
typedef std::pair<const int, float> ValueType;
//Alias an STL compatible allocator of for the map.
//This allocator will allow to place containers
@@ -61,7 +61,7 @@ int main ()
//Insert data in the map
for(int i = 0; i < 100; ++i){
mymap->insert(std::pair<int, float>(i, (float)i));
mymap->insert(std::pair<const int, float>(i, (float)i));
}
}
catch(...){

View File

@@ -56,6 +56,8 @@ int main ()
for(int i = 0; i < 2; ++i){
//Create an object in shared memory
my_class * my_object = shmem.construct<my_class>("my_object")();
my_class * my_object2 = shmem.construct<my_class>(anonymous_instance)();
shmem.destroy_ptr(my_object2);
//Since the next shared memory allocation can throw
//assign it to a scoped_ptr so that if an exception occurs

View File

@@ -12,6 +12,7 @@
//[doc_vectorstream
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/streams/vectorstream.hpp>
#include <iterator>

View File

@@ -301,18 +301,6 @@ bool operator!=(const adaptive_pool<T, S, NodesPerChunk, F> &alloc1,
{ return alloc1.get_node_pool() != alloc2.get_node_pool(); }
/// @cond
/*!This specialization indicates that the construct function allows
convertible types to construct the value type. This allows
storing less allocator instances in containers.*/
template<class T, class S, std::size_t NodesPerChunk, std::size_t F>
struct has_convertible_construct
<boost::interprocess::adaptive_pool<T, S, NodesPerChunk, F> >
{
enum { value = true };
};
/// @endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -26,7 +26,7 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <memory>
#include <algorithm>
#include <cstddef>
@@ -140,21 +140,6 @@ class allocator
void deallocate(const pointer &ptr, size_type)
{ mp_mngr->deallocate(detail::get_pointer(ptr)); }
/*!Construct object, calling constructor.
Throws if T(const Convertible &) throws*/
template<class Convertible>
void construct(const pointer &ptr, const Convertible &value)
{ new(detail::get_pointer(ptr)) value_type(value); }
/*!Default construct an object.
Throws if T's default constructor throws*/
void construct(const pointer &ptr)
{ new(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(); }
/*!Returns the number of elements that could be allocated. Never throws*/
size_type max_size() const
{ return mp_mngr->get_size()/sizeof(value_type); }
@@ -229,21 +214,13 @@ bool operator!=(const allocator<T, SegmentManager> &alloc1,
const allocator<T, SegmentManager> &alloc2)
{ return alloc1.get_segment_manager() != alloc2.get_segment_manager(); }
/// @cond
/*!This specialization indicates that the construct function allows
convertible types to construct the value type. This allows
storing less allocator instances in containers.*/
template<class T, class SegmentManager>
struct has_convertible_construct
<boost::interprocess::allocator<T, SegmentManager> >
{
enum { value = true };
};
/// @endcond
} //namespace interprocess {
/// @cond
template<class T>
struct has_trivial_destructor;
template<class T, class SegmentManager>
struct has_trivial_destructor
<boost::interprocess::allocator <T, SegmentManager> >

View File

@@ -390,18 +390,6 @@ bool operator!=(const cached_adaptive_pool<T, S, NodesPerChunk, M> &alloc1,
const cached_adaptive_pool<T, S, NodesPerChunk, M> &alloc2)
{ return alloc1.get_node_pool() != alloc2.get_node_pool(); }
/// @cond
/*!This specialization indicates that the construct function allows
convertible types to construct the value type. This allows
storing less allocator instances in containers.*/
template<class T, class SegmentManager, std::size_t NodesPerChunk, std::size_t M>
struct has_convertible_construct
<boost::interprocess::cached_adaptive_pool<T, SegmentManager, NodesPerChunk, M> >
{
enum { value = true };
};
/// @endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -388,18 +388,6 @@ bool operator!=(const cached_node_allocator<T, S, NodesPerChunk> &alloc1,
const cached_node_allocator<T, S, NodesPerChunk> &alloc2)
{ return alloc1.get_node_pool() != alloc2.get_node_pool(); }
/// @cond
/*!This specialization indicates that the construct function allows
convertible types to construct the value type. This allows
storing less allocator instances in containers.*/
template<class T, class SegmentManager, std::size_t NodesPerChunk>
struct has_convertible_construct
<boost::interprocess::cached_node_allocator<T, SegmentManager, NodesPerChunk> >
{
enum { value = true };
};
/// @endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -273,7 +273,6 @@ class private_node_pool
//If there are no free nodes we allocate a new block
if (m_freelist.empty())
priv_alloc_chunk();
//We take the first free node
node_t *n = (node_t*)&m_freelist.front();
m_freelist.pop_front();
@@ -303,9 +302,8 @@ class private_node_pool
//We initialize all Nodes in Node Block to insert
//them in the free Node list
for(std::size_t i = 0; i < NumAlloc; ++i){
m_freelist.push_front(*(node_t*)pNode );
pNode += RealNodeSize;
for(std::size_t i = 0; i < NumAlloc; ++i, pNode += RealNodeSize){
m_freelist.push_front(*new (pNode) node_t);
}
}

View File

@@ -298,19 +298,6 @@ bool operator!=(const node_allocator<T, S, NodesPerChunk> &alloc1,
const node_allocator<T, S, NodesPerChunk> &alloc2)
{ return alloc1.get_node_pool() != alloc2.get_node_pool(); }
/// @cond
/*!This specialization indicates that the construct function allows
convertible types to construct the value type. This allows
storing less allocator instances in containers.*/
template<class T, class S, std::size_t NodesPerChunk>
struct has_convertible_construct
<boost::interprocess::node_allocator<T, S, NodesPerChunk> >
{
enum { value = true };
};
/// @endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -235,16 +235,6 @@ bool operator!=(const private_adaptive_pool<T, S, NodesPerChunk, F> &alloc1,
return &alloc1 != &alloc2;
}
/// @cond
//!This specialization indicates that the construct function allows
//!convertible types to construct the value type. This allows
//!storing less allocator instances in containers.
template<class T, class S, std::size_t NodesPerChunk, std::size_t F>
struct has_convertible_construct
<boost::interprocess::private_adaptive_pool<T, S, NodesPerChunk, F> >
{ enum { value = true }; };
/// @endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -236,18 +236,6 @@ bool operator!=(const private_node_allocator<T, S, NodesPerChunk> &alloc1,
return &alloc1 != &alloc2;
}
/// @cond
//!This specialization indicates that the construct function allows
//!convertible types to construct the value type. This allows
//!storing less allocator instances in containers.
template<class T, class S, std::size_t NodesPerChunk>
struct has_convertible_construct
<boost::interprocess::private_node_allocator<T, S, NodesPerChunk> >
{
enum { value = true };
};
/// @endcond
} //namespace interprocess {
} //namespace boost {

View File

@@ -52,6 +52,10 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/algorithms.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
@@ -64,7 +68,6 @@
#include <boost/interprocess/detail/move_iterator.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/allocator_utilities.hpp>
namespace boost {
@@ -84,10 +87,8 @@ inline std::size_t deque_buf_size(std::size_t size)
// exception safety easier.
template <class T, class Alloc>
class deque_base
: public boost::detail::allocator::
rebind_to<Alloc, T >::type,
public boost::detail::allocator::
rebind_to<Alloc, typename Alloc::pointer>::type
: public Alloc::template rebind<T>::other,
public Alloc::template rebind<typename Alloc::pointer>::other
{
public:
typedef typename Alloc::value_type val_alloc_val;
@@ -96,16 +97,15 @@ class deque_base
typedef typename Alloc::reference val_alloc_ref;
typedef typename Alloc::const_reference val_alloc_cref;
typedef typename Alloc::value_type val_alloc_diff;
typedef typename boost::detail::allocator::
rebind_to<Alloc, val_alloc_ptr>::type ptr_alloc;
typedef typename Alloc::template rebind
<typename Alloc::pointer>::other ptr_alloc;
typedef typename ptr_alloc::value_type ptr_alloc_val;
typedef typename ptr_alloc::pointer ptr_alloc_ptr;
typedef typename ptr_alloc::const_pointer ptr_alloc_cptr;
typedef typename ptr_alloc::reference ptr_alloc_ref;
typedef typename ptr_alloc::const_reference ptr_alloc_cref;
typedef typename boost::detail::allocator::
rebind_to<Alloc, T >::type allocator_type;
typedef typename Alloc::template
rebind<T>::other allocator_type;
allocator_type get_allocator() const
{ return *this; }
@@ -113,8 +113,8 @@ class deque_base
protected:
enum { trivial_dctr_after_move = boost::has_trivial_destructor<val_alloc_val>::value };
typedef typename boost::detail::allocator::
rebind_to<Alloc, typename Alloc::pointer>::type map_allocator_type;
typedef typename Alloc::template
rebind<typename Alloc::pointer>::other map_allocator_type;
val_alloc_ptr priv_allocate_node()
{ return this->allocator_type::allocate(deque_buf_size(sizeof(T))); }
@@ -372,6 +372,7 @@ class deque_base
: allocator_type(a), map_allocator_type(a),
m_map(0), m_map_size(0), m_start(), m_finish() {}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
deque_base(const detail::moved_object<deque_base> &md)
: allocator_type(md.get()), map_allocator_type(md.get()),
m_map(md.get().m_map), m_map_size(md.get().m_map_size),
@@ -382,6 +383,18 @@ class deque_base
m_start = iterator();
m_finish = iterator();
}
#else
deque_base(deque_base &&md)
: allocator_type(md), map_allocator_type(md),
m_map(md.m_map), m_map_size(md.m_map_size),
m_start(md.m_start), m_finish(md.m_finish)
{
m_map = 0;
m_map_size = 0;
m_start = iterator();
m_finish = iterator();
}
#endif
~deque_base()
{
@@ -464,8 +477,8 @@ class deque : protected deque_base<T, Alloc>
typedef typename Alloc::const_pointer val_alloc_cptr;
typedef typename Alloc::reference val_alloc_ref;
typedef typename Alloc::const_reference val_alloc_cref;
typedef typename boost::detail::allocator::
rebind_to<Alloc, val_alloc_ptr>::type ptr_alloc;
typedef typename Alloc::template
rebind<val_alloc_ptr>::other ptr_alloc;
typedef typename ptr_alloc::value_type ptr_alloc_val;
typedef typename ptr_alloc::pointer ptr_alloc_ptr;
typedef typename ptr_alloc::const_pointer ptr_alloc_cptr;
@@ -581,9 +594,15 @@ class deque : protected deque_base<T, Alloc>
deque(const deque& x) : Base(x.get_allocator(), x.size())
{ std::uninitialized_copy(x.begin(), x.end(), this->m_start); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
deque(const detail::moved_object<deque> &mx)
: Base(move((Base&)mx.get()))
{}
#else
deque(deque &&mx)
: Base(move((Base&)mx))
{}
#endif
deque(size_type n, const value_type& value,
const allocator_type& a = allocator_type()) : Base(a, n)
@@ -599,7 +618,7 @@ class deque : protected deque_base<T, Alloc>
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InpIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_initialize_dispatch(first, last, Result());
}
@@ -621,8 +640,13 @@ class deque : protected deque_base<T, Alloc>
return *this;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
deque& operator= (const detail::moved_object<deque> &mx)
{ this->clear(); this->swap(mx.get()); return *this; }
#else
deque& operator= (deque &&mx)
{ this->clear(); this->swap(mx); return *this; }
#endif
void swap(deque& x)
{
@@ -632,8 +656,13 @@ class deque : protected deque_base<T, Alloc>
std::swap(this->m_map_size, x.m_map_size);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<deque> &mx)
{ this->swap(mx.get()); }
#else
void swap(deque &&mx)
{ this->swap(mx); }
#endif
void assign(size_type n, const T& val) {
this->priv_fill_assign(n, val);
@@ -643,55 +672,79 @@ class deque : protected deque_base<T, Alloc>
void assign(InpIt first, InpIt last) {
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InpIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
}
void push_back(const value_type& t)
{
if (this->m_finish.m_cur != this->m_finish.m_last - 1) {
this->allocator_type::construct(this->m_finish.m_cur, t);
new(detail::get_pointer(this->m_finish.m_cur))value_type(t);
++this->m_finish.m_cur;
}
else
this->priv_push_back_aux(t);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_back(const detail::moved_object<value_type> &mt)
{
if (this->m_finish.m_cur != this->m_finish.m_last - 1) {
this->allocator_type::construct(this->m_finish.m_cur, mt);
new(detail::get_pointer(this->m_finish.m_cur))value_type(mt);
++this->m_finish.m_cur;
}
else
this->priv_push_back_aux(mt);
}
#else
void push_back(value_type &&mt)
{
if (this->m_finish.m_cur != this->m_finish.m_last - 1) {
new(detail::get_pointer(this->m_finish.m_cur))value_type(move(mt));
++this->m_finish.m_cur;
}
else
this->priv_push_back_aux(move(mt));
}
#endif
void push_front(const value_type& t)
{
if (this->m_start.m_cur != this->m_start.m_first) {
this->allocator_type::construct(this->m_start.m_cur - 1, t);
new(detail::get_pointer(this->m_start.m_cur)- 1)value_type(t);
--this->m_start.m_cur;
}
else
this->priv_push_front_aux(t);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_front(const detail::moved_object<value_type> &mt)
{
if (this->m_start.m_cur != this->m_start.m_first) {
this->allocator_type::construct(this->m_start.m_cur - 1, mt);
new(detail::get_pointer(this->m_start.m_cur)- 1)value_type(mt);
--this->m_start.m_cur;
}
else
this->priv_push_front_aux(mt);
}
#else
void push_front(value_type &&mt)
{
if (this->m_start.m_cur != this->m_start.m_first) {
new(detail::get_pointer(this->m_start.m_cur)- 1)value_type(move(mt));
--this->m_start.m_cur;
}
else
this->priv_push_front_aux(move(mt));
}
#endif
void pop_back()
{
if (this->m_finish.m_cur != this->m_finish.m_first) {
--this->m_finish.m_cur;
static_cast<allocator_type*>(this)->destroy(this->m_finish.m_cur);
detail::get_pointer(this->m_finish.m_cur)->~value_type();
}
else
this->priv_pop_back_aux();
@@ -700,7 +753,7 @@ class deque : protected deque_base<T, Alloc>
void pop_front()
{
if (this->m_start.m_cur != this->m_start.m_last - 1) {
static_cast<allocator_type*>(this)->destroy(this->m_start.m_cur);
detail::get_pointer(this->m_start.m_cur)->~value_type();
++this->m_start.m_cur;
}
else
@@ -724,6 +777,7 @@ class deque : protected deque_base<T, Alloc>
}
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<value_type> &mx)
{
if (position.m_cur == this->m_start.m_cur) {
@@ -740,6 +794,24 @@ class deque : protected deque_base<T, Alloc>
return this->priv_insert_aux(position, mx);
}
}
#else
iterator insert(iterator position, value_type &&mx)
{
if (position.m_cur == this->m_start.m_cur) {
this->push_front(move(mx));
return this->m_start;
}
else if (position.m_cur == this->m_finish.m_cur) {
this->push_back(move(mx));
iterator tmp = this->m_finish;
--tmp;
return tmp;
}
else {
return this->priv_insert_aux(position, move(mx));
}
}
#endif
void insert(iterator pos, size_type n, const value_type& x)
{ this->priv_fill_insert(pos, n, x); }
@@ -750,7 +822,7 @@ class deque : protected deque_base<T, Alloc>
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InpIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_insert_dispatch(pos, first, last, Result());
}
@@ -873,7 +945,7 @@ class deque : protected deque_base<T, Alloc>
if (pos.m_cur == this->m_start.m_cur) {
iterator new_start = this->priv_reserve_elements_at_front(n);
BOOST_TRY{
std::uninitialized_copy(first, last, new_start);
boost::interprocess::uninitialized_copy(first, last, new_start);
this->m_start = new_start;
}
BOOST_CATCH(...){
@@ -885,7 +957,7 @@ class deque : protected deque_base<T, Alloc>
else if (pos.m_cur == this->m_finish.m_cur) {
iterator new_finish = this->priv_reserve_elements_at_back(n);
BOOST_TRY{
std::uninitialized_copy(first, last, this->m_finish);
boost::interprocess::uninitialized_copy(first, last, this->m_finish);
this->m_finish = new_finish;
}
BOOST_CATCH(...){
@@ -914,31 +986,37 @@ class deque : protected deque_base<T, Alloc>
}
template <class Integer>
void priv_initialize_dispatch(Integer n, Integer x, boost::mpl::true_)
void priv_initialize_dispatch(Integer n, Integer x, true_)
{
this->priv_initialize_map(n);
this->priv_fill_initialize(x);
}
template <class InpIt>
void priv_initialize_dispatch(InpIt first, InpIt last, boost::mpl::false_)
void priv_initialize_dispatch(InpIt first, InpIt last, false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_range_initialize(first, last, ItCat());
}
void priv_destroy_range(iterator p, iterator p2)
{ for(;p != p2; ++p) static_cast<allocator_type*>(this)->destroy(&*p); }
{
for(;p != p2; ++p)
detail::get_pointer(&*p)->~value_type();
}
void priv_destroy_range(pointer p, pointer p2)
{ for(;p != p2; ++p) static_cast<allocator_type*>(this)->destroy(p); }
{
for(;p != p2; ++p)
detail::get_pointer(&*p)->~value_type();
}
template <class Integer>
void priv_assign_dispatch(Integer n, Integer val, boost::mpl::true_)
void priv_assign_dispatch(Integer n, Integer val, true_)
{ this->priv_fill_assign((size_type) n, (T) val); }
template <class InpIt>
void priv_assign_dispatch(InpIt first, InpIt last, boost::mpl::false_)
void priv_assign_dispatch(InpIt first, InpIt last, false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_assign_aux(first, last, ItCat());
@@ -973,7 +1051,7 @@ class deque : protected deque_base<T, Alloc>
template <class Integer>
void priv_insert_dispatch(iterator pos, Integer n, Integer x,
boost::mpl::true_)
true_)
{
this->priv_fill_insert(pos, (size_type) n, (value_type) x);
}
@@ -981,7 +1059,7 @@ class deque : protected deque_base<T, Alloc>
template <class InpIt>
void priv_insert_dispatch(iterator pos,
InpIt first, InpIt last,
boost::mpl::false_)
false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->insert(pos, first, last, ItCat());
@@ -994,6 +1072,7 @@ class deque : protected deque_base<T, Alloc>
return iterator(this->begin() + n);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator priv_insert_aux(iterator pos, const detail::moved_object<value_type> &mx)
{
typedef repeat_iterator<T, difference_type> r_iterator;
@@ -1005,6 +1084,19 @@ class deque : protected deque_base<T, Alloc>
,move_it(r_iterator()));
return iterator(this->begin() + n);
}
#else
iterator priv_insert_aux(iterator pos, value_type &&mx)
{
typedef repeat_iterator<T, difference_type> r_iterator;
typedef detail::move_iterator<r_iterator> move_it;
//Just call more general insert(pos, size, value) and return iterator
size_type n = pos - begin();
this->insert(pos
,move_it(r_iterator(mx, 1))
,move_it(r_iterator()));
return iterator(this->begin() + n);
}
#endif
void priv_insert_aux(iterator pos, size_type n, const value_type& x)
{
@@ -1024,7 +1116,7 @@ class deque : protected deque_base<T, Alloc>
BOOST_TRY {
if (elemsbefore >= difference_type(n)) {
iterator start_n = this->m_start + difference_type(n);
std::uninitialized_copy(detail::make_move_iterator(this->m_start), detail::make_move_iterator(start_n), new_start);
boost::interprocess::uninitialized_copy(detail::make_move_iterator(this->m_start), detail::make_move_iterator(start_n), new_start);
this->m_start = new_start;
std::copy(detail::make_move_iterator(start_n), detail::make_move_iterator(pos), old_start);
std::copy(first, last, pos - difference_type(n));
@@ -1053,7 +1145,7 @@ class deque : protected deque_base<T, Alloc>
BOOST_TRY {
if (elemsafter > difference_type(n)) {
iterator finish_n = this->m_finish - difference_type(n);
std::uninitialized_copy(detail::make_move_iterator(finish_n), detail::make_move_iterator(this->m_finish), this->m_finish);
boost::interprocess::uninitialized_copy(detail::make_move_iterator(finish_n), detail::make_move_iterator(this->m_finish), this->m_finish);
this->m_finish = new_finish;
std::copy_backward(detail::make_move_iterator(pos), detail::make_move_iterator(finish_n), old_finish);
std::copy(first, last, pos);
@@ -1087,9 +1179,9 @@ class deque : protected deque_base<T, Alloc>
index_pointer cur;
BOOST_TRY {
for (cur = this->m_start.m_node; cur < this->m_finish.m_node; ++cur){
std::uninitialized_fill(*cur, *cur + this->s_buffer_size(), value);
boost::interprocess::uninitialized_fill(*cur, *cur + this->s_buffer_size(), value);
}
std::uninitialized_fill(this->m_finish.m_first, this->m_finish.m_cur, value);
boost::interprocess::uninitialized_fill(this->m_finish.m_first, this->m_finish.m_cur, value);
}
BOOST_CATCH(...){
this->priv_destroy_range(this->m_start, iterator(*cur, cur));
@@ -1127,10 +1219,10 @@ class deque : protected deque_base<T, Alloc>
++cur_node) {
FwdIt mid = first;
std::advance(mid, this->s_buffer_size());
std::uninitialized_copy(first, mid, *cur_node);
boost::interprocess::uninitialized_copy(first, mid, *cur_node);
first = mid;
}
std::uninitialized_copy(first, last, this->m_finish.m_first);
boost::interprocess::uninitialized_copy(first, last, this->m_finish.m_first);
}
BOOST_CATCH(...){
this->priv_destroy_range(this->m_start, iterator(*cur_node, cur_node));
@@ -1145,7 +1237,7 @@ class deque : protected deque_base<T, Alloc>
this->priv_reserve_map_at_back();
*(this->m_finish.m_node + 1) = this->priv_allocate_node();
BOOST_TRY {
this->allocator_type::construct(this->m_finish.m_cur, t);
new(detail::get_pointer(this->m_finish.m_cur))value_type(t);
this->m_finish.priv_set_node(this->m_finish.m_node + 1);
this->m_finish.m_cur = this->m_finish.m_first;
}
@@ -1157,12 +1249,13 @@ class deque : protected deque_base<T, Alloc>
}
// Called only if this->m_finish.m_cur == this->m_finish.m_last - 1.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void priv_push_back_aux(const detail::moved_object<value_type> &mt)
{
this->priv_reserve_map_at_back();
*(this->m_finish.m_node + 1) = this->priv_allocate_node();
BOOST_TRY {
this->allocator_type::construct(this->m_finish.m_cur, mt);
new(detail::get_pointer(this->m_finish.m_cur))value_type(mt);
this->m_finish.priv_set_node(this->m_finish.m_node + 1);
this->m_finish.m_cur = this->m_finish.m_first;
}
@@ -1172,6 +1265,23 @@ class deque : protected deque_base<T, Alloc>
}
BOOST_CATCH_END
}
#else
void priv_push_back_aux(value_type &&mt)
{
this->priv_reserve_map_at_back();
*(this->m_finish.m_node + 1) = this->priv_allocate_node();
BOOST_TRY {
new(detail::get_pointer(this->m_finish.m_cur))value_type(move(mt));
this->m_finish.priv_set_node(this->m_finish.m_node + 1);
this->m_finish.m_cur = this->m_finish.m_first;
}
BOOST_CATCH(...){
this->priv_deallocate_node(*(this->m_finish.m_node + 1));
BOOST_RETHROW
}
BOOST_CATCH_END
}
#endif
// Called only if this->m_start.m_cur == this->m_start.m_first.
void priv_push_front_aux(const value_type& t)
@@ -1181,7 +1291,7 @@ class deque : protected deque_base<T, Alloc>
BOOST_TRY {
this->m_start.priv_set_node(this->m_start.m_node - 1);
this->m_start.m_cur = this->m_start.m_last - 1;
this->allocator_type::construct(this->m_start.m_cur, t);
new(detail::get_pointer(this->m_start.m_cur))value_type(t);
}
BOOST_CATCH(...){
++this->m_start;
@@ -1191,6 +1301,7 @@ class deque : protected deque_base<T, Alloc>
BOOST_CATCH_END
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void priv_push_front_aux(const detail::moved_object<value_type> &mt)
{
this->priv_reserve_map_at_front();
@@ -1198,7 +1309,7 @@ class deque : protected deque_base<T, Alloc>
BOOST_TRY {
this->m_start.priv_set_node(this->m_start.m_node - 1);
this->m_start.m_cur = this->m_start.m_last - 1;
this->allocator_type::construct(this->m_start.m_cur, mt);
new(detail::get_pointer(this->m_start.m_cur))value_type(mt);
}
BOOST_CATCH(...){
++this->m_start;
@@ -1206,7 +1317,25 @@ class deque : protected deque_base<T, Alloc>
BOOST_RETHROW
}
BOOST_CATCH_END
}
}
#else
void priv_push_front_aux(value_type &&mt)
{
this->priv_reserve_map_at_front();
*(this->m_start.m_node - 1) = this->priv_allocate_node();
BOOST_TRY {
this->m_start.priv_set_node(this->m_start.m_node - 1);
this->m_start.m_cur = this->m_start.m_last - 1;
new(detail::get_pointer(this->m_start.m_cur))value_type(move(mt));
}
BOOST_CATCH(...){
++this->m_start;
this->priv_deallocate_node(*(this->m_start.m_node - 1));
BOOST_RETHROW
}
BOOST_CATCH_END
}
#endif
// Called only if this->m_finish.m_cur == this->m_finish.m_first.
void priv_pop_back_aux()
@@ -1214,7 +1343,7 @@ class deque : protected deque_base<T, Alloc>
this->priv_deallocate_node(this->m_finish.m_first);
this->m_finish.priv_set_node(this->m_finish.m_node - 1);
this->m_finish.m_cur = this->m_finish.m_last - 1;
static_cast<allocator_type*>(this)->destroy(this->m_finish.m_cur);
detail::get_pointer(this->m_finish.m_cur)->~value_type();
}
// Called only if this->m_start.m_cur == this->m_start.m_last - 1. Note that
@@ -1223,7 +1352,7 @@ class deque : protected deque_base<T, Alloc>
// must have at least two nodes.
void priv_pop_front_aux()
{
static_cast<allocator_type*>(this)->destroy(this->m_start.m_cur);
detail::get_pointer(this->m_start.m_cur)->~value_type();
this->priv_deallocate_node(this->m_start.m_first);
this->m_start.priv_set_node(this->m_start.m_node + 1);
this->m_start.m_cur = this->m_start.m_first;
@@ -1336,13 +1465,13 @@ class deque : protected deque_base<T, Alloc>
iterator first2, iterator last2,
const T& x)
{
iterator mid2 = std::uninitialized_copy(first1, last1, first2);
iterator mid2 = boost::interprocess::uninitialized_copy(first1, last1, first2);
BOOST_TRY {
std::uninitialized_fill(mid2, last2, x);
boost::interprocess::uninitialized_fill(mid2, last2, x);
}
BOOST_CATCH(...){
for(;first2 != mid2; ++first2){
static_cast<allocator_type*>(this)->destroy(&*first2);
detail::get_pointer(&*first2)->~value_type();
}
}
BOOST_CATCH_END
@@ -1355,13 +1484,13 @@ class deque : protected deque_base<T, Alloc>
const T& x,
iterator first, iterator last)
{
std::uninitialized_fill(result, mid, x);
boost::interprocess::uninitialized_fill(result, mid, x);
BOOST_TRY {
return std::uninitialized_copy(first, last, mid);
return boost::interprocess::uninitialized_copy(first, last, mid);
}
BOOST_CATCH(...){
for(;result != mid; ++result){
static_cast<allocator_type*>(this)->destroy(&*result);
detail::get_pointer(&*result)->~value_type();
}
BOOST_RETHROW
}
@@ -1377,13 +1506,13 @@ class deque : protected deque_base<T, Alloc>
InpIt2 first2, InpIt2 last2,
FwdIt result)
{
FwdIt mid = std::uninitialized_copy(first1, last1, result);
FwdIt mid = boost::interprocess::uninitialized_copy(first1, last1, result);
BOOST_TRY {
return std::uninitialized_copy(first2, last2, mid);
return boost::interprocess::uninitialized_copy(first2, last2, mid);
}
BOOST_CATCH(...){
for(;result != mid; ++result){
static_cast<allocator_type*>(this)->destroy(&*result);
detail::get_pointer(&*result)->~value_type();
}
BOOST_RETHROW
}

View File

@@ -37,7 +37,6 @@
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
@@ -134,9 +133,15 @@ class flat_tree
: m_data(x.m_data, x.m_data.m_vect)
{ }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_tree(const detail::moved_object<flat_tree> &x)
: m_data(move(x.get().m_data))
{ }
#else
flat_tree(flat_tree &&x)
: m_data(move(x.m_data))
{ }
#endif
~flat_tree()
{ }
@@ -144,8 +149,13 @@ class flat_tree
flat_tree& operator=(const flat_tree& x)
{ flat_tree(x).swap(*this); return *this; }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_tree& operator=(const detail::moved_object<flat_tree>& mx)
{ m_data = move(mx.get().m_data); return *this; }
#else
flat_tree& operator=(flat_tree &&mx)
{ m_data = move(mx.m_data); return *this; }
#endif
public:
// accessors:
@@ -198,10 +208,15 @@ class flat_tree
myvect.swap(othervect);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<flat_tree>& other)
{ this->swap(other.get()); }
#else
void swap(flat_tree &&other)
{ this->swap(other); }
#endif
public:
public:
// insert/erase
std::pair<iterator,bool> insert_unique(const value_type& val)
{
@@ -213,6 +228,7 @@ class flat_tree
return ret;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert_unique(const detail::moved_object<value_type>& mval)
{
insert_commit_data data;
@@ -222,6 +238,18 @@ class flat_tree
}
return ret;
}
#else
std::pair<iterator,bool> insert_unique(value_type && mval)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(mval, data);
if(ret.second){
ret.first = priv_insert_commit(data, move(mval));
}
return ret;
}
#endif
iterator insert_equal(const value_type& val)
{
@@ -230,12 +258,21 @@ class flat_tree
return i;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_equal(const detail::moved_object<value_type>& mval)
{
iterator i = this->upper_bound(KeyOfValue()(mval.get()));
i = this->m_data.m_vect.insert(i, mval);
return i;
}
#else
iterator insert_equal(value_type && mval)
{
iterator i = this->upper_bound(KeyOfValue()(mval));
i = this->m_data.m_vect.insert(i, move(mval));
return i;
}
#endif
iterator insert_unique(const_iterator pos, const value_type& val)
{
@@ -247,6 +284,7 @@ class flat_tree
return ret.first;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_unique(const_iterator pos, const detail::moved_object<value_type>& mval)
{
insert_commit_data data;
@@ -256,6 +294,17 @@ class flat_tree
}
return ret.first;
}
#else
iterator insert_unique(const_iterator pos, 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, move(mval));
}
return ret.first;
}
#endif
iterator insert_equal(const_iterator pos, const value_type& val)
{
@@ -264,12 +313,21 @@ class flat_tree
return priv_insert_commit(data, val);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_equal(const_iterator pos, const detail::moved_object<value_type>& mval)
{
insert_commit_data data;
priv_insert_equal_prepare(pos, mval.get(), data);
return priv_insert_commit(data, mval);
}
#else
iterator insert_equal(const_iterator pos, value_type && mval)
{
insert_commit_data data;
priv_insert_equal_prepare(pos, mval, data);
return priv_insert_commit(data, move(mval));
}
#endif
template <class InIt>
void insert_unique(InIt first, InIt last)
@@ -468,10 +526,17 @@ class flat_tree
}
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
iterator priv_insert_commit
(insert_commit_data &commit_data, const Convertible &convertible)
{ return this->m_data.m_vect.insert(commit_data.position, convertible); }
#else
template<class Convertible>
iterator priv_insert_commit
(insert_commit_data &commit_data, Convertible &&convertible)
{ return this->m_data.m_vect.insert(commit_data.position, forward<Convertible>(convertible)); }
#endif
template <class RanIt>
RanIt priv_lower_bound(RanIt first, RanIt last,

View File

@@ -47,16 +47,11 @@
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/interprocess/detail/generic_cast.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/intrusive/rbtree.hpp>
#include <boost/intrusive/list.hpp>
#include <iterator>
#include <algorithm>
@@ -70,10 +65,7 @@ struct value_compare_impl
typedef Value value_type;
typedef KeyCompare key_compare;
typedef KeyOfValue key_of_value;
class dummy;
typedef typename boost::mpl::if_c
<is_same<Key, Value>::value, dummy, Key>::type key_type;
typedef Key key_type;
value_compare_impl(key_compare kcomp)
: key_compare(kcomp)
@@ -85,14 +77,9 @@ struct value_compare_impl
key_compare &key_comp()
{ return static_cast<key_compare &>(*this); }
bool operator()(const value_type &a, const value_type &b) const
template<class A, class B>
bool operator()(const A &a, const B &b) const
{ return key_compare::operator()(KeyOfValue()(a), KeyOfValue()(b)); }
bool operator()(const key_type &a, const value_type &b) const
{ return key_compare::operator()(a, KeyOfValue()(b)); }
bool operator()(const value_type &a, const key_type &b) const
{ return key_compare::operator()(KeyOfValue()(a), b); }
};
template <class T, class VoidPointer>
@@ -109,9 +96,15 @@ struct rbtree_node
typedef T value_type;
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
rbtree_node(const Convertible &conv)
: m_data(conv){}
#else
template<class Convertible>
rbtree_node(Convertible &&conv)
: m_data(forward<Convertible>(conv)){}
#endif
rbtree_node &operator=(const rbtree_node &other)
{ do_assign(other.m_data); return *this; }
@@ -133,21 +126,20 @@ struct rbtree_node
template<class A, class ValueCompare>
struct rbtree_alloc
: public boost::detail::allocator::
rebind_to<A, rbtree_node
<typename A::value_type, typename boost::detail::allocator::
rebind_to<A, void>::type::pointer>
>::type
: public A::template rebind<rbtree_node
< typename A::value_type
, typename detail::pointer_to_other<typename A::pointer, void>::type>
>::other
{
typedef rbtree_alloc<A, ValueCompare> self_t;
typedef typename A::value_type value_type;
typedef rbtree_node
<value_type, typename boost::detail::allocator::
rebind_to<A, void>::type::pointer> Node;
typedef typename boost::detail::allocator::
rebind_to<A, void>::type::pointer VoidPointer;
typedef typename boost::detail::allocator::
rebind_to<A, Node>::type NodeAlloc;
<typename A::value_type
,typename detail::pointer_to_other
<typename A::pointer, void>::type> Node;
typedef typename A::template rebind<Node>::other NodeAlloc;
typedef typename detail::pointer_to_other
<typename A::pointer, void>::type VoidPointer;
typedef A ValAlloc;
typedef typename NodeAlloc::pointer NodePtr;
typedef detail::scoped_deallocator<NodeAlloc> Deallocator;
@@ -180,28 +172,34 @@ struct rbtree_alloc
,boost::intrusive::safe_link
,typename A::size_type> Irbtree;
enum {
node_has_trivial_destructor =
boost::has_trivial_destructor<NodePtr>::value &&
boost::has_trivial_destructor<value_type>::value
};
rbtree_alloc(const ValAlloc &a, const ValueCompare &c)
: NodeAlloc(a), m_irbtree(node_compare(c))
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree_alloc(const detail::moved_object<ValAlloc> &a, const ValueCompare &c)
: NodeAlloc(a.get()), m_irbtree(node_compare(c))
{}
#else
rbtree_alloc(ValAlloc &&a, const ValueCompare &c)
: NodeAlloc(a), m_irbtree(node_compare(c))
{}
#endif
rbtree_alloc(const rbtree_alloc &other, const ValueCompare &c)
: NodeAlloc(other), m_irbtree(node_compare(c))
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree_alloc
(const detail::moved_object<rbtree_alloc> &other, const ValueCompare &c)
: NodeAlloc(move((NodeAlloc&)other.get())), m_irbtree(node_compare(c))
{ this->swap(other.get()); }
#else
rbtree_alloc(rbtree_alloc &&other, const ValueCompare &c)
: NodeAlloc(move((NodeAlloc&)other)), m_irbtree(node_compare(c))
{ this->swap(other); }
#endif
~rbtree_alloc()
{}
@@ -209,10 +207,17 @@ struct rbtree_alloc
typename NodeAlloc::size_type max_size() const
{ return NodeAlloc::max_size(); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
static void construct(const NodePtr &ptr, const Convertible &value)
{ new(detail::get_pointer(ptr)) Node(value); }
#else
template<class Convertible>
static void construct(const NodePtr &ptr, Convertible &&value)
{ new(detail::get_pointer(ptr)) Node(forward<Convertible>(value)); }
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible1, class Convertible2>
static void construct(const NodePtr &ptr,
const detail::moved_object<std::pair<Convertible1, Convertible2> > &value)
@@ -225,25 +230,49 @@ struct rbtree_alloc
new((void*)detail::get_pointer(ptr)) hack_node_t(value);
}
#else
template<class Convertible1, class Convertible2>
static void construct(const NodePtr &ptr,
std::pair<Convertible1, Convertible2> &&value)
{
//std::pair is not movable so we define our own type and overwrite it
typedef detail::pair<typename Node::value_type::first_type
,typename Node::value_type::second_type> hack_pair_t;
typedef rbtree_node<hack_pair_t, VoidPointer> hack_node_t;
new((void*)detail::get_pointer(ptr)) hack_node_t(value);
}
#endif
static void destroy(const NodePtr &ptr)
{ detail::get_pointer(ptr)->~Node(); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
NodePtr create_node(const Convertible& x)
{
NodePtr p = NodeAlloc::allocate(1);
scoped_ptr<Node, Deallocator>node_deallocator(p, *this);
Deallocator node_deallocator(p, *this);
self_t::construct(p, x);
node_deallocator.release();
return (p);
}
#else
template<class Convertible>
NodePtr create_node(Convertible &&x)
{
NodePtr p = NodeAlloc::allocate(1);
Deallocator node_deallocator(p, *this);
self_t::construct(p, forward<Convertible>(x));
node_deallocator.release();
return (p);
}
#endif
void destroy_node(NodePtr node)
{
if(!node_has_trivial_destructor){
self_t::destroy(node);
}
self_t::destroy(node);
NodeAlloc::deallocate(node, 1);
}
@@ -511,9 +540,15 @@ class rbtree
(x.m_irbtree, typename AllocHolder::cloner(*this), Destroyer(*this));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree(const detail::moved_object<rbtree>& x)
: AllocHolder(x.get(), x.get().key_comp())
{ this->swap(x.get()); }
#else
rbtree(rbtree &&x)
: AllocHolder(x, x.key_comp())
{ this->swap(x); }
#endif
~rbtree()
{ this->clear(); }
@@ -540,8 +575,13 @@ class rbtree
return *this;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
rbtree& operator=(const detail::moved_object<rbtree>& mx)
{ this->clear(); this->swap(mx.get()); return *this; }
#else
rbtree& operator=(rbtree &&mx)
{ this->clear(); this->swap(mx); return *this; }
#endif
public:
// accessors:
@@ -590,8 +630,13 @@ class rbtree
void swap(ThisType& x)
{ AllocHolder::swap(x); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<rbtree>& mt)
{ this->swap(mt.get()); }
#else
void swap(rbtree &&mt)
{ this->swap(mt); }
#endif
public:
@@ -621,6 +666,7 @@ class rbtree
return iterator(it);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_unique_commit
(const detail::moved_object<MovableConvertible>& mv, insert_commit_data &data)
@@ -629,6 +675,16 @@ class rbtree
iiterator it(this->m_irbtree.insert_unique_commit(*tmp, data));
return iterator(it);
}
#else
template<class MovableConvertible>
iterator insert_unique_commit
(MovableConvertible && mv, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(forward<MovableConvertible>(mv));
iiterator it(this->m_irbtree.insert_unique_commit(*tmp, data));
return iterator(it);
}
#endif
std::pair<iterator,bool> insert_unique(const value_type& v)
{
@@ -641,6 +697,7 @@ class rbtree
(this->insert_unique_commit(v, data), true);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique
(const detail::moved_object<MovableConvertible>& mv)
@@ -653,6 +710,19 @@ class rbtree
return std::pair<iterator,bool>
(this->insert_unique_commit(mv, data), true);
}
#else
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(MovableConvertible &&mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(mv), data);
if(!ret.second)
return ret;
return std::pair<iterator,bool>
(this->insert_unique_commit(forward<MovableConvertible>(mv), data), true);
}
#endif
iterator insert_unique(const_iterator hint, const value_type& v)
{
@@ -664,6 +734,7 @@ class rbtree
return this->insert_unique_commit(v, data);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_unique
(const_iterator hint, const detail::moved_object<MovableConvertible> &mv)
@@ -675,6 +746,19 @@ class rbtree
return ret.first;
return this->insert_unique_commit(mv, data);
}
#else
template<class MovableConvertible>
iterator insert_unique
(const_iterator hint, MovableConvertible &&mv)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, KeyOfValue()(mv), data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(forward<MovableConvertible>(mv), data);
}
#endif
template <class InputIterator>
void insert_unique(InputIterator first, InputIterator last)
@@ -698,12 +782,21 @@ class rbtree
return iterator(this->m_irbtree.insert_equal_upper_bound(*p));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_equal(const detail::moved_object<MovableConvertible> &mv)
{
NodePtr p(AllocHolder::create_node(mv));
return iterator(this->m_irbtree.insert_equal_upper_bound(*p));
}
#else
template<class MovableConvertible>
iterator insert_equal(MovableConvertible &&mv)
{
NodePtr p(AllocHolder::create_node(forward<MovableConvertible>(mv)));
return iterator(this->m_irbtree.insert_equal_upper_bound(*p));
}
#endif
iterator insert_equal(const_iterator hint, const value_type& v)
{
@@ -711,12 +804,21 @@ class rbtree
return iterator(this->m_irbtree.insert_equal(hint.get(), *p));
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, const detail::moved_object<MovableConvertible> &mv)
{
NodePtr p(AllocHolder::create_node(mv));
return iterator(this->m_irbtree.insert_equal(hint.get(), *p));
}
#else
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, MovableConvertible &&mv)
{
NodePtr p(AllocHolder::create_node(move(mv)));
return iterator(this->m_irbtree.insert_equal(hint.get(), *p));
}
#endif
template <class InputIterator>
void insert_equal(InputIterator first, InputIterator last)

View File

@@ -22,9 +22,9 @@
#include <utility>
#include <functional>
#include <memory>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/interprocess/containers/detail/flat_tree.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/move.hpp>
namespace boost { namespace interprocess {
@@ -72,15 +72,15 @@ class flat_map
//This is the real tree stored here. It's based on a movable pair
typedef detail::flat_tree<Key,
detail::pair<Key, T>,
detail::select1st< detail::pair<Key, T> >,
select1st< detail::pair<Key, T> >,
Pred,
typename boost::detail::allocator::
rebind_to<Alloc, detail::pair<Key, T> >::type> impl_tree_t;
typename Alloc::template
rebind<detail::pair<Key, T> >::other> impl_tree_t;
//This is the tree that we should store if pair was movable
typedef detail::flat_tree<Key,
std::pair<Key, T>,
detail::select1st< std::pair<Key, T> >,
select1st< std::pair<Key, T> >,
Pred,
Alloc> tree_t;
@@ -98,15 +98,21 @@ class flat_map
typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
typedef detail::moved_object<impl_value_type> impl_moved_value_type;
/*
template<class D, class S>
static D &force(S &s)
{ return *(reinterpret_cast<D*>(&s)); }
*/
#else
typedef impl_value_type&& impl_moved_value_type;
#endif
template<class D, class S>
static D &force(const S &s)
{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class D, class S>
static D &&force(S &&s)
{ return reinterpret_cast<D&&>(s); }
#endif
/// @endcond
public:
@@ -158,9 +164,15 @@ class flat_map
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_map(const detail::moved_object<flat_map<Key,T,Pred,Alloc> >& x)
: m_flat_tree(move(x.get().m_flat_tree)) {}
#else
flat_map(flat_map<Key,T,Pred,Alloc> && x)
: m_flat_tree(move(x.m_flat_tree)) {}
#endif
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
@@ -173,8 +185,13 @@ class flat_map
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_map<Key,T,Pred,Alloc>& operator=(const detail::moved_object<flat_map<Key, T, Pred, Alloc> >& mx)
{ m_flat_tree = move(mx.get().m_flat_tree); return *this; }
#else
flat_map<Key,T,Pred,Alloc>& operator=(flat_map<Key, T, Pred, Alloc> && mx)
{ m_flat_tree = move(mx.m_flat_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
@@ -289,6 +306,13 @@ class flat_map
size_type max_size() const
{ return m_flat_tree.max_size(); }
//! Effects: If there is no key equivalent to x in the flat_map, inserts
//! value_type(move(x), T()) into the flat_map (the key is move-constructed)
//!
//! Returns: A reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
//! Effects: If there is no key equivalent to x in the flat_map, inserts
//! value_type(x, T()) into the flat_map.
//!
@@ -304,12 +328,6 @@ class flat_map
return (*i).second;
}
//! Effects: If there is no key equivalent to x in the flat_map, inserts
//! value_type(move(x), T()) into the flat_map (the key is move-constructed)
//!
//! Returns: A reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
T &operator[](const detail::moved_object<key_type>& mk)
{
key_type &k = mk.get();
@@ -319,6 +337,23 @@ class flat_map
i = insert(i, value_type(k, move(T())));
return (*i).second;
}
#else
//! Effects: If there is no key equivalent to x in the flat_map, inserts
//! value_type(x, T()) into the flat_map.
//!
//! Returns: A reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
T &operator[](key_type &&mk)
{
key_type &k = mk;
iterator i = lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first))
i = insert(i, value_type(forward<key_type>(k), move(T())));
return (*i).second;
}
#endif
//! <b>Effects</b>: Swaps the contents of *this and x.
//! If this->allocator_type() != x.allocator_type() allocators are also swapped.
@@ -335,8 +370,13 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<flat_map<Key,T,Pred,Alloc> >& x)
{ m_flat_tree.swap(x.get().m_flat_tree); }
#else
void swap(flat_map<Key,T,Pred,Alloc> && x)
{ m_flat_tree.swap(x.m_flat_tree); }
#endif
//! <b>Effects</b>: Inserts x if and only if there is no element in the container
//! with key equivalent to the key of x.
@@ -364,9 +404,15 @@ class flat_map
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert(const detail::moved_object<value_type>& x)
{ return force<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(force<impl_moved_value_type>(x))); }
#else
std::pair<iterator,bool> insert(value_type &&x)
{ return force<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(force<impl_moved_value_type>(move(x)))); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
//! no element in the container with key equivalent to the key of x.
@@ -392,9 +438,15 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<value_type>& x)
{ return force<iterator>(
m_flat_tree.insert_unique(force<impl_iterator>(position), force<impl_moved_value_type>(x))); }
#else
iterator insert(iterator position, value_type &&x)
{ return force<iterator>(
m_flat_tree.insert_unique(force<impl_iterator>(position), force<impl_moved_value_type>(move(x)))); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -571,6 +623,7 @@ inline bool operator>=(const flat_map<Key,T,Pred,Alloc>& x,
const flat_map<Key,T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class Key, class T, class Pred, class Alloc>
inline void swap(flat_map<Key,T,Pred,Alloc>& x,
flat_map<Key,T,Pred,Alloc>& y)
@@ -585,6 +638,12 @@ template <class Key, class T, class Pred, class Alloc>
inline void swap(flat_map<Key,T,Pred,Alloc>& x,
const detail::moved_object<flat_map<Key,T,Pred,Alloc> >& y)
{ x.swap(y.get()); }
#else
template <class Key, class T, class Pred, class Alloc>
inline void swap(flat_map<Key,T,Pred,Alloc>&&x,
flat_map<Key,T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
//!This class is movable
@@ -641,14 +700,14 @@ class flat_multimap
//This is the real tree stored here. It's based on a movable pair
typedef detail::flat_tree<Key,
detail::pair<Key, T>,
detail::select1st< detail::pair<Key, T> >,
select1st< detail::pair<Key, T> >,
Pred,
typename boost::detail::allocator::
rebind_to<Alloc, detail::pair<Key, T> >::type> impl_tree_t;
typename Alloc::template
rebind<detail::pair<Key, T> >::other> impl_tree_t;
typedef detail::flat_tree<Key,
std::pair<Key, T>,
detail::select1st< std::pair<Key, T> >,
select1st< std::pair<Key, T> >,
Pred,
Alloc> tree_t;
// tree_t m_flat_tree; // flat tree representing flat_multimap
@@ -665,15 +724,21 @@ class flat_multimap
typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
typedef detail::moved_object<impl_value_type> impl_moved_value_type;
/*
template<class D, class S>
static D &force(S &s)
{ return *(reinterpret_cast<D*>(&s)); }
*/
#else
typedef impl_value_type&& impl_moved_value_type;
#endif
template<class D, class S>
static D &force(const S &s)
{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class D, class S>
static D &&force(S &&s)
{ return reinterpret_cast<D&&>(s); }
#endif
/// @endcond
public:
@@ -726,8 +791,13 @@ class flat_multimap
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_multimap(const detail::moved_object<flat_multimap<Key,T,Pred,Alloc> >& x)
: m_flat_tree(move(x.get().m_flat_tree)) { }
#else
flat_multimap(flat_multimap<Key,T,Pred,Alloc> && x)
: m_flat_tree(move(x.m_flat_tree)) { }
#endif
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -739,9 +809,15 @@ class flat_multimap
//! <b>Effects</b>: this->swap(x.get()).
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_multimap<Key,T,Pred,Alloc>&
operator=(const detail::moved_object<flat_multimap<Key,T,Pred,Alloc> >& mx)
{ m_flat_tree = move(mx.get().m_flat_tree); return *this; }
#else
flat_multimap<Key,T,Pred,Alloc>&
operator=(flat_multimap<Key,T,Pred,Alloc> && mx)
{ m_flat_tree = move(mx.m_flat_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
@@ -871,8 +947,13 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<flat_multimap<Key,T,Pred,Alloc> >& x)
{ m_flat_tree.swap(x.get().m_flat_tree); }
#else
void swap(flat_multimap<Key,T,Pred,Alloc> && x)
{ m_flat_tree.swap(x.m_flat_tree); }
#endif
//! <b>Effects</b>: Inserts x and returns the iterator pointing to the
//! newly inserted element.
@@ -891,8 +972,13 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(const detail::moved_object<value_type>& x)
{ return force<iterator>(m_flat_tree.insert_equal(force<impl_moved_value_type>(x))); }
#else
iterator insert(value_type &&x)
{ return force<iterator>(m_flat_tree.insert_equal(force<impl_moved_value_type>(move(x)))); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -919,8 +1005,13 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<value_type>& x)
{ return force<iterator>(m_flat_tree.insert_equal(force<impl_iterator>(position), force<impl_moved_value_type>(x))); }
#else
iterator insert(iterator position, value_type &&x)
{ return force<iterator>(m_flat_tree.insert_equal(force<impl_iterator>(position), force<impl_moved_value_type>(move(x)))); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -1098,6 +1189,7 @@ inline bool operator>=(const flat_multimap<Key,T,Pred,Alloc>& x,
const flat_multimap<Key,T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class Key, class T, class Pred, class Alloc>
inline void swap(flat_multimap<Key,T,Pred,Alloc>& x,
flat_multimap<Key,T,Pred,Alloc>& y)
@@ -1113,6 +1205,12 @@ template <class Key, class T, class Pred, class Alloc>
inline void swap(flat_multimap<Key,T,Pred,Alloc>& x,
const detail::moved_object<flat_multimap<Key,T,Pred,Alloc> > & y)
{ x.swap(y.get()); }
#else
template <class Key, class T, class Pred, class Alloc>
inline void swap(flat_multimap<Key,T,Pred,Alloc>&&x,
flat_multimap<Key,T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
//!This class is movable

View File

@@ -23,6 +23,7 @@
#include <functional>
#include <memory>
#include <boost/interprocess/containers/detail/flat_tree.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/move.hpp>
@@ -60,7 +61,7 @@ class flat_set
/// @cond
private:
typedef detail::flat_tree<T, T,
detail::identity<T>, Pred, Alloc> tree_t;
identity<T>, Pred, Alloc> tree_t;
tree_t m_flat_tree; // flat tree representing flat_set
/// @endcond
@@ -114,8 +115,13 @@ class flat_set
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_set(const detail::moved_object<flat_set<T,Pred,Alloc> >& mx)
: m_flat_tree(move(mx.get().m_flat_tree)) {}
#else
flat_set(flat_set<T,Pred,Alloc> && mx)
: m_flat_tree(move(mx.m_flat_tree)) {}
#endif
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -126,9 +132,16 @@ class flat_set
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_set<T,Pred,Alloc>& operator=(const detail::moved_object<flat_set<T, Pred, Alloc> > &mx)
{ m_flat_tree = move(mx.get().m_flat_tree); return *this; }
#else
flat_set<T,Pred,Alloc>& operator=(flat_set<T, Pred, Alloc> &&mx)
{ m_flat_tree = move(mx.m_flat_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
//!
@@ -257,8 +270,13 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object <flat_set<T,Pred,Alloc> >& mx)
{ this->swap(mx.get()); }
#else
void swap(flat_set<T,Pred,Alloc> && mx)
{ this->swap(mx); }
#endif
//! <b>Effects</b>: Inserts x if and only if there is no element in the container
//! with key equivalent to the key of x.
@@ -285,8 +303,13 @@ class flat_set
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert(const detail::moved_object<value_type>& x)
{ return m_flat_tree.insert_unique(x); }
#else
std::pair<iterator,bool> insert(value_type && x)
{ return m_flat_tree.insert_unique(move(x)); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
//! no element in the container with key equivalent to the key of x.
@@ -311,8 +334,13 @@ class flat_set
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<value_type>& x)
{ return m_flat_tree.insert_unique(position, x); }
#else
iterator insert(iterator position, value_type && x)
{ return m_flat_tree.insert_unique(position, move(x)); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -490,6 +518,7 @@ inline bool operator>=(const flat_set<T,Pred,Alloc>& x,
const flat_set<T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T, class Pred, class Alloc>
inline void swap(flat_set<T,Pred,Alloc>& x,
flat_set<T,Pred,Alloc>& y)
@@ -504,6 +533,12 @@ template <class T, class Pred, class Alloc>
inline void swap(flat_set<T,Pred,Alloc>& x,
const detail::moved_object<flat_set<T,Pred,Alloc> >& y)
{ x.swap(y.get()); }
#else
template <class T, class Pred, class Alloc>
inline void swap(flat_set<T,Pred,Alloc>&&x,
flat_set<T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
/*!This class is movable*/
@@ -543,7 +578,7 @@ class flat_multiset
/// @cond
private:
typedef detail::flat_tree<T, T,
detail::identity<T>, Pred, Alloc> tree_t;
identity<T>, Pred, Alloc> tree_t;
tree_t m_flat_tree; // flat tree representing flat_multiset
/// @endcond
@@ -580,14 +615,24 @@ class flat_multiset
flat_multiset(const flat_multiset<T,Pred,Alloc>& x)
: m_flat_tree(x.m_flat_tree) {}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_multiset(const detail::moved_object<flat_multiset<T,Pred,Alloc> >& x)
: m_flat_tree(move(x.get().m_flat_tree)) {}
#else
flat_multiset(flat_multiset<T,Pred,Alloc> && x)
: m_flat_tree(move(x.m_flat_tree)) {}
#endif
flat_multiset<T,Pred,Alloc>& operator=(const flat_multiset<T,Pred,Alloc>& x)
{ m_flat_tree = x.m_flat_tree; return *this; }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
flat_multiset<T,Pred,Alloc>& operator=(const detail::moved_object<flat_multiset<T,Pred,Alloc> >& mx)
{ m_flat_tree = move(mx.get().m_flat_tree); return *this; }
#else
flat_multiset<T,Pred,Alloc>& operator=(flat_multiset<T,Pred,Alloc> && mx)
{ m_flat_tree = move(mx.m_flat_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
@@ -717,8 +762,13 @@ class flat_multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<flat_multiset<T,Pred,Alloc> >& mx)
{ this->swap(mx.get()); }
#else
void swap(flat_multiset<T,Pred,Alloc> && mx)
{ this->swap(mx); }
#endif
//! <b>Effects</b>: Inserts x and returns the iterator pointing to the
//! newly inserted element.
@@ -737,8 +787,13 @@ class flat_multiset
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(const detail::moved_object<value_type>& x)
{ return m_flat_tree.insert_equal(x); }
#else
iterator insert(value_type && x)
{ return m_flat_tree.insert_equal(move(x)); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -763,8 +818,13 @@ class flat_multiset
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<value_type>& x)
{ return m_flat_tree.insert_equal(position, x); }
#else
iterator insert(iterator position, value_type && x)
{ return m_flat_tree.insert_equal(position, move(x)); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -942,6 +1002,7 @@ inline bool operator>=(const flat_multiset<T,Pred,Alloc>& x,
const flat_multiset<T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T, class Pred, class Alloc>
inline void swap(flat_multiset<T,Pred,Alloc>& x,
flat_multiset<T,Pred,Alloc>& y)
@@ -956,6 +1017,12 @@ template <class T, class Pred, class Alloc>
inline void swap(flat_multiset<T,Pred,Alloc>& x,
const detail::moved_object<flat_multiset<T,Pred,Alloc> >& y)
{ x.swap(y.get()); }
#else
template <class T, class Pred, class Alloc>
inline void swap(flat_multiset<T,Pred,Alloc>&&x,
flat_multiset<T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
/*!This class is movable*/

View File

@@ -55,17 +55,10 @@
#include <boost/iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/mpl/if.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <iterator>
#include <utility>
@@ -91,54 +84,66 @@ struct list_node
, boost::intrusive::safe_link
, VoidPointer> IlistData;
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
list_node(const Convertible &conv)
: m_data(conv)
{}
#else
template<class Convertible>
list_node(Convertible &&conv)
: m_data(forward<Convertible>(conv))
{}
#endif
T m_data;
};
template<class A>
struct list_alloc
: public boost::detail::allocator::
rebind_to<A, list_node
<typename A::value_type, typename boost::detail::allocator::
rebind_to<A, void>::type::pointer>
>::type
: public A::template rebind<list_node
< typename A::value_type
, typename detail::pointer_to_other<typename A::pointer, void>::type>
>::other
{
typedef list_alloc<A> self_t;
typedef typename A::value_type value_type;
typedef list_node
<value_type, typename boost::detail::allocator::
rebind_to<A, void>::type::pointer> Node;
typedef typename boost::detail::allocator::
rebind_to<A, Node>::type NodeAlloc;
<typename A::value_type
,typename detail::pointer_to_other
<typename A::pointer, void>::type> Node;
typedef typename A::template rebind<Node>::other NodeAlloc;
typedef A ValAlloc;
typedef typename NodeAlloc::pointer NodePtr;
typedef detail::scoped_deallocator<NodeAlloc> Deallocator;
enum {
node_has_trivial_destructor =
boost::has_trivial_destructor<NodePtr>::value &&
boost::has_trivial_destructor<value_type>::value
};
list_alloc(const ValAlloc &a)
: NodeAlloc(a)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
list_alloc(const detail::moved_object<ValAlloc> &a)
: NodeAlloc(a.get())
{}
#else
list_alloc(ValAlloc &&a)
: NodeAlloc(a)
{}
#endif
list_alloc(const list_alloc &other)
: NodeAlloc(other)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
list_alloc(const detail::moved_object<list_alloc> &other)
: NodeAlloc(move((NodeAlloc&)other.get()))
{ this->swap(other.get()); }
#else
list_alloc(list_alloc &&other)
: NodeAlloc(move((NodeAlloc&)other))
{ this->swap(other); }
#endif
~list_alloc()
{}
@@ -146,28 +151,44 @@ struct list_alloc
typename NodeAlloc::size_type max_size() const
{ return NodeAlloc::max_size(); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
static void construct(const NodePtr &ptr, const Convertible &value)
{ new(detail::get_pointer(ptr)) Node(value); }
#else
template<class Convertible>
static void construct(const NodePtr &ptr, Convertible &&value)
{ new(detail::get_pointer(ptr)) Node(forward<Convertible>(value)); }
#endif
static void destroy(const NodePtr &ptr)
{ detail::get_pointer(ptr)->~Node(); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
NodePtr create_node(const Convertible& x)
{
NodePtr p = NodeAlloc::allocate(1);
scoped_ptr<Node, Deallocator>node_deallocator(p, *this);
Deallocator node_deallocator(p, *this);
self_t::construct(p, x);
node_deallocator.release();
return (p);
}
#else
template<class Convertible>
NodePtr create_node(Convertible &&x)
{
NodePtr p = NodeAlloc::allocate(1);
Deallocator node_deallocator(p, *this);
self_t::construct(p, forward<Convertible>(x));
node_deallocator.release();
return (p);
}
#endif
void destroy_node(NodePtr node)
{
if(!node_has_trivial_destructor){
self_t::destroy(node);
}
self_t::destroy(node);
NodeAlloc::deallocate(node, 1);
}
@@ -433,9 +454,15 @@ class list
//! <b>Throws</b>: If allocator_type's default constructor throws.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
list(const detail::moved_object<list> &x)
: AllocHolder(move((AllocHolder&)x.get()))
{}
#else
list(list &&x)
: AllocHolder(move((AllocHolder&)x))
{}
#endif
//! <b>Effects</b>: Constructs a list that will use a copy of allocator a
//! and inserts a copy of the range [first, last) in the list.
@@ -581,8 +608,13 @@ class list
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_front(const detail::moved_object<T>& x)
{ this->insert(this->begin(), x); }
#else
void push_front(T &&x)
{ this->insert(this->begin(), move(x)); }
#endif
//! <b>Effects</b>: Removes the last element from the list.
//!
@@ -597,8 +629,13 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_back (const detail::moved_object<T>& x)
{ this->insert(this->end(), x); }
#else
void push_back (T &&x)
{ this->insert(this->end(), move(x)); }
#endif
//! <b>Effects</b>: Removes the first element from the list.
//!
@@ -758,12 +795,21 @@ class list
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
ThisType& operator=(const detail::moved_object<ThisType>& mx)
{
this->clear();
this->swap(mx.get());
return *this;
}
#else
ThisType& operator=(ThisType &&mx)
{
this->clear();
this->swap(mx);
return *this;
}
#endif
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
@@ -787,7 +833,7 @@ class list
void insert(iterator p, InpIt first, InpIt last)
{
const bool aux_boolean = boost::is_integral<InpIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_insert_dispatch(p, first, last, Result());
}
@@ -811,11 +857,19 @@ class list
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator p, const detail::moved_object<T>& x)
{
NodePtr tmp = AllocHolder::create_node(x);
return iterator(this->m_ilist.insert(p.get(), *tmp));
}
#else
iterator insert(iterator p, T &&x)
{
NodePtr tmp = AllocHolder::create_node(move(x));
return iterator(this->m_ilist.insert(p.get(), *tmp));
}
#endif
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
@@ -855,7 +909,7 @@ class list
void assign(InpIt first, InpIt last)
{
const bool aux_boolean = boost::is_integral<InpIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
}
@@ -1143,7 +1197,7 @@ class list
template <class InputIter>
void priv_insert_dispatch(iterator p,
InputIter first, InputIter last,
boost::mpl::false_)
false_)
{
for ( ; first != last; ++first){
this->insert(p, *first);
@@ -1151,7 +1205,7 @@ class list
}
template<class Integer>
void priv_insert_dispatch(iterator p, Integer n, Integer x, boost::mpl::true_)
void priv_insert_dispatch(iterator p, Integer n, Integer x, true_)
{ this->priv_fill_insert(p, n, x); }
void priv_fill_assign(size_type n, const T& val)
@@ -1167,12 +1221,12 @@ class list
}
template <class Integer>
void priv_assign_dispatch(Integer n, Integer val, boost::mpl::true_)
void priv_assign_dispatch(Integer n, Integer val, true_)
{ this->priv_fill_assign((size_type) n, (T) val); }
template <class InputIter>
void priv_assign_dispatch(InputIter first2, InputIter last2,
boost::mpl::false_)
false_)
{
iterator first1 = this->begin();
iterator last1 = this->end();
@@ -1248,6 +1302,7 @@ inline bool operator>=(const list<T,A>& x, const list<T,A>& y)
return !(x < y);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T, class A>
inline void swap(list<T, A>& x, list<T, A>& y)
{
@@ -1265,6 +1320,14 @@ inline void swap(list<T, A>& x, const detail::moved_object<list<T, A> >& y)
{
x.swap(y.get());
}
#else
template <class T, class A>
inline void swap(list<T, A> &&x, list<T, A> &&y)
{
x.swap(y);
}
#endif
/// @cond
/*!This class is movable*/

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gazta<EFBFBD>ga 2005-2007. Distributed under the Boost
// (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)
//
@@ -55,6 +55,7 @@
#include <functional>
#include <memory>
#include <boost/interprocess/containers/detail/tree.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/move.hpp>
namespace boost { namespace interprocess {
@@ -89,7 +90,7 @@ class map
private:
typedef detail::rbtree<Key,
std::pair<const Key, T>,
detail::select1st< std::pair<const Key, T> >,
select1st< std::pair<const Key, T> >,
Pred,
Alloc> tree_t;
tree_t m_tree; // red-black tree representing map
@@ -161,9 +162,15 @@ class map
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
map(const detail::moved_object<map<Key,T,Pred,Alloc> >& x)
: m_tree(move(x.get().m_tree))
{}
#else
map(map<Key,T,Pred,Alloc> &&x)
: m_tree(move(x.m_tree))
{}
#endif
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -174,8 +181,13 @@ class map
//! <b>Effects</b>: this->swap(x.get()).
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
map<Key,T,Pred,Alloc>& operator=(const detail::moved_object<map<Key,T,Pred,Alloc> >& x)
{ m_tree = move(x.get().m_tree); return *this; }
#else
map<Key,T,Pred,Alloc>& operator=(map<Key,T,Pred,Alloc> &&x)
{ m_tree = move(x.m_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
@@ -314,6 +326,7 @@ class map
//! Returns: A reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
T& operator[](const detail::moved_object<key_type>& mk)
{
key_type &k = mk.get();
@@ -326,6 +339,21 @@ class map
}
return (*i).second;
}
#else
T& operator[](key_type &&mk)
{
key_type &k = mk;
//we can optimize this
iterator i = lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first)){
value_type val(move(k), move(T()));
i = insert(i, move(val));
}
return (*i).second;
}
#endif
/*
//! Effects: If there is no key equivalent to x in the map, inserts
//! value_type(move(x), T()) into the map (the key is move-constructed)
@@ -370,8 +398,13 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<map<Key,T,Pred,Alloc> >& x)
{ m_tree.swap(x.get().m_tree); }
#else
void swap(map<Key,T,Pred,Alloc> &&x)
{ m_tree.swap(x.m_tree); }
#endif
//! <b>Effects</b>: Inserts x if and only if there is no element in the container
//! with key equivalent to the key of x.
@@ -403,8 +436,13 @@ class map
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert(const detail::moved_object<std::pair<key_type, mapped_type> > &x)
{ return m_tree.insert_unique(x); }
#else
std::pair<iterator,bool> insert(std::pair<key_type, mapped_type> &&x)
{ return m_tree.insert_unique(move(x)); }
#endif
//! <b>Effects</b>: Move constructs a new value from x if and only if there is
//! no element in the container with key equivalent to the key of x.
@@ -414,8 +452,13 @@ class map
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert(const detail::moved_object<value_type>& x)
{ return m_tree.insert_unique(x); }
#else
std::pair<iterator,bool> insert(value_type &&x)
{ return m_tree.insert_unique(move(x)); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
//! no element in the container with key equivalent to the key of x.
@@ -438,8 +481,13 @@ class map
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<std::pair<key_type, mapped_type> > &x)
{ return m_tree.insert_unique(position, x); }
#else
iterator insert(iterator position, std::pair<key_type, mapped_type> &&x)
{ return m_tree.insert_unique(position, move(x)); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -456,8 +504,13 @@ class map
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<value_type>& x)
{ return m_tree.insert_unique(position, x); }
#else
iterator insert(iterator position, value_type &&x)
{ return m_tree.insert_unique(position, move(x)); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -603,6 +656,7 @@ inline bool operator>=(const map<Key,T,Pred,Alloc>& x,
const map<Key,T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class Key, class T, class Pred, class Alloc>
inline void swap(map<Key,T,Pred,Alloc>& x,
map<Key,T,Pred,Alloc>& y)
@@ -617,6 +671,15 @@ template <class Key, class T, class Pred, class Alloc>
inline void swap(map<Key,T,Pred,Alloc>& x,
const detail::moved_object<map<Key,T,Pred,Alloc> >& y)
{ x.swap(y.get()); }
#else
template <class Key, class T, class Pred, class Alloc>
inline void swap(map<Key,T,Pred,Alloc>&&x,
map<Key,T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
/*!This class is movable*/
@@ -667,7 +730,7 @@ class multimap
private:
typedef detail::rbtree<Key,
std::pair<const Key, T>,
detail::select1st< std::pair<const Key, T> >,
select1st< std::pair<const Key, T> >,
Pred,
Alloc> tree_t;
tree_t m_tree; // red-black tree representing map
@@ -740,9 +803,15 @@ class multimap
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
multimap(const detail::moved_object<multimap<Key,T,Pred,Alloc> >& x)
: m_tree(move(x.get().m_tree))
{}
#else
multimap(multimap<Key,T,Pred,Alloc> && x)
: m_tree(move(x.m_tree))
{}
#endif
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -754,9 +823,15 @@ class multimap
//! <b>Effects</b>: this->swap(x.get()).
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
multimap<Key,T,Pred,Alloc>&
operator=(const detail::moved_object<multimap<Key,T,Pred,Alloc> >& x)
{ m_tree = move(x.get().m_tree); return *this; }
#else
multimap<Key,T,Pred,Alloc>&
operator=(multimap<Key,T,Pred,Alloc> && x)
{ m_tree = move(x.m_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
@@ -886,8 +961,13 @@ class multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<multimap<Key,T,Pred,Alloc> >& x)
{ m_tree.swap(x.get().m_tree); }
#else
void swap(multimap<Key,T,Pred,Alloc> && x)
{ m_tree.swap(x.m_tree); }
#endif
//! <b>Effects</b>: Inserts x and returns the iterator pointing to the
//! newly inserted element.
@@ -907,8 +987,13 @@ class multimap
//! the iterator pointing to the newly inserted element.
//!
//! <b>Complexity</b>: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(const detail::moved_object<std::pair<key_type, mapped_type> >& x)
{ return m_tree.insert_equal(x); }
#else
iterator insert(std::pair<key_type, mapped_type> && x)
{ return m_tree.insert_equal(move(x)); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -940,8 +1025,13 @@ class multimap
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<std::pair<key_type, mapped_type> >& x)
{ return m_tree.insert_equal(position, x); }
#else
iterator insert(iterator position, std::pair<key_type, mapped_type> && x)
{ return m_tree.insert_equal(position, move(x)); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -1088,6 +1178,8 @@ inline bool operator>=(const multimap<Key,T,Pred,Alloc>& x,
const multimap<Key,T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class Key, class T, class Pred, class Alloc>
inline void swap(multimap<Key,T,Pred,Alloc>& x,
multimap<Key,T,Pred,Alloc>& y)
@@ -1102,6 +1194,12 @@ template <class Key, class T, class Pred, class Alloc>
inline void swap(multimap<Key,T,Pred,Alloc>& x,
const detail::moved_object<multimap<Key,T,Pred,Alloc> >& y)
{ x.swap(y.get()); }
#else
template <class Key, class T, class Pred, class Alloc>
inline void swap(multimap<Key,T,Pred,Alloc>&&x,
multimap<Key,T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
template <class T, class P, class A>

View File

@@ -49,15 +49,17 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <utility>
#include <functional>
#include <memory>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/containers/detail/tree.hpp>
#include <boost/interprocess/detail/move.hpp>
namespace boost { namespace interprocess {
/// @cond
@@ -84,7 +86,7 @@ class set
/// @cond
private:
typedef detail::rbtree<T, T,
detail::identity<T>, Pred, Alloc> tree_t;
identity<T>, Pred, Alloc> tree_t;
tree_t m_tree; // red-black tree representing set
/// @endcond
@@ -138,9 +140,15 @@ class set
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
set(const detail::moved_object<set<T,Pred,Alloc> >& x)
: m_tree(move(x.get().m_tree))
{}
#else
set(set<T,Pred,Alloc> &&x)
: m_tree(move(x.m_tree))
{}
#endif
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -151,8 +159,13 @@ class set
//! <b>Effects</b>: this->swap(x.get()).
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
set<T,Pred,Alloc>& operator=(const detail::moved_object<set<T, Pred, Alloc> >& x)
{ m_tree = move(x.get().m_tree); return *this; }
#else
set<T,Pred,Alloc>& operator=(set<T, Pred, Alloc> &&x)
{ m_tree = move(x.m_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
@@ -282,8 +295,13 @@ class set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<set<T,Pred,Alloc> >& x)
{ m_tree.swap(x.get().m_tree); }
#else
void swap(set<T,Pred,Alloc> &&x)
{ m_tree.swap(x.m_tree); }
#endif
//! <b>Effects</b>: Inserts x if and only if there is no element in the container
//! with key equivalent to the key of x.
@@ -304,8 +322,13 @@ class set
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert(const detail::moved_object<value_type>& x)
{ return m_tree.insert_unique(x); }
#else
std::pair<iterator,bool> insert(value_type &&x)
{ return m_tree.insert_unique(move(x)); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
//! no element in the container with key equivalent to the key of x.
@@ -325,8 +348,13 @@ class set
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(const_iterator p, const detail::moved_object<value_type>& x)
{ return m_tree.insert_unique(p, x); }
#else
iterator insert(const_iterator p, value_type &&x)
{ return m_tree.insert_unique(p, move(x)); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -473,6 +501,7 @@ inline bool operator>=(const set<T,Pred,Alloc>& x,
const set<T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T, class Pred, class Alloc>
inline void swap(set<T,Pred,Alloc>& x,
set<T,Pred,Alloc>& y)
@@ -488,6 +517,13 @@ inline void swap(detail::moved_object<set<T,Pred,Alloc> >& y,
set<T,Pred,Alloc>& x)
{ y.swap(x.get()); }
#else
template <class T, class Pred, class Alloc>
inline void swap(set<T,Pred,Alloc>&&x,
set<T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
/*!This class is movable*/
template <class T, class P, class A>
@@ -530,7 +566,7 @@ class multiset
/// @cond
private:
typedef detail::rbtree<T, T,
detail::identity<T>, Pred, Alloc> tree_t;
identity<T>, Pred, Alloc> tree_t;
tree_t m_tree; // red-black tree representing multiset
/// @endcond
@@ -585,9 +621,15 @@ class multiset
//! <b>Complexity</b>: Construct.
//!
//! <b>Postcondition</b>: x is emptied.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
multiset(const detail::moved_object<multiset<T,Pred,Alloc> >& x)
: m_tree(move(x.get().m_tree))
{}
#else
multiset(multiset<T,Pred,Alloc> &&x)
: m_tree(move(x.m_tree))
{}
#endif
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -598,8 +640,13 @@ class multiset
//! <b>Effects</b>: this->swap(x.get()).
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
multiset<T,Pred,Alloc>& operator=(const detail::moved_object<multiset<T,Pred,Alloc> >& x)
{ m_tree = move(x.get().m_tree); return *this; }
#else
multiset<T,Pred,Alloc>& operator=(multiset<T,Pred,Alloc> &&x)
{ m_tree = move(x.m_tree); return *this; }
#endif
//! <b>Effects</b>: Returns the comparison object out
//! of which a was constructed.
@@ -729,8 +776,13 @@ class multiset
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<multiset<T,Pred,Alloc> >& x)
{ m_tree.swap(x.get().m_tree); }
#else
void swap(multiset<T,Pred,Alloc> && x)
{ m_tree.swap(x.m_tree); }
#endif
//! <b>Effects</b>: Inserts x and returns the iterator pointing to the
//! newly inserted element.
@@ -746,8 +798,13 @@ class multiset
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(const detail::moved_object<value_type>& x)
{ return m_tree.insert_equal(x); }
#else
iterator insert(value_type && x)
{ return m_tree.insert_equal(move(x)); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -768,8 +825,13 @@ class multiset
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(const_iterator p, const detail::moved_object<value_type>& x)
{ return m_tree.insert_equal(p, x); }
#else
iterator insert(const_iterator p, value_type && x)
{ return m_tree.insert_equal(p, move(x)); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
//!
@@ -916,6 +978,7 @@ inline bool operator>=(const multiset<T,Pred,Alloc>& x,
const multiset<T,Pred,Alloc>& y)
{ return !(x < y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T, class Pred, class Alloc>
inline void swap(multiset<T,Pred,Alloc>& x,
multiset<T,Pred,Alloc>& y)
@@ -930,6 +993,12 @@ template <class T, class Pred, class Alloc>
inline void swap(detail::moved_object<multiset<T,Pred,Alloc> >& y,
multiset<T,Pred,Alloc>& x)
{ y.swap(x.get()); }
#else
template <class T, class Pred, class Alloc>
inline void swap(multiset<T,Pred,Alloc>&&x,
multiset<T,Pred,Alloc>&&y)
{ x.swap(y); }
#endif
/// @cond
/*!This class is movable*/

View File

@@ -54,12 +54,12 @@
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <iterator>
#include <utility>
@@ -83,54 +83,65 @@ struct slist_node
, boost::intrusive::safe_link
, VoidPointer> IslistData;
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
slist_node(const Convertible &value)
: m_data(value){}
#else
template<class Convertible>
slist_node(Convertible &&value)
: m_data(forward<Convertible>(value)){}
#endif
T m_data;
};
template<class A>
struct slist_alloc
: public boost::detail::allocator::
rebind_to<A, slist_node
<typename A::value_type, typename boost::detail::allocator::
rebind_to<A, void>::type::pointer>
>::type
: public A::template rebind<slist_node
< typename A::value_type
, typename detail::pointer_to_other<typename A::pointer, void>::type>
>::other
{
typedef slist_alloc<A> self_t;
typedef typename A::value_type value_type;
typedef slist_node
<value_type, typename boost::detail::allocator::
rebind_to<A, void>::type::pointer> Node;
typedef typename boost::detail::allocator::
rebind_to<A, Node>::type NodeAlloc;
<typename A::value_type
,typename detail::pointer_to_other
<typename A::pointer, void>::type> Node;
typedef typename A::template rebind<Node>::other NodeAlloc;
typedef A ValAlloc;
typedef typename A::size_type SizeType;
typedef typename NodeAlloc::pointer NodePtr;
typedef detail::scoped_deallocator<NodeAlloc> Deallocator;
enum {
node_has_trivial_destructor =
boost::has_trivial_destructor<NodePtr>::value &&
boost::has_trivial_destructor<value_type>::value
};
slist_alloc(const ValAlloc &a)
: NodeAlloc(a)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
slist_alloc(const detail::moved_object<ValAlloc> &a)
: NodeAlloc(a.get())
{}
#else
slist_alloc(ValAlloc&&a)
: NodeAlloc(a)
{}
#endif
slist_alloc(const slist_alloc &other)
: NodeAlloc(other)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
slist_alloc(const detail::moved_object<slist_alloc> &other)
: NodeAlloc(move((NodeAlloc&)other.get()))
{ this->swap(other.get()); }
#else
slist_alloc(slist_alloc &&other)
: NodeAlloc(move((NodeAlloc&)other))
{ this->swap(other); }
#endif
~slist_alloc()
{}
@@ -138,28 +149,44 @@ struct slist_alloc
typename NodeAlloc::size_type max_size() const
{ return NodeAlloc::max_size(); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
static void construct(const NodePtr &ptr, const Convertible &value)
{ new(detail::get_pointer(ptr)) Node(value); }
#else
template<class Convertible>
static void construct(const NodePtr &ptr, Convertible &&value)
{ new(detail::get_pointer(ptr)) Node(forward<Convertible>(value)); }
#endif
static void destroy(const NodePtr &ptr)
{ detail::get_pointer(ptr)->~Node(); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible>
NodePtr create_node(const Convertible& x)
{
NodePtr p = NodeAlloc::allocate(1);
scoped_ptr<Node, Deallocator>node_deallocator(p, *this);
Deallocator node_deallocator(p, *this);
self_t::construct(p, x);
node_deallocator.release();
return (p);
}
#else
template<class Convertible>
NodePtr create_node(Convertible &&x)
{
NodePtr p = NodeAlloc::allocate(1);
Deallocator node_deallocator(p, *this);
self_t::construct(p, forward<Convertible>(x));
node_deallocator.release();
return (p);
}
#endif
void destroy_node(NodePtr node)
{
if(!node_has_trivial_destructor){
self_t::destroy(node);
}
self_t::destroy(node);
NodeAlloc::deallocate(node, 1);
}
@@ -428,9 +455,15 @@ class slist
//! <b>Throws</b>: If allocator_type's default constructor throws.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
slist(const detail::moved_object<slist> &x)
: AllocHolder(move((AllocHolder&)x.get()))
{}
#else
slist(slist &&x)
: AllocHolder(move((AllocHolder&)x))
{}
#endif
//! <b>Effects</b>: Makes *this contain the same elements as x.
//!
@@ -456,6 +489,7 @@ class slist
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to the number of elements in x.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
slist& operator= (const detail::moved_object<slist>& mx)
{
if (&mx.get() != this){
@@ -464,6 +498,16 @@ class slist
}
return *this;
}
#else
slist& operator= (slist && mx)
{
if (&mx != this){
this->clear();
this->swap(mx);
}
return *this;
}
#endif
//! <b>Effects</b>: Destroys the list. All stored values are destroyed
//! and used memory is deallocated.
@@ -502,7 +546,7 @@ class slist
void assign(InpIt first, InpIt last)
{
const bool aux_boolean = boost::is_integral<InpIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->assign_dispatch(first, last, Result());
}
@@ -629,8 +673,13 @@ class slist
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_front(const detail::moved_object<T>& x)
{ this->m_islist.push_front(*this->create_node(x)); }
#else
void push_front(T && x)
{ this->m_islist.push_front(*this->create_node(move(x))); }
#endif
//! <b>Effects</b>: Removes the first element from the list.
//!
@@ -689,8 +738,13 @@ class slist
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert_after(iterator prev_pos, const detail::moved_object<value_type>& x)
{ return iterator(this->m_islist.insert_after(prev_pos.get(), *this->create_node(x))); }
#else
iterator insert_after(iterator prev_pos, value_type && x)
{ return iterator(this->m_islist.insert_after(prev_pos.get(), *this->create_node(move(x)))); }
#endif
//! <b>Requires</b>: prev_pos must be a valid iterator of *this.
//!
@@ -738,8 +792,13 @@ class slist
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Linear to the elements before p.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator p, const detail::moved_object<value_type>& x)
{ return insert_after(previous(p), x); }
#else
iterator insert(iterator p, value_type && x)
{ return insert_after(previous(p), move(x)); }
#endif
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
@@ -1223,12 +1282,12 @@ class slist
}
template <class Int>
void assign_dispatch(Int n, Int val, boost::mpl::true_)
void assign_dispatch(Int n, Int val, true_)
{ this->fill_assign((size_type) n, (T)val); }
template <class InpIt>
void assign_dispatch(InpIt first, InpIt last,
boost::mpl::false_)
false_)
{
iterator end_n(end());
iterator prev(before_begin());
@@ -1258,16 +1317,16 @@ class slist
void insert_after_range(iterator prev_pos, InIter first, InIter last)
{
const bool aux_boolean = boost::is_integral<InIter>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->insert_after_range(prev_pos, first, last, Result());
}
template <class Int>
void insert_after_range(iterator prev_pos, Int n, Int x, boost::mpl::true_)
void insert_after_range(iterator prev_pos, Int n, Int x, true_)
{ this->priv_insert_after_fill(prev_pos, n, x); }
template <class InIter>
void insert_after_range(iterator prev_pos, InIter first, InIter last, boost::mpl::false_)
void insert_after_range(iterator prev_pos, InIter first, InIter last, false_)
{
typename Islist::iterator intrusive_it(prev_pos.get());
while (first != last){
@@ -1349,6 +1408,7 @@ inline bool
operator>=(const slist<T,A>& sL1, const slist<T,A>& sL2)
{ return !(sL1 < sL2); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T, class A>
inline void swap(slist<T,A>& x, slist<T,A>& y)
{ x.swap(y); }
@@ -1360,6 +1420,11 @@ inline void swap(const detail::moved_object<slist<T,A> >& x, slist<T,A>& y)
template <class T, class A>
inline void swap(slist<T,A>& x, const detail::moved_object<slist<T,A> >& y)
{ x.swap(y.get()); }
#else
template <class T, class A>
inline void swap(slist<T,A>&&x, slist<T,A>&&y)
{ x.swap(y); }
#endif
/// @cond
/*!This class is movable*/

View File

@@ -30,15 +30,18 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/config.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/algorithms.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <functional>
#include <string>
#include <stdexcept>
@@ -95,12 +98,21 @@ class basic_string_base
this->allocate_initial_block(n);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_string_base(const detail::moved_object<basic_string_base<A> >& b)
: allocator_type(static_cast<allocator_type&>(b.get()))
{
init();
this->swap(b.get());
}
#else
basic_string_base(basic_string_base<A> && b)
: allocator_type(static_cast<allocator_type&>(b))
{
init();
this->swap(b);
}
#endif
~basic_string_base()
{
@@ -279,13 +291,16 @@ class basic_string_base
}
void construct(pointer p, const value_type &value = value_type())
{ allocator_type::construct(p, value); }
{ new(detail::get_pointer(p)) value_type(value); }
void destroy(pointer p, size_type n)
{ for(; n--; ++p) allocator_type::destroy(p); }
{
for(; n--; ++p)
detail::get_pointer(p)->~value_type();
}
void destroy(pointer p)
{ allocator_type::destroy(p); }
{ detail::get_pointer(p)->~value_type(); }
void allocate_initial_block(std::size_t n)
{
@@ -521,9 +536,15 @@ class basic_string
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_string(const detail::moved_object<basic_string>& s)
: base_t(move((base_t&)s.get()))
{}
#else
basic_string(basic_string && s)
: base_t(move((base_t&)s))
{}
#endif
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by a specific number of characters of the s string.
@@ -571,7 +592,7 @@ class basic_string
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InputIterator>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_initialize_dispatch(f, l, Result());
}
@@ -600,6 +621,7 @@ class basic_string
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_string& operator=(const detail::moved_object<basic_string>& ms)
{
basic_string &s = ms.get();
@@ -608,6 +630,16 @@ class basic_string
}
return *this;
}
#else
basic_string& operator=(basic_string && ms)
{
basic_string &s = ms;
if (&s != this){
this->swap(s);
}
return *this;
}
#endif
//! <b>Effects</b>: Assignment from a null-terminated c-string.
basic_string& operator=(const CharT* s)
@@ -759,7 +791,7 @@ class basic_string
size_type new_length = 0;
new_length += priv_uninitialized_copy
(this->priv_addr(), this->priv_addr() + this->priv_size(), new_start, this->get_alloc());
(this->priv_addr(), this->priv_addr() + this->priv_size(), new_start);
this->priv_construct_null(new_start + new_length);
this->deallocate_block();
this->is_short(false);
@@ -917,8 +949,13 @@ class basic_string
{ return this->operator=(s); }
//! <b>Effects</b>: Moves the resources from ms *this.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_string& assign(const detail::moved_object<basic_string>& ms)
{ return this->operator=(ms);}
#else
basic_string& assign(basic_string && ms)
{ return this->operator=(ms);}
#endif
//! <b>Effects</b>: Assigns the range [pos, pos + n) from s to *this.
basic_string& assign(const basic_string& s,
@@ -947,7 +984,7 @@ class basic_string
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InputIter>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
return this->priv_assign_dispatch(first, last, Result());
}
@@ -1048,7 +1085,7 @@ class basic_string
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InputIter>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_insert_dispatch(p, first, last, Result());
}
@@ -1191,7 +1228,7 @@ class basic_string
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<iterator>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
return this->priv_replace_dispatch(first, last, f, l, Result());
}
@@ -1210,8 +1247,13 @@ class basic_string
{ base_t::swap(s); }
//! <b>Effects</b>: Swaps the contents of two strings.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<basic_string>& ms)
{ this->swap(ms.get()); }
#else
void swap(basic_string && ms)
{ this->swap(ms); }
#endif
//! <b>Returns</b>: Returns a pointer to a null-terminated array of characters
//! representing the string's contents. For any string s it is guaranteed
@@ -1564,7 +1606,7 @@ class basic_string
{
difference_type n = std::distance(f, l);
this->allocate_initial_block(max_value<difference_type>(n+1, InternalBufferChars));
priv_uninitialized_copy(f, l, this->priv_addr(), this->get_alloc());
priv_uninitialized_copy(f, l, this->priv_addr());
this->priv_size(n);
this->priv_terminate_string();
}
@@ -1577,21 +1619,20 @@ class basic_string
}
template <class Integer>
void priv_initialize_dispatch(Integer n, Integer x, boost::mpl::true_)
void priv_initialize_dispatch(Integer n, Integer x, true_)
{
this->allocate_initial_block(max_value<difference_type>(n+1, InternalBufferChars));
priv_uninitialized_fill_n(this->priv_addr(), n, x, this->get_alloc());
priv_uninitialized_fill_n(this->priv_addr(), n, x);
this->priv_size(n);
this->priv_terminate_string();
}
template <class InputIter>
void priv_initialize_dispatch(InputIter f, InputIter l, boost::mpl::false_)
void priv_initialize_dispatch(InputIter f, InputIter l, false_)
{ this->priv_range_initialize(f, l); }
template<class FwdIt, class Count, class Alloc> inline
void priv_uninitialized_fill_n(FwdIt first, Count count,
const CharT val, Alloc& al)
template<class FwdIt, class Count> inline
void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val)
{
//Save initial position
FwdIt init = first;
@@ -1599,22 +1640,21 @@ class basic_string
BOOST_TRY{
//Construct objects
for (; count--; ++first){
al.construct(first, val);
this->construct(first, val);
}
}
BOOST_CATCH(...){
//Call destructors
for (; init != first; ++init){
al.destroy(init);
this->destroy(init);
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
template<class InpIt, class FwdIt, class Alloc> inline
size_type priv_uninitialized_copy(InpIt first, InpIt last,
FwdIt dest, Alloc& al)
template<class InpIt, class FwdIt> inline
size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest)
{
//Save initial destination position
FwdIt dest_init = dest;
@@ -1623,13 +1663,13 @@ class basic_string
BOOST_TRY{
//Try to build objects
for (; first != last; ++dest, ++first, ++constructed){
al.construct(dest, *first);
this->construct(dest, *first);
}
}
BOOST_CATCH(...){
//Call destructors
for (; constructed--; ++dest_init){
al.destroy(dest_init);
this->destroy(dest_init);
}
BOOST_RETHROW;
}
@@ -1638,12 +1678,12 @@ class basic_string
}
template <class Integer>
basic_string& priv_assign_dispatch(Integer n, Integer x, boost::mpl::true_)
basic_string& priv_assign_dispatch(Integer n, Integer x, true_)
{ return this->assign((size_type) n, (CharT) x); }
template <class InputIter>
basic_string& priv_assign_dispatch(InputIter f, InputIter l,
boost::mpl::false_)
false_)
{
size_type cur = 0;
CharT *ptr = detail::get_pointer(this->priv_addr());
@@ -1707,8 +1747,7 @@ class basic_string
if (elems_after >= n) {
pointer pointer_past_last = this->priv_addr() + this->priv_size() + 1;
priv_uninitialized_copy(this->priv_addr() + (this->priv_size() - n + 1),
pointer_past_last,
pointer_past_last, *this);
pointer_past_last, pointer_past_last);
this->priv_size(this->priv_size()+n);
Traits::move(detail::get_pointer(position + n),
@@ -1720,11 +1759,11 @@ class basic_string
ForwardIter mid = first;
std::advance(mid, elems_after + 1);
priv_uninitialized_copy(mid, last, this->priv_addr() + this->priv_size() + 1, *this);
priv_uninitialized_copy(mid, last, this->priv_addr() + this->priv_size() + 1);
this->priv_size(this->priv_size() + (n - elems_after));
priv_uninitialized_copy
(position, this->priv_addr() + old_length + 1,
this->priv_addr() + this->priv_size(), *this);
this->priv_addr() + this->priv_size());
this->priv_size(this->priv_size() + elems_after);
this->priv_copy(first, mid, position);
}
@@ -1736,12 +1775,12 @@ class basic_string
size_type new_length = 0;
//This can't throw, since characters are POD
new_length += priv_uninitialized_copy
(this->priv_addr(), position, new_start, *this);
(this->priv_addr(), position, new_start);
new_length += priv_uninitialized_copy
(first, last, new_start + new_length, *this);
(first, last, new_start + new_length);
new_length += priv_uninitialized_copy
(position, this->priv_addr() + this->priv_size(),
new_start + new_length, *this);
new_start + new_length);
this->priv_construct_null(new_start + new_length);
this->deallocate_block();
@@ -1762,7 +1801,7 @@ class basic_string
Traits::move(newbuf, oldbuf, before);
Traits::move(newbuf + before + n, pos, old_size - before);
//Now initialize the new data
priv_uninitialized_copy(first, last, new_start + before, *this);
priv_uninitialized_copy(first, last, new_start + before);
this->priv_construct_null(new_start + (old_size + n));
this->is_short(false);
this->priv_addr(new_start);
@@ -1775,12 +1814,12 @@ class basic_string
template <class Integer>
void priv_insert_dispatch(iterator p, Integer n, Integer x,
boost::mpl::true_)
true_)
{ insert(p, (size_type) n, (CharT) x); }
template <class InputIter>
void priv_insert_dispatch(iterator p, InputIter first, InputIter last,
boost::mpl::false_)
false_)
{
typedef typename std::iterator_traits<InputIter>::iterator_category Category;
priv_insert(p, first, last, Category());
@@ -1799,13 +1838,13 @@ class basic_string
template <class Integer>
basic_string& priv_replace_dispatch(iterator first, iterator last,
Integer n, Integer x,
boost::mpl::true_)
true_)
{ return this->replace(first, last, (size_type) n, (CharT) x); }
template <class InputIter>
basic_string& priv_replace_dispatch(iterator first, iterator last,
InputIter f, InputIter l,
boost::mpl::false_)
false_)
{
typedef typename std::iterator_traits<InputIter>::iterator_category Category;
return this->priv_replace(first, last, f, l, Category());
@@ -1872,6 +1911,7 @@ operator+(const basic_string<CharT,Traits,A>& x,
return result;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline detail::moved_object<basic_string<CharT,Traits,A> >
operator+(const detail::moved_object<basic_string<CharT,Traits,A> >& mx,
@@ -1880,15 +1920,36 @@ operator+(const detail::moved_object<basic_string<CharT,Traits,A> >& mx,
mx.get() += y;
return mx;
}
#else
template <class CharT, class Traits, class A>
basic_string<CharT,Traits,A> &&
operator+(basic_string<CharT,Traits,A> && mx,
const basic_string<CharT,Traits,A>& y)
{
mx += y;
return move(mx);
}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline detail::moved_object<basic_string<CharT,Traits,A> >
operator+(const basic_string<CharT,Traits,A>& x,
const detail::moved_object<basic_string<CharT,Traits,A> >& my)
{
my.get() += x;
return my;
typedef typename basic_string<CharT,Traits,A>::size_type size_type;
return my.get().replace(size_type(0), size_type(0), x);
}
#else
template <class CharT, class Traits, class A>
inline basic_string<CharT,Traits,A> &&
operator+(const basic_string<CharT,Traits,A>& x,
basic_string<CharT,Traits,A> && my)
{
typedef typename basic_string<CharT,Traits,A>::size_type size_type;
return my.replace(size_type(0), size_type(0), x);
}
#endif
template <class CharT, class Traits, class A>
inline basic_string<CharT,Traits,A>
@@ -1904,6 +1965,26 @@ operator+(const CharT* s, const basic_string<CharT,Traits,A>& y)
return result;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline detail::moved_object<basic_string<CharT,Traits,A> >
operator+(const CharT* s,
const detail::moved_object<basic_string<CharT,Traits,A> >& my)
{
typedef typename basic_string<CharT,Traits,A>::size_type size_type;
return my.get().replace(size_type(0), size_type(0), s);
}
#else
template <class CharT, class Traits, class A>
inline basic_string<CharT,Traits,A> &&
operator+(const CharT* s,
basic_string<CharT,Traits,A> && my)
{
typedef typename basic_string<CharT,Traits,A>::size_type size_type;
return move(my.get().replace(size_type(0), size_type(0), s));
}
#endif
template <class CharT, class Traits, class A>
inline basic_string<CharT,Traits,A>
operator+(CharT c, const basic_string<CharT,Traits,A>& y)
@@ -1917,6 +1998,26 @@ operator+(CharT c, const basic_string<CharT,Traits,A>& y)
return result;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline detail::moved_object<basic_string<CharT,Traits,A> >
operator+(CharT c,
const detail::moved_object<basic_string<CharT,Traits,A> >& my)
{
typedef typename basic_string<CharT,Traits,A>::size_type size_type;
return my.get().replace(size_type(0), size_type(0), &c, &c + 1);
}
#else
template <class CharT, class Traits, class A>
inline basic_string<CharT,Traits,A> &&
operator+(CharT c,
basic_string<CharT,Traits,A> && my)
{
typedef typename basic_string<CharT,Traits,A>::size_type size_type;
return my.replace(size_type(0), size_type(0), &c, &c + 1);
}
#endif
template <class CharT, class Traits, class A>
inline basic_string<CharT,Traits,A>
operator+(const basic_string<CharT,Traits,A>& x, const CharT* s)
@@ -1931,6 +2032,26 @@ operator+(const basic_string<CharT,Traits,A>& x, const CharT* s)
return result;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline detail::moved_object<basic_string<CharT,Traits,A> >
operator+(const detail::moved_object<basic_string<CharT,Traits,A> >& mx,
const CharT* s)
{
mx.get() += s;
return mx;
}
#else
template <class CharT, class Traits, class A>
basic_string<CharT,Traits,A> &&
operator+(basic_string<CharT,Traits,A> && mx,
const CharT* s)
{
mx += s;
return move(mx);
}
#endif
template <class CharT, class Traits, class A>
inline basic_string<CharT,Traits,A>
operator+(const basic_string<CharT,Traits,A>& x, const CharT c)
@@ -1944,6 +2065,25 @@ operator+(const basic_string<CharT,Traits,A>& x, const CharT c)
return result;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline detail::moved_object<basic_string<CharT,Traits,A> >
operator+(const detail::moved_object<basic_string<CharT,Traits,A> >& mx,
const CharT c)
{
mx.get() += c;
return mx;
}
#else
template <class CharT, class Traits, class A>
basic_string<CharT,Traits,A> &&
operator+(basic_string<CharT,Traits,A> && mx, const CharT c)
{
mx += c;
return move(mx);
}
#endif
// Operator== and operator!=
template <class CharT, class Traits, class A>
@@ -2076,7 +2216,7 @@ operator>=(const basic_string<CharT,Traits,A>& x, const CharT* s)
{ return !(x < s); }
// Swap.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline void swap(basic_string<CharT,Traits,A>& x,
basic_string<CharT,Traits,A>& y)
@@ -2091,7 +2231,12 @@ template <class CharT, class Traits, class A>
inline void swap(basic_string<CharT,Traits,A>& x,
const detail::moved_object<basic_string<CharT,Traits,A> >& my)
{ x.swap(my.get()); }
#else
template <class CharT, class Traits, class A>
inline void swap(basic_string<CharT,Traits,A> && x,
basic_string<CharT,Traits,A> &&y)
{ x.swap(y); }
#endif
/// @cond
// I/O.
@@ -2118,7 +2263,11 @@ interprocess_string_fill(std::basic_ostream<CharT, Traits>& os,
template <class CharT, class Traits, class A>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
const basic_string<CharT,Traits,A>& s)
#else
const basic_string<CharT,Traits,A>&&s)
#endif
{
typename std::basic_ostream<CharT, Traits>::sentry sentry(os);
bool ok = false;
@@ -2150,16 +2299,23 @@ operator<<(std::basic_ostream<CharT, Traits>& os,
return os;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const detail::moved_object<basic_string<CharT,Traits,A> >& ms)
{ return os << ms.get(); }
#endif
template <class CharT, class Traits, class A>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is,
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_string<CharT,Traits,A>& s)
#else
basic_string<CharT,Traits,A>&&s)
#endif
{
typename std::basic_istream<CharT, Traits>::sentry sentry(is);
@@ -2204,16 +2360,22 @@ operator>>(std::basic_istream<CharT, Traits>& is,
return is;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is,
const detail::moved_object<basic_string<CharT,Traits,A> >& ms)
{ return is >> ms.get(); }
#endif
template <class CharT, class Traits, class A>
std::basic_istream<CharT, Traits>&
getline(std::istream& is,
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_string<CharT,Traits,A>& s,
#else
basic_string<CharT,Traits,A>&&s,
#endif
CharT delim)
{
std::size_t nread = 0;
@@ -2245,6 +2407,16 @@ getline(std::istream& is,
return is;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
std::basic_istream<CharT, Traits>&
getline(std::istream& is,
const detail::moved_object<basic_string<CharT,Traits,A> >& ms,
CharT delim)
{ return getline(is, ms.get(), delim); }
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class CharT, class Traits, class A>
inline std::basic_istream<CharT, Traits>&
getline(std::basic_istream<CharT, Traits>& is,
@@ -2256,15 +2428,15 @@ getline(std::basic_istream<CharT, Traits>& is,
template <class CharT, class Traits, class A>
std::basic_istream<CharT, Traits>&
getline(std::istream& is,
const detail::moved_object<basic_string<CharT,Traits,A> >& ms,
CharT delim)
{ return getline(is, ms.get(), delim); }
const detail::moved_object<basic_string<CharT,Traits,A> >& ms)
{ return getline(is, ms.get()); }
#else
template <class CharT, class Traits, class A>
std::basic_istream<CharT, Traits>&
getline(std::istream& is,
const detail::moved_object<basic_string<CharT,Traits,A> >& ms)
{ return getline(is, ms.get()); }
basic_string<CharT,Traits,A> && ms)
{ return getline(is, ms); }
#endif
template <class Ch, class A>
inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, A> const& v)

View File

@@ -45,27 +45,31 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/interprocess/detail/move_iterator.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <cstddef>
#include <memory>
#include <algorithm>
#include <stdexcept>
#include <iterator>
#include <utility>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/algorithms.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/move_iterator.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/mpl.hpp>
namespace boost {
namespace interprocess {
@@ -81,7 +85,9 @@ struct vector_alloc_holder
typedef typename A::size_type size_type;
typedef typename A::value_type value_type;
enum { trivial_dctr_after_move = has_trivial_destructor_after_move<value_type>::value };
enum { trivial_dctr_after_move =
has_trivial_destructor_after_move<value_type>::value ||
boost::has_trivial_destructor<value_type>::value };
//Constructor, does not throw
vector_alloc_holder(const A &a)
@@ -94,9 +100,15 @@ struct vector_alloc_holder
{}
//Constructor, does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
vector_alloc_holder(const detail::moved_object<vector_alloc_holder<A> > &h)
: A(move((A&)h.get())), m_start(0), m_size(0), m_capacity(0)
{}
#else
vector_alloc_holder(vector_alloc_holder<A> &&h)
: A(move((A&)h)), m_start(0), m_size(0), m_capacity(0)
{}
#endif
//Destructor
~vector_alloc_holder()
@@ -165,13 +177,13 @@ struct vector_alloc_holder
void destroy(pointer p)
{
if(!has_trivial_destructor<value_type>::value)
A::destroy(p);
detail::get_pointer(p)->~value_type();
}
void destroy_n(pointer p, size_type n)
{
if(!has_trivial_destructor<value_type>::value)
for(; n--; ++p) this->destroy(p);
for(; n--; ++p) detail::get_pointer(p)->~value_type();
}
};
@@ -409,6 +421,7 @@ class vector : private detail::vector_alloc_holder<A>
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
vector(const detail::moved_object<vector<T, A> >& mx)
: base_t(move((base_t&)mx.get()))
{
@@ -420,6 +433,19 @@ class vector : private detail::vector_alloc_holder<A>
x.m_size = 0;
x.m_capacity = 0;
}
#else
vector(vector<T, A> && mx)
: base_t(move((base_t&)mx))
{
vector<T, A> &x = mx;
this->m_start = x.m_start;
this->m_size = x.m_size;
this->m_capacity = x.m_capacity;
x.m_start = 0;
x.m_size = 0;
x.m_capacity = 0;
}
#endif
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
//! and inserts a copy of the range [first, last) in the vector.
@@ -651,15 +677,16 @@ class vector : private detail::vector_alloc_holder<A>
//There is not enough memory, allocate a new
//buffer or expand the old one.
bool same_buffer_start;
size_type real_cap;
std::pair<pointer, bool> ret =
this->allocation_command
(allocate_new | expand_fwd | expand_bwd,
new_cap, new_cap, new_cap, this->m_start);
new_cap, new_cap, real_cap, this->m_start);
//Check for forward expansion
same_buffer_start = ret.second && this->m_start == ret.first;
if(same_buffer_start){
this->m_capacity = new_cap;
this->m_capacity = real_cap;
}
//If there is no forward expansion, move objects
@@ -669,12 +696,12 @@ class vector : private detail::vector_alloc_holder<A>
//Backwards (and possibly forward) expansion
if(ret.second){
this->priv_range_insert_expand_backwards
(ret.first, new_cap, this->m_start, dummy_it, dummy_it, 0);
(ret.first, real_cap, this->m_start, dummy_it, dummy_it, 0);
}
//New buffer
else{
this->priv_range_insert_new_allocation
(ret.first, new_cap, this->m_start, dummy_it, dummy_it);
(ret.first, real_cap, this->m_start, dummy_it, dummy_it);
}
}
}
@@ -704,6 +731,7 @@ class vector : private detail::vector_alloc_holder<A>
//! <b>Throws</b>: If allocator_type's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
vector<T, A>& operator=(const detail::moved_object<vector<T, A> >& mx)
{
vector<T, A> &x = mx.get();
@@ -715,6 +743,19 @@ class vector : private detail::vector_alloc_holder<A>
}
return *this;
}
#else
vector<T, A>& operator=(vector<T, A> && mx)
{
vector<T, A> &x = mx;
if (&x != this){
this->swap(x);
x.clear();
//? base_t::prot_deallocate();
}
return *this;
}
#endif
//! <b>Effects</b>: Assigns the n copies of val to *this.
//!
@@ -735,7 +776,7 @@ class vector : private detail::vector_alloc_holder<A>
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
}
@@ -749,7 +790,7 @@ class vector : private detail::vector_alloc_holder<A>
{
if (this->m_size < this->m_capacity){
//There is more memory, just construct a new object at the end
this->construct(this->m_start + this->m_size, x);
new(detail::get_pointer(this->m_start) + this->m_size)value_type(x);
++this->m_size;
}
else{
@@ -763,18 +804,32 @@ class vector : private detail::vector_alloc_holder<A>
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_back(const detail::moved_object<T> & mx)
{
if (this->m_size < this->m_capacity){
//There is more memory, just construct a new object at the end
this->construct(this->m_start + this->m_size, mx);
new(detail::get_pointer(this->m_start + this->m_size))value_type(mx);
++this->m_size;
}
else{
this->insert(this->end(), mx);
}
}
#else
void push_back(T && mx)
{
if (this->m_size < this->m_capacity){
//There is more memory, just construct a new object at the end
new(detail::get_pointer(this->m_start + this->m_size))value_type(move(mx));
++this->m_size;
}
else{
this->insert(this->end(), move(mx));
}
}
#endif
//! <b>Effects</b>: Swaps the contents of *this and x.
//! If this->allocator_type() != x.allocator_type()
//! allocators are also swapped.
@@ -802,11 +857,19 @@ class vector : private detail::vector_alloc_holder<A>
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<vector<T, A> >& mx)
{
vector<T, A> &x = mx.get();
this->swap(x);
}
#else
void swap(vector<T, A> && mx)
{
vector<T, A> &x = mx;
this->swap(x);
}
#endif
//! <b>Requires</b>: position must be a valid iterator of *this.
//!
@@ -832,6 +895,7 @@ class vector : private detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: If position is begin() or end(), amortized constant time
//! Linear time otherwise.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(iterator position, const detail::moved_object<T> &mx)
{
typedef repeat_iterator<T, difference_type> r_iterator;
@@ -843,6 +907,19 @@ class vector : private detail::vector_alloc_holder<A>
,move_it(r_iterator()));
return iterator(this->m_start + n);
}
#else
iterator insert(iterator position, T &&mx)
{
typedef repeat_iterator<T, difference_type> r_iterator;
typedef detail::move_iterator<r_iterator> move_it;
//Just call more general insert(pos, size, value) and return iterator
size_type n = position - begin();
this->insert(position
,move_it(r_iterator(mx, 1))
,move_it(r_iterator()));
return iterator(this->m_start + n);
}
#endif
//! <b>Requires</b>: pos must be a valid iterator of *this.
//!
@@ -857,7 +934,7 @@ class vector : private detail::vector_alloc_holder<A>
{
//Dispatch depending on integer/iterator
const bool aux_boolean = boost::is_integral<InIt>::value;
typedef boost::mpl::bool_<aux_boolean> Result;
typedef bool_<aux_boolean> Result;
this->priv_insert_dispatch(pos, first, last, Result());
}
@@ -999,7 +1076,7 @@ class vector : private detail::vector_alloc_holder<A>
size_type remaining = this->m_capacity - this->m_size;
bool same_buffer_start;
std::pair<pointer, bool> ret;
size_type new_cap;
size_type real_cap = this->m_capacity;
//Check if we already have room
if (n <= remaining){
@@ -1008,15 +1085,15 @@ class vector : private detail::vector_alloc_holder<A>
else{
//There is not enough memory, allocate a new
//buffer or expand the old one.
new_cap = this->next_capacity(n);
size_type new_cap = this->next_capacity(n);
ret = this->allocation_command
(allocate_new | expand_fwd | expand_bwd,
this->m_size + n, new_cap, new_cap, this->m_start);
this->m_size + n, new_cap, real_cap, this->m_start);
//Check for forward expansion
same_buffer_start = ret.second && this->m_start == ret.first;
if(same_buffer_start){
this->m_capacity = new_cap;
this->m_capacity = real_cap;
}
}
@@ -1028,12 +1105,12 @@ class vector : private detail::vector_alloc_holder<A>
//Backwards (and possibly forward) expansion
else if(ret.second){
this->priv_range_insert_expand_backwards
(ret.first, new_cap, pos, first, last, n);
(ret.first, real_cap, pos, first, last, n);
}
//New buffer
else{
this->priv_range_insert_new_allocation
(ret.first, new_cap, pos, first, last);
(ret.first, real_cap, pos, first, last);
}
}
}
@@ -1050,8 +1127,8 @@ class vector : private detail::vector_alloc_holder<A>
if (elems_after > n){
//New elements can be just copied.
//Move to uninitialized memory last objects
n_uninitialized_copy(move_it(old_finish - n), move_it(old_finish),
old_finish, static_cast<A&>(*this));
boost::interprocess::n_uninitialized_copy
(move_it(old_finish - n), move_it(old_finish), old_finish);
this->m_size += n;
//Copy previous to last objects to the initialized end
std::copy_backward(move_it(pos), move_it(old_finish - n), old_finish);
@@ -1063,11 +1140,11 @@ class vector : private detail::vector_alloc_holder<A>
//to the beginning of the unallocated zone the last new elements.
FwdIt mid = first;
std::advance(mid, elems_after);
n_uninitialized_copy(mid, last, old_finish, static_cast<A&>(*this));
boost::interprocess::n_uninitialized_copy(mid, last, old_finish);
this->m_size += n - elems_after;
//Copy old [pos, end()) elements to the uninitialized memory
n_uninitialized_copy(move_it(pos), move_it(old_finish),
this->m_start + this->m_size, static_cast<A&>(*this));
boost::interprocess::n_uninitialized_copy
(move_it(pos), move_it(old_finish), this->m_start + this->m_size);
this->m_size += elems_after;
//Copy first new elements in pos
std::copy(first, mid, pos);
@@ -1080,20 +1157,20 @@ class vector : private detail::vector_alloc_holder<A>
{
typedef detail::move_iterator<pointer> move_it;
//Anti-exception rollback
scoped_ptr<T, dealloc_t> scoped_alloc(new_start, dealloc_t(*this, new_cap));
dealloc_t scoped_alloc(new_start, *this, new_cap);
pointer new_finish = new_start;
BOOST_TRY{
//Initialize with [begin(), pos) old buffer
//the start of the new buffer
new_finish += n_uninitialized_copy
(move_it(this->m_start), move_it(pos), new_start, static_cast<A&>(*this));
new_finish += boost::interprocess::n_uninitialized_copy
(move_it(this->m_start), move_it(pos), new_start);
//Initialize new objects, starting from previous point
new_finish += n_uninitialized_copy
(first, last, new_finish, static_cast<A&>(*this));
new_finish += boost::interprocess::n_uninitialized_copy
(first, last, new_finish);
//Initialize from the rest of the old buffer,
//starting from previous point
new_finish += n_uninitialized_copy
(move_it(pos), move_it(this->m_start + this->m_size), new_finish, static_cast<A&>(*this));
new_finish += boost::interprocess::n_uninitialized_copy
(move_it(pos), move_it(this->m_start + this->m_size), new_finish);
}
BOOST_CATCH(...){
this->destroy_n(new_start, new_finish - new_start);
@@ -1101,10 +1178,13 @@ class vector : private detail::vector_alloc_holder<A>
}
BOOST_CATCH_END
scoped_alloc.release();
//Destroy and deallocate old elements except if we have
//moved them and they have has_trivial_destructor_after_move
if(!base_t::trivial_dctr_after_move)
this->priv_destroy_and_deallocate();
//Destroy and deallocate old elements
//If there is allocated memory, destroy and deallocate
if(this->m_start != 0){
if(!base_t::trivial_dctr_after_move)
this->destroy_n(this->m_start, this->m_size);
this->deallocate(this->m_start, this->m_capacity);
}
this->m_start = new_start;
this->m_size = new_finish - new_start;
this->m_capacity = new_cap;
@@ -1115,8 +1195,7 @@ class vector : private detail::vector_alloc_holder<A>
(pointer new_start, size_type new_capacity,
pointer pos, FwdIt first, FwdIt last, size_type n)
{
typedef detail::scoped_destructor_n
<allocator_type> ValueArrayDestructor;
typedef detail::scoped_destructor_n<pointer> ValueArrayDestructor;
typedef detail::move_iterator<pointer> move_it;
//Backup old data
pointer old_start = this->m_start;
@@ -1134,9 +1213,7 @@ class vector : private detail::vector_alloc_holder<A>
//If anything goes wrong, this object will destroy
//all the old objects to fulfill previous vector state
scoped_ptr<value_type, ValueArrayDestructor>
old_values_destroyer
(old_start, ValueArrayDestructor(static_cast<A&>(*this),old_size));
ValueArrayDestructor old_values_destroyer(old_start, old_size);
//Check if s_before is so big that even copying the old data + new data
//there is a gap between the new data and the old data
@@ -1153,15 +1230,12 @@ class vector : private detail::vector_alloc_holder<A>
//
//Copy first old values before pos, after that the
//new objects
uninitialized_copy_copy
(move_it(old_start), move_it(pos), first, last, new_start, static_cast<A&>(*this));
scoped_ptr<value_type, ValueArrayDestructor>
new_values_destroyer(new_start
,ValueArrayDestructor(static_cast<A&>(*this)
,elemsbefore));
boost::interprocess::uninitialized_copy_copy
(move_it(old_start), move_it(pos), first, last, new_start);
ValueArrayDestructor new_values_destroyer(new_start, elemsbefore);
//Now initialize the rest of memory with the last old values
uninitialized_copy(move_it(pos), move_it(old_finish)
,new_start + elemsbefore + n, static_cast<A&>(*this));
boost::interprocess::uninitialized_copy(move_it(pos), move_it(old_finish)
,new_start + elemsbefore + n);
//All new elements correctly constructed, avoid new element destruction
new_values_destroyer.release();
this->m_size = old_size + n;
@@ -1185,17 +1259,14 @@ class vector : private detail::vector_alloc_holder<A>
//
//Copy first old values before pos, after that the
//new objects
uninitialized_copy_copy
(move_it(old_start), move_it(pos), first, last, new_start, static_cast<A&>(*this));
scoped_ptr<value_type, ValueArrayDestructor>
new_values_destroyer(new_start
,ValueArrayDestructor(static_cast<A&>(*this)
,elemsbefore));
boost::interprocess::uninitialized_copy_copy
(move_it(old_start), move_it(pos), first, last, new_start);
ValueArrayDestructor new_values_destroyer(new_start, elemsbefore);
size_type raw_gap = s_before - (elemsbefore + n);
//Now initialize the rest of s_before memory with the
//first of elements after new values
uninitialized_copy(move_it(pos), move_it(pos + raw_gap)
,new_start + elemsbefore + n, static_cast<A&>(*this));
boost::interprocess::uninitialized_copy
(move_it(pos), move_it(pos + raw_gap), new_start + elemsbefore + n);
//All new elements correctly constructed, avoid new element destruction
new_values_destroyer.release();
//All new elements correctly constructed, avoid old element destruction
@@ -1269,7 +1340,8 @@ class vector : private detail::vector_alloc_holder<A>
//
//Copy the first part of old_begin to raw_mem
pointer start_n = old_start + difference_type(s_before);
uninitialized_copy(move_it(old_start), move_it(start_n), new_start, static_cast<A&>(*this));
boost::interprocess::uninitialized_copy
(move_it(old_start), move_it(start_n), new_start);
//The buffer is all constructed until old_end,
//release destroyer and update size
old_values_destroyer.release();
@@ -1319,8 +1391,8 @@ class vector : private detail::vector_alloc_holder<A>
FwdIt mid = first;
size_type n_new_init = difference_type(s_before) - elemsbefore;
std::advance(mid, n_new_init);
uninitialized_copy_copy
(move_it(old_start), move_it(pos), first, mid, new_start, static_cast<A&>(*this));
boost::interprocess::uninitialized_copy_copy
(move_it(old_start), move_it(pos), first, mid, new_start);
//The buffer is all constructed until old_end,
//release destroyer and update size
old_values_destroyer.release();
@@ -1388,8 +1460,8 @@ class vector : private detail::vector_alloc_holder<A>
//
//First copy the part of old_end raw_mem
pointer finish_n = old_finish - difference_type(n_after);
uninitialized_copy(move_it(finish_n), move_it(old_finish)
,old_finish, static_cast<A&>(*this));
boost::interprocess::uninitialized_copy
(move_it(finish_n), move_it(old_finish), old_finish);
this->m_size += n_after;
//Displace the rest of old_end to the new position
std::copy_backward(move_it(pos), move_it(finish_n), old_finish);
@@ -1412,9 +1484,8 @@ class vector : private detail::vector_alloc_holder<A>
FwdIt mid = first;
std::advance(mid, elemsafter);
//First initialize data in raw memory
uninitialized_copy_copy
(mid, last, move_it(pos), move_it(old_finish),
old_finish, static_cast<A&>(*this));
boost::interprocess::uninitialized_copy_copy
(mid, last, move_it(pos), move_it(old_finish), old_finish);
this->m_size += n_after;
//Now copy the part of new_end over constructed elements
std::copy(first, mid, pos);
@@ -1461,20 +1532,20 @@ class vector : private detail::vector_alloc_holder<A>
size_type remaining = this->m_capacity - this->m_size;
bool same_buffer_start;
std::pair<pointer, bool> ret;
size_type new_cap;
size_type real_cap = this->m_capacity;
if (n <= remaining){
same_buffer_start = true;
}
else{
//There is not enough memory, allocate a new buffer
new_cap = this->next_capacity(n);
size_type new_cap = this->next_capacity(n);
ret = this->allocation_command
(allocate_new | expand_fwd | expand_bwd,
this->size() + n, new_cap, new_cap, this->m_start);
this->size() + n, new_cap, real_cap, this->m_start);
same_buffer_start = ret.second && this->m_start == ret.first;
if(same_buffer_start){
this->m_capacity = new_cap;
this->m_capacity = real_cap;
}
}
@@ -1494,43 +1565,42 @@ class vector : private detail::vector_alloc_holder<A>
std::advance(mid, this->size());
std::copy(first, mid, this->m_start);
//Initialize the remaining new elements in the uninitialized memory
n_uninitialized_copy(mid, last, this->m_start + this->m_size, static_cast<A&>(*this));
boost::interprocess::n_uninitialized_copy
(mid, last, this->m_start + this->m_size);
this->m_size = n;
}
}
else if(!ret.second){
scoped_ptr<T, dealloc_t> scoped_alloc(ret.first, dealloc_t(*this, new_cap));
n_uninitialized_copy(first, last, ret.first, static_cast<A&>(*this));
dealloc_t scoped_alloc(ret.first, *this, real_cap);
boost::interprocess::n_uninitialized_copy(first, last, ret.first);
scoped_alloc.release();
//Destroy and deallocate old buffer
this->priv_destroy_and_deallocate();
if(this->m_start != 0){
this->destroy_n(this->m_start, this->m_size);
this->deallocate(this->m_start, this->m_capacity);
}
this->m_start = ret.first;
this->m_size = n;
this->m_capacity = new_cap;
this->m_capacity = real_cap;
}
else{
//Backwards expansion
//If anything goes wrong, this object will destroy
//all old objects
typedef detail::scoped_destructor_n
<allocator_type> ValueArrayDestructor;
typedef detail::scoped_destructor_n<pointer> ValueArrayDestructor;
pointer old_start = this->m_start;
size_type old_size = this->m_size;
scoped_ptr<value_type, ValueArrayDestructor>
old_values_destroyer(old_start
,ValueArrayDestructor(static_cast<A&>(*this)
,old_size));
ValueArrayDestructor old_values_destroyer(old_start, old_size);
//If something goes wrong size will be 0
//but holding the whole buffer
this->m_size = 0;
this->m_start = ret.first;
this->m_capacity = new_cap;
this->m_capacity = real_cap;
//Backup old buffer data
size_type old_offset = old_start - ret.first;
size_type first_count = min_value(n, old_offset);
FwdIt mid = n_uninitialized_copy_n
(first, first_count, ret.first, static_cast<A&>(*this));
FwdIt mid = boost::interprocess::n_uninitialized_copy_n(first, first_count, ret.first);
if(old_offset > n){
//All old elements will be destroyed by "old_values_destroyer"
@@ -1549,8 +1619,8 @@ class vector : private detail::vector_alloc_holder<A>
//Check if we still have to append elements in the
//uninitialized end
if(second_count == old_size){
n_uninitialized_copy_n(mid, n - first_count - second_count
, old_start + old_size, static_cast<A&>(*this));
boost::interprocess::n_uninitialized_copy_n
(mid, n - first_count - second_count, old_start + old_size);
}
else{
//We have to destroy some old values
@@ -1564,12 +1634,12 @@ class vector : private detail::vector_alloc_holder<A>
}
template <class Integer>
void priv_assign_dispatch(Integer n, Integer val, boost::mpl::true_)
void priv_assign_dispatch(Integer n, Integer val, true_)
{ this->assign((size_type) n, (T) val); }
template <class InIt>
void priv_assign_dispatch(InIt first, InIt last,
boost::mpl::false_)
false_)
{
//Dispatch depending on integer/iterator
typedef typename
@@ -1579,12 +1649,12 @@ class vector : private detail::vector_alloc_holder<A>
template <class Integer>
void priv_insert_dispatch( iterator pos, Integer n,
Integer val, boost::mpl::true_)
Integer val, true_)
{ this->insert(pos, (size_type)n, (T)val); }
template <class InIt>
void priv_insert_dispatch(iterator pos, InIt first,
InIt last, boost::mpl::false_)
InIt last, false_)
{
//Dispatch depending on integer/iterator
typedef typename
@@ -1593,7 +1663,7 @@ class vector : private detail::vector_alloc_holder<A>
}
template <class Integer>
void priv_initialize_aux(Integer n, Integer value, boost::mpl::true_)
void priv_initialize_aux(Integer n, Integer value, true_)
{
this->priv_range_initialize(cvalue_iterator(value, n),
cvalue_iterator(),
@@ -1602,7 +1672,7 @@ class vector : private detail::vector_alloc_holder<A>
template <class InIt>
void priv_initialize_aux(InIt first, InIt last,
boost::mpl::false_)
false_)
{
//Dispatch depending on integer/iterator
typedef typename
@@ -1610,23 +1680,14 @@ class vector : private detail::vector_alloc_holder<A>
this->priv_range_initialize(first, last, ItCat());
}
void priv_destroy_and_deallocate()
{
//If there is allocated memory, destroy and deallocate
if(this->m_start != 0){
this->destroy_n(this->m_start, this->m_size);
this->deallocate(this->m_start, this->m_capacity);
}
}
template <class FwdIt>
pointer priv_reserve_and_copy(size_type n, size_type &cap
,FwdIt first, FwdIt last)
{
//Allocate n element buffer and initialize from range
pointer result = this->allocation_command(allocate_new, n, n, cap).first;
scoped_ptr<T, dealloc_t> scoped_alloc(result, dealloc_t(*this, cap));
n_uninitialized_copy(first, last, result, static_cast<A&>(*this));
dealloc_t scoped_alloc(result, *this, cap);
boost::interprocess::n_uninitialized_copy(first, last, result);
scoped_alloc.release();
return result;
}
@@ -1666,6 +1727,7 @@ operator<(const vector<T, A>& x, const vector<T, A>& y)
y.begin(), y.end());
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T, class A>
inline void swap(vector<T, A>& x, vector<T, A>& y)
{ x.swap(y); }
@@ -1677,6 +1739,11 @@ inline void swap(const detail::moved_object<vector<T, A> >& x, vector<T, A>& y)
template <class T, class A>
inline void swap(vector<T, A> &x, const detail::moved_object<vector<T, A> >& y)
{ x.swap(y.get()); }
#else
template <class T, class A>
inline void swap(vector<T, A>&&x, vector<T, A>&&y)
{ x.swap(y); }
#endif
/// @cond
/*!This class is movable*/

View File

@@ -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_BASIC_SEGMENT_MANAGER_HPP
#define BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_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/detail/no_exceptions_support.hpp>
#include <boost/type_traits/alignment_of.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
#ifndef BOOST_NO_EXCEPTIONS
#include <exception>
#endif
/*!\file
Describes the object placed in a memory segment that provides
named object allocation capabilities for single-segment and
multi-segment allocations.
*/
namespace boost{
namespace interprocess{
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); }
};
//!An integer that describes the type of the
//!instance constructed in memory
enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type };
/// @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 allocation_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)allocation_type << 5u) |
((unsigned char)sizeof_char & 0x1F) )
{};
template<class T>
block_header &operator= (const T& )
{ return *this; }
std::size_t total_size() const
{
if(allocation_type() != detail::anonymous_type){
return name_offset() + (m_num_char+1)*sizeof_char();
}
else{
return value_offset() + m_value_bytes;
}
}
template<class Header>
std::size_t total_size_with_header() const
{
return get_rounded_size
( sizeof(Header)
, boost::alignment_of<block_header>::value)
+ total_size();
}
std::size_t allocation_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 reinterpret_cast<CharType*>
(detail::char_ptr_cast(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 detail::char_ptr_cast(this) + value_offset();
}
std::size_t value_offset() const
{
return get_rounded_size(sizeof(block_header), m_value_alignment);
}
template<class CharType>
bool less(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(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), boost::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 =
reinterpret_cast<block_header*>(detail::char_ptr_cast(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*>(detail::char_ptr_cast(header) +
get_rounded_size(sizeof(Header), boost::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*>(detail::char_ptr_cast(bheader) -
get_rounded_size(sizeof(Header), boost::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 MemoryAlgorithm>
class basic_segment_manager
: private MemoryAlgorithm
{
public:
typedef typename MemoryAlgorithm::void_pointer void_pointer;
typedef typename MemoryAlgorithm::mutex_family mutex_family;
MemoryAlgorithm &memory_algorithm()
{ return *this; }
const MemoryAlgorithm &memory_algorithm() const
{ return *this; }
enum { PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation };
basic_segment_manager(std::size_t size, std::size_t reserved_bytes)
: MemoryAlgorithm(size, reserved_bytes)
{
assert((sizeof(basic_segment_manager<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
}
//!Returns the size of the memory segment
std::size_t get_size() const
{ return MemoryAlgorithm::get_size(); }
//!Returns the number of unallocated bytes of the memory segment
std::size_t get_free_memory() const
{ return MemoryAlgorithm::get_free_memory(); }
//!Obtains the minimum size needed by the segment manager
static std::size_t get_min_size (std::size_t size)
{ return MemoryAlgorithm::get_min_size(size); }
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Never throws
void * allocate (std::size_t nbytes, std::nothrow_t)
{ return MemoryAlgorithm::allocate(nbytes); }
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Throws bad_alloc when fails
void * allocate(std::size_t nbytes)
{
void * ret = MemoryAlgorithm::allocate(nbytes);
if(!ret)
throw bad_alloc();
return ret;
}
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Never throws
void * allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t)
{ return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Throws bad_alloc when fails
void * allocate_aligned(std::size_t nbytes, std::size_t alignment)
{
void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
if(!ret)
throw bad_alloc();
return ret;
}
std::pair<void *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
void *reuse_ptr = 0, std::size_t backwards_multiple = 1)
{
std::pair<void *, bool> ret = MemoryAlgorithm::allocation_command
( command | nothrow_allocation, limit_size, preferred_size, received_size
, reuse_ptr, backwards_multiple);
if(!(command & nothrow_allocation) && !ret.first)
throw bad_alloc();
return ret;
}
//!Deallocates the bytes allocated with allocate/allocate_at_least()
//!pointed by addr
void deallocate (void *addr)
{ MemoryAlgorithm::deallocate(addr); }
//!Increases managed memory in extra_size bytes more. This only works
//!with single-segment management*
void grow(std::size_t extra_size)
{ MemoryAlgorithm::grow(extra_size); }
//!Returns the result of "all_memory_deallocated()" function
//!of the used memory algorithm
bool all_memory_deallocated()
{ return MemoryAlgorithm::all_memory_deallocated(); }
//!Returns the result of "check_sanity()" function
//!of the used memory algorithm
bool check_sanity()
{ return MemoryAlgorithm::check_sanity(); }
//!Writes to zero free memory (memory not yet allocated) of the memory algorithm
void zero_free_memory()
{ MemoryAlgorithm::zero_free_memory(); }
/// @cond
protected:
void * prot_anonymous_construct
(std::size_t num, bool dothrow, detail::in_place_interface &table)
{
typedef detail::block_header block_header_t;
block_header_t block_info ( table.size*num
, table.alignment
, detail::anonymous_type
, 1
, 0);
//Allocate memory
void *ptr_struct = this->allocate(block_info.total_size(), std::nothrow_t());
//Check if there is enough memory
if(!ptr_struct){
if(dothrow){
throw bad_alloc();
}
else{
return 0;
}
}
//Build scoped ptr to avoid leaks with constructor exception
detail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
//Now construct the header
block_header_t * hdr = new(ptr_struct) block_header_t(block_info);
void *ptr = hdr->value();
//Now call constructors
detail::array_construct(ptr, num, table);
//All constructors successful, we don't want erase memory
mem.release();
return ptr;
}
//!Calls the destructor and makes an anonymous deallocate
bool prot_anonymous_destroy(const void *object, detail::in_place_interface &table)
{
if(!object)
return false;
//Get control data from associated with this object
typedef detail::block_header block_header_t;
block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
//-------------------------------
//boost::interprocess::scoped_lock<rmutex> guard(m_header);
//-------------------------------
if(ctrl_data->allocation_type() != detail::anonymous_type){
//This is not an anonymous object, the pointer is wrong!
assert(0);
return false;
}
//Call destructors and free memory
//Build scoped ptr to avoid leaks with destructor exception
std::size_t destroyed = 0;
table.destroy_n((void*)object, ctrl_data->m_value_bytes/table.size, destroyed);
this->deallocate(ctrl_data);
return true;
}
};
} //namespace detail {
}} //namespace boost { namespace interprocess
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP

View File

@@ -18,9 +18,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/type_traits/is_pointer.hpp>
namespace boost{
namespace interprocess{

View File

@@ -0,0 +1,229 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_DETAIL_ALGORITHMS_HPP
#define BOOST_INTERPROCESS_DETAIL_ALGORITHMS_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/get_pointer.hpp>
#include <boost/detail/no_exceptions_support.hpp>
namespace boost {
namespace interprocess {
template<class FwdIt, class T>
void uninitialized_fill(FwdIt first, FwdIt last, const T& val)
{
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
//Save initial position
FwdIt init = first;
BOOST_TRY{
//Construct objects
for (; first != last; ++first){
new(detail::get_pointer(&*first))value_type(val);
}
}
BOOST_CATCH(...){
//Call destructors
for (; init != first; ++init){
detail::get_pointer(&*init)->~value_type();
}
BOOST_RETHROW;
}
BOOST_CATCH_END
}
template<class FwdIt, class Count, class T>
void uninitialized_fill_n(FwdIt first, Count count,
const T& val)
{
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
//Save initial position
FwdIt init = first;
BOOST_TRY{
//Construct objects
for (; count--; ++first){
new(detail::get_pointer(&*first))value_type(val);
}
}
BOOST_CATCH(...){
//Call destructors
for (; init != first; ++init){
detail::get_pointer(&*init)->~value_type();
}
BOOST_RETHROW;
}
BOOST_CATCH_END
}
template<class InIt, class OutIt>
InIt copy_n(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest)
{
for (; length--; ++dest, ++first)
*dest = *first;
return first;
}
template<class InIt, class FwdIt>
typename std::iterator_traits<InIt>::difference_type
n_uninitialized_copy(InIt first, InIt last, FwdIt dest)
{
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 constructed = 0;
BOOST_TRY{
//Try to build objects
for (; first != last; ++dest, ++first, ++constructed){
new(detail::get_pointer(&*dest))value_type(*first);
}
}
BOOST_CATCH(...){
//Call destructors
for (; dest_init != dest; ++dest_init){
detail::get_pointer(&*dest_init)->~value_type();
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return (constructed);
}
template<class InIt, class FwdIt> inline
FwdIt uninitialized_copy(InIt first, InIt last, FwdIt dest)
{
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 constructed = 0;
BOOST_TRY{
//Try to build objects
for (; first != last; ++dest, ++first, ++constructed){
new(detail::get_pointer(&*dest))value_type(*first);
}
}
BOOST_CATCH(...){
//Call destructors
for (; dest_init != dest; ++dest_init){
detail::get_pointer(&*dest_init)->~value_type();
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return (dest);
}
template<class InIt, class FwdIt> inline
InIt n_uninitialized_copy_n
(InIt first,
typename std::iterator_traits<InIt>::difference_type count,
FwdIt dest)
{
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){
new(detail::get_pointer(&*dest))value_type(*first);
}
}
BOOST_CATCH(...){
//Call destructors
new_count = count - new_count;
for (; new_count--; ++dest_init){
detail::get_pointer(&*dest_init)->~value_type();
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return first;
}
// 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 = boost::interprocess::uninitialized_copy(first1, last1, result);
BOOST_TRY {
return boost::interprocess::uninitialized_copy(first2, last2, mid);
}
BOOST_CATCH(...){
for(;result != mid; ++result){
detail::get_pointer(&*result)->~value_type();
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
// uninitialized_copy_n_copy_n
// Copies [first1, first1 + n1) into [result, result + n1), and
// copies [first2, first2 + n2) into
// [result + n1, result + n1 + n2).
template <class InpIt1, class InpIt2, class FwdIt>
InpIt2 uninitialized_copy_n_copy_n
(InpIt1 first1,
typename std::iterator_traits<InpIt1>::difference_type n1,
InpIt2 first2,
typename std::iterator_traits<InpIt2>::difference_type n2,
FwdIt result)
{
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
typename std::iterator_traits<InpIt1>::difference_type c1 = n1+1;
typename std::iterator_traits<InpIt2>::difference_type c2 = n2+1;
FwdIt dest_init = result;
BOOST_TRY{
//Try to build objects
for (; --c1; ++result, ++first1){
new(detail::get_pointer(&*result))value_type(*first1);
}
for (; --c2; ++result, ++first2){
new(detail::get_pointer(&*result))value_type(*first2);
}
}
BOOST_CATCH(...){
//Call destructors
typename std::iterator_traits<FwdIt>::
difference_type c = (n1 - c1) + (n2 - c2);
for (; c--; ++dest_init){
detail::get_pointer(&*dest_init)->~value_type();
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return first2;
}
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP

View File

@@ -179,8 +179,8 @@ static boost::uint32_t inline intel_atomic_add32
(volatile boost::uint32_t *mem, boost::uint32_t val)
{
asm volatile ("lock; xaddl %0,%1"
: "=r"(val), "=m"(*mem) /* outputs */
: "0"(val), "m"(*mem) /* inputs */
: "=r"(val), "=m"(*mem) // outputs
: "0"(val), "m"(*mem) // inputs
: "memory", "cc");
return val;
}
@@ -368,16 +368,24 @@ inline boost::uint32_t atomic_xchg32(volatile boost::uint32_t *mem, boost::uint3
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
{ atomic_xchg32(mem, val); }
#elif (defined(SOLARIS2) && SOLARIS2 >= 10)
} //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(mem, val) - 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"
@@ -387,25 +395,25 @@ inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32
//! 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(mem, cmp, with); }
{ return atomic_cas_32(reinterpret_cast<volatile ::uint32_t*>(mem), cmp, with); }
//! Atomically subtract 'val' from an apr_uint32_t
//! "mem": pointer to the object
//! "val": amount to subtract
inline void atomic_sub32(volatile boost::uint32_t *mem, boost::uint32_t val)
{ return atomic_add_32(mem, (-val)); }
{ return atomic_add_32(reinterpret_cast<volatile ::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_add_32_nv(mem, 1) - 1; }
{ 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 false if the value becomes zero on decrement, otherwise true
inline bool atomic_dec32(volatile boost::uint32_t *mem)
{ return atomic_add_32_nv(mem, -1) != 0; }
{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), -1) != 0; }
//! Atomically read an boost::uint32_t from memory
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
@@ -416,7 +424,7 @@ inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
//! "val": what to swap it with
//! Returns the old value of *mem
inline boost::uint32_t atomic_xchg32(volatile boost::uint32_t *mem, boost::uint32_t val)
{ return atomic_swap_32(mem, val); }
{ return atomic_swap_32(reinterpret_cast<volatile ::uint32_t*>(mem), val); }
//! Atomically set an boost::uint32_t in memory
//! "mem": pointer to the object

View File

@@ -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_BASIC_SEGMENT_MANAGER_HPP
#define BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_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/detail/no_exceptions_support.hpp>
#include <boost/type_traits/alignment_of.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
#ifndef BOOST_NO_EXCEPTIONS
#include <exception>
#endif
/*!\file
Describes the object placed in a memory segment that provides
named object allocation capabilities for single-segment and
multi-segment allocations.
*/
namespace boost{
namespace interprocess{
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); }
};
//!An integer that describes the type of the
//!instance constructed in memory
enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type };
/// @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 allocation_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)allocation_type << 5u) |
((unsigned char)sizeof_char & 0x1F) )
{};
template<class T>
block_header &operator= (const T& )
{ return *this; }
std::size_t total_size() const
{
if(allocation_type() != detail::anonymous_type){
return name_offset() + (m_num_char+1)*sizeof_char();
}
else{
return value_offset() + m_value_bytes;
}
}
template<class Header>
std::size_t total_size_with_header() const
{
return get_rounded_size
( sizeof(Header)
, boost::alignment_of<block_header>::value)
+ total_size();
}
std::size_t allocation_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 reinterpret_cast<CharType*>
(detail::char_ptr_cast(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 detail::char_ptr_cast(this) + value_offset();
}
std::size_t value_offset() const
{
return get_rounded_size(sizeof(block_header), m_value_alignment);
}
template<class CharType>
bool less(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(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), boost::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 =
reinterpret_cast<block_header*>(detail::char_ptr_cast(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*>(detail::char_ptr_cast(header) +
get_rounded_size(sizeof(Header), boost::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*>(detail::char_ptr_cast(bheader) -
get_rounded_size(sizeof(Header), boost::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 MemoryAlgorithm>
class basic_segment_manager
: private MemoryAlgorithm
{
public:
typedef typename MemoryAlgorithm::void_pointer void_pointer;
typedef typename MemoryAlgorithm::mutex_family mutex_family;
MemoryAlgorithm &memory_algorithm()
{ return *this; }
const MemoryAlgorithm &memory_algorithm() const
{ return *this; }
enum { PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation };
basic_segment_manager(std::size_t size, std::size_t reserved_bytes)
: MemoryAlgorithm(size, reserved_bytes)
{
assert((sizeof(basic_segment_manager<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
}
//!Returns the size of the memory segment
std::size_t get_size() const
{ return MemoryAlgorithm::get_size(); }
//!Returns the number of unallocated bytes of the memory segment
std::size_t get_free_memory() const
{ return MemoryAlgorithm::get_free_memory(); }
//!Obtains the minimum size needed by the segment manager
static std::size_t get_min_size (std::size_t size)
{ return MemoryAlgorithm::get_min_size(size); }
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Never throws
void * allocate (std::size_t nbytes, std::nothrow_t)
{ return MemoryAlgorithm::allocate(nbytes); }
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Throws bad_alloc when fails
void * allocate(std::size_t nbytes)
{
void * ret = MemoryAlgorithm::allocate(nbytes);
if(!ret)
throw bad_alloc();
return ret;
}
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Never throws
void * allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t)
{ return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
//!Allocates nbytes bytes. This function is only used in
//!single-segment management. Throws bad_alloc when fails
void * allocate_aligned(std::size_t nbytes, std::size_t alignment)
{
void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
if(!ret)
throw bad_alloc();
return ret;
}
std::pair<void *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
std::size_t preferred_size,std::size_t &received_size,
void *reuse_ptr = 0, std::size_t backwards_multiple = 1)
{
std::pair<void *, bool> ret = MemoryAlgorithm::allocation_command
( command | nothrow_allocation, limit_size, preferred_size, received_size
, reuse_ptr, backwards_multiple);
if(!(command & nothrow_allocation) && !ret.first)
throw bad_alloc();
return ret;
}
//!Deallocates the bytes allocated with allocate/allocate_at_least()
//!pointed by addr
void deallocate (void *addr)
{ MemoryAlgorithm::deallocate(addr); }
//!Increases managed memory in extra_size bytes more. This only works
//!with single-segment management*
void grow(std::size_t extra_size)
{ MemoryAlgorithm::grow(extra_size); }
//!Returns the result of "all_memory_deallocated()" function
//!of the used memory algorithm
bool all_memory_deallocated()
{ return MemoryAlgorithm::all_memory_deallocated(); }
//!Returns the result of "check_sanity()" function
//!of the used memory algorithm
bool check_sanity()
{ return MemoryAlgorithm::check_sanity(); }
//!Writes to zero free memory (memory not yet allocated) of the memory algorithm
void zero_free_memory()
{ MemoryAlgorithm::zero_free_memory(); }
/// @cond
protected:
void * prot_anonymous_construct
(std::size_t num, bool dothrow, detail::in_place_interface &table)
{
typedef detail::block_header block_header_t;
block_header_t block_info ( table.size*num
, table.alignment
, detail::anonymous_type
, 1
, 0);
//Allocate memory
void *ptr_struct = this->allocate(block_info.total_size(), std::nothrow_t());
//Check if there is enough memory
if(!ptr_struct){
if(dothrow){
throw bad_alloc();
}
else{
return 0;
}
}
//Build scoped ptr to avoid leaks with constructor exception
detail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
//Now construct the header
block_header_t * hdr = new(ptr_struct) block_header_t(block_info);
void *ptr = hdr->value();
//Now call constructors
detail::array_construct(ptr, num, table);
//All constructors successful, we don't want erase memory
mem.release();
return ptr;
}
//!Calls the destructor and makes an anonymous deallocate
bool prot_anonymous_destroy(const void *object, detail::in_place_interface &table)
{
if(!object)
return false;
//Get control data from associated with this object
typedef detail::block_header block_header_t;
block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
//-------------------------------
//boost::interprocess::scoped_lock<rmutex> guard(m_header);
//-------------------------------
if(ctrl_data->allocation_type() != detail::anonymous_type){
//This is not an anonymous object, the pointer is wrong!
assert(0);
return false;
}
//Call destructors and free memory
//Build scoped ptr to avoid leaks with destructor exception
std::size_t destroyed = 0;
table.destroy_n((void*)object, ctrl_data->m_value_bytes/table.size, destroyed);
this->deallocate(ctrl_data);
return true;
}
};
} //namespace detail {
}} //namespace boost { namespace interprocess
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP

View File

@@ -32,9 +32,3 @@
#pragma warning (disable : 4146)
#pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data
#endif
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# pragma warn -8026 // shut up warning "cannot inline function because ..."
# pragma warn -8027 // shut up warning "cannot inline function because ..."
#endif

View File

@@ -1,8 +1,3 @@
#if defined _MSC_VER
#pragma warning (pop)
#endif
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# pragma warn .8026
# pragma warn .8027
#endif

View File

@@ -47,13 +47,19 @@ class file_wrapper
/*!Moves the ownership of "moved"'s shared memory object to *this.
After the call, "moved" does not represent any shared memory object.
Does not throw*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
file_wrapper
(detail::moved_object<file_wrapper> &moved)
{ this->swap(moved.get()); }
#else
file_wrapper(file_wrapper &&moved)
{ this->swap(moved); }
#endif
/*!Moves the ownership of "moved"'s shared memory to *this.
After the call, "moved" does not represent any shared memory.
Does not throw*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
file_wrapper &operator=
(detail::moved_object<file_wrapper> &moved)
{
@@ -61,6 +67,14 @@ class file_wrapper
this->swap(tmp);
return *this;
}
#else
file_wrapper &operator=(file_wrapper &&moved)
{
file_wrapper tmp(move(moved));
this->swap(tmp);
return *this;
}
#endif
/*!Swaps to shared_memory_objects. Does not throw*/
void swap(file_wrapper &other);

View File

@@ -0,0 +1,75 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_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/type_traits/alignment_of.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(void *mem) = 0;
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) = 0;
virtual void destroy(void *mem) = 0;
virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) = 0;
virtual ~in_place_interface(){}
};
template<class T>
struct placement_destroy : public in_place_interface
{
placement_destroy()
: in_place_interface(boost::alignment_of<T>::value, sizeof(T), typeid(T).name())
{}
virtual void destroy(void *mem)
{ static_cast<T*>(mem)->~T(); }
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(void *) {}
virtual void construct_n(void *, std::size_t, std::size_t &) {}
};
}
}
} //namespace boost { namespace interprocess { namespace detail {
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP

View File

@@ -0,0 +1,138 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2007.
// (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_ITERATORS_HPP
#define BOOST_INTERPROCESS_DETAIL_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 <boost/iterator/iterator_facade.hpp>
namespace boost {
namespace interprocess {
template <class T, class Difference = std::ptrdiff_t>
class constant_iterator
: public boost::iterator_facade
< constant_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, const T &
, Difference>
{
typedef boost::iterator_facade
< constant_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, const T &
, Difference> super_t;
typedef constant_iterator<T, Difference> this_type;
//Give access to private core functions
friend class boost::iterator_core_access;
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){}
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; }
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 repeat_iterator
: public boost::iterator_facade
< repeat_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, T &
, Difference>
{
typedef boost::iterator_facade
< repeat_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, T &
, Difference> super_t;
typedef repeat_iterator<T, Difference> this_type;
//Give access to private core functions
friend class boost::iterator_core_access;
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){}
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; }
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; }
};
} //namespace interprocess {
} //namespace boost {
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP

View File

@@ -84,10 +84,15 @@ class basic_managed_memory_impl
public:
typedef typename segment_manager_type
<CharType, MemoryAlgorithm, IndexType>::type segment_manager;
typedef typename MemoryAlgorithm::void_pointer void_pointer;
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::
named_index_t::const_iterator const_named_iterator;
typedef typename segment_manager::
unique_index_t::const_iterator const_unique_iterator;
enum { PayloadPerAllocation = segment_manager::PayloadPerAllocation };
@@ -208,6 +213,26 @@ class basic_managed_memory_impl
std::size_t get_size () const
{ return mp_header->get_size(); }
//!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
@@ -280,7 +305,7 @@ class basic_managed_memory_impl
//!array was being constructed, destructors of created objects are called
//!before freeing the memory.
template <class T>
typename segment_manager::template construct_proxy<T, true>::type
typename segment_manager::template construct_proxy<T>::type
construct(char_ptr_holder_t name)
{ return mp_header->construct<T>(name); }
@@ -301,7 +326,7 @@ class basic_managed_memory_impl
//!array was being constructed, destructors of created objects are called
//!before freeing the memory.
template <class T>
typename segment_manager::template find_construct_proxy<T, true>::type
typename segment_manager::template construct_proxy<T>::type
find_or_construct(char_ptr_holder_t name)
{ return mp_header->find_or_construct<T>(name); }
@@ -322,7 +347,7 @@ class basic_managed_memory_impl
//!array was being constructed, destructors of created objects are called
//!before freeing the memory.
template <class T>
typename segment_manager::template construct_proxy<T, false>::type
typename segment_manager::template construct_proxy<T>::type
construct(char_ptr_holder_t name, std::nothrow_t nothrow)
{ return mp_header->construct<T>(name, nothrow); }
@@ -343,7 +368,7 @@ class basic_managed_memory_impl
//!array was being constructed, destructors of created objects are called
//!before freeing the memory.
template <class T>
typename segment_manager::template find_construct_proxy<T, false>::type
typename segment_manager::template construct_proxy<T>::type
find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow)
{ return mp_header->find_or_construct<T>(name, nothrow); }
@@ -364,7 +389,7 @@ class basic_managed_memory_impl
//!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, true>::type
typename segment_manager::template construct_iter_proxy<T>::type
construct_it(char_ptr_holder_t name)
{ return mp_header->construct_it<T>(name); }
@@ -387,7 +412,7 @@ class basic_managed_memory_impl
//!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 find_construct_iter_proxy<T, true>::type
typename segment_manager::template construct_iter_proxy<T>::type
find_or_construct_it(char_ptr_holder_t name)
{ return mp_header->find_or_construct_it<T>(name); }
@@ -408,7 +433,7 @@ class basic_managed_memory_impl
//!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, false>::type
typename segment_manager::template construct_iter_proxy<T>::type
construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
{ return mp_header->construct_it<T>(name, nothrow); }
@@ -431,7 +456,7 @@ class basic_managed_memory_impl
//!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 find_construct_iter_proxy<T, false>::type
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->find_or_construct_it<T>(name, nothrow); }
@@ -525,7 +550,7 @@ class basic_managed_memory_impl
//!Returns is the the name of an object created with construct/find_or_construct
//!functions. Does not throw
template<class T>
InstanceType get_type(const T *ptr)
detail::instance_type get_type(const T *ptr)
{ return mp_header->get_type(ptr); }
//!Preallocates needed index resources to optimize the
@@ -566,28 +591,16 @@ class basic_managed_memory_impl
(std::streamsize)get_size()).good();
}
typename segment_manager::named_index_t::iterator named_begin()
const_named_iterator named_begin() const
{ return mp_header->named_begin(); }
typename segment_manager::named_index_t::iterator named_begin() const
{ return mp_header->named_begin(); }
typename segment_manager::named_index_t::iterator named_end()
const_named_iterator named_end() const
{ return mp_header->named_end(); }
typename segment_manager::named_index_t::iterator named_end() const
{ return mp_header->named_end(); }
typename segment_manager::unique_index_t::iterator unique_begin()
const_unique_iterator unique_begin() const
{ return mp_header->unique_begin(); }
typename segment_manager::unique_index_t::iterator unique_begin() const
{ return mp_header->unique_begin(); }
typename segment_manager::unique_index_t::iterator unique_end()
{ return mp_header->unique_end(); }
typename segment_manager::unique_index_t::iterator unique_end() const
const_unique_iterator unique_end() const
{ return mp_header->unique_end(); }
protected:

View File

@@ -19,8 +19,8 @@
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/interprocess/detail/creation_tags.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/cstdint.hpp>
#include <boost/mpl/bool.hpp>
namespace boost {
namespace interprocess {
@@ -147,10 +147,17 @@ class managed_open_or_create_impl
, construct_func);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
managed_open_or_create_impl
(detail::moved_object<managed_open_or_create_impl> &moved)
{ this->swap(moved.get()); }
#else
managed_open_or_create_impl
(managed_open_or_create_impl &&moved)
{ this->swap(moved); }
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
managed_open_or_create_impl &operator=
(detail::moved_object<managed_open_or_create_impl> &moved)
{
@@ -158,6 +165,15 @@ class managed_open_or_create_impl
this->swap(tmp);
return *this;
}
#else
managed_open_or_create_impl &operator=
(managed_open_or_create_impl &&moved)
{
managed_open_or_create_impl tmp(move(moved));
this->swap(tmp);
return *this;
}
#endif
~managed_open_or_create_impl()
{}
@@ -184,11 +200,11 @@ class managed_open_or_create_impl
//These are templatized to allow explicit instantiations
template<bool dummy>
static void write_whole_device(DeviceAbstraction &, std::size_t, boost::mpl::false_)
static void write_whole_device(DeviceAbstraction &, std::size_t, false_)
{} //Empty
template<bool dummy>
static void write_whole_device(DeviceAbstraction &dev, std::size_t size, boost::mpl::true_)
static void write_whole_device(DeviceAbstraction &dev, std::size_t size, true_)
{
file_handle_t hnd = detail::file_handle_from_mapping_handle(dev.get_mapping_handle());
@@ -208,7 +224,7 @@ class managed_open_or_create_impl
;remaining -= write_size){
const std::size_t DataSize = 512;
static char data [DataSize];
write_size = min_value(DataSize, remaining);
write_size = DataSize < remaining ? DataSize : remaining;
if(!detail::write_file(hnd, data, write_size)){
error_info err = system_error_code();
throw interprocess_exception(err);
@@ -218,23 +234,23 @@ class managed_open_or_create_impl
//These are templatized to allow explicit instantiations
template<bool dummy>
static void truncate_device(DeviceAbstraction &, std::size_t, boost::mpl::false_)
static void truncate_device(DeviceAbstraction &, std::size_t, false_)
{} //Empty
template<bool dummy>
static void truncate_device(DeviceAbstraction &dev, std::size_t size, boost::mpl::true_)
static void truncate_device(DeviceAbstraction &dev, std::size_t size, 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, boost::mpl::false_)
static void create_device(DeviceAbstraction &dev, const char *name, std::size_t size, 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, boost::mpl::true_)
static void create_device(DeviceAbstraction &dev, const char *name, std::size_t, true_)
{
DeviceAbstraction tmp(create_only, name, read_write);
tmp.swap(dev);
@@ -246,7 +262,7 @@ class managed_open_or_create_impl
mode_t mode, const void *addr,
ConstructFunc construct_func)
{
typedef boost::mpl::bool_<FileBased> file_like_t;
typedef bool_<FileBased> file_like_t;
(void)mode;
error_info err;
bool created = false;

View File

@@ -0,0 +1,40 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_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

View File

@@ -17,7 +17,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/mpl/if.hpp>
/*!\file
Describes a function and a type to emulate move semantics.
@@ -32,6 +31,15 @@ struct is_movable
enum { value = false };
};
} //namespace interprocess {
} //namespace boost {
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
#include <boost/interprocess/detail/mpl.hpp>
namespace boost {
namespace interprocess {
namespace detail {
/*!An object that represents a moved object.*/
@@ -54,11 +62,7 @@ template <typename T>
struct move_type
{
public: // metafunction result
typedef typename mpl::if_<
is_movable<T>
, moved_object<T>
, T&
>::type type;
typedef typename if_<is_movable<T>, moved_object<T>, T&>::type type;
};
template <typename T>
@@ -87,14 +91,15 @@ struct return_type
{
public: // metafunction result
typedef typename boost::mpl::if_
<is_movable<T>
, move_return<T>
, T
>::type type;
typedef typename if_<is_movable<T>, move_return<T>, T>::type type;
};
} //namespace detail {
} //namespace interprocess {
} //namespace boost {
namespace boost {
namespace interprocess {
/*!A function that converts an object to a moved object so that
it can match a function taking a detail::moved_object object.*/
@@ -109,6 +114,29 @@ typename detail::move_type<Object>::type move
} //namespace interprocess {
} //namespace boost {
#else //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#include <boost/type_traits/remove_reference.hpp>
namespace boost {
namespace interprocess {
template <class T>
inline typename boost::remove_reference<T>::type&&
move(T&& t)
{ return t; }
template <class T>
inline
T&&
forward(typename identity<T>::type&& t)
{ return t; }
} //namespace interprocess {
} //namespace boost {
#endif //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_MOVE_HPP

View File

@@ -25,7 +25,11 @@ class move_iterator
public:
typedef typename boost::remove_reference<It>::type iterator_type;
typedef typename std::iterator_traits<iterator_type>::value_type value_type;
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
typedef typename move_type<value_type>::type reference;
#else
typedef value_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;
@@ -49,7 +53,11 @@ class move_iterator
{ return m_it; }
reference operator*() const
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
{ return move(*m_it); }
#else
{ return *m_it; }
#endif
pointer operator->() const
{ return m_it; }

View File

@@ -0,0 +1,88 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_DETAIL_MPL_HPP
#define BOOST_INTERPROCESS_DETAIL_MPL_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <functional>
namespace boost {
namespace interprocess {
template< bool C_ >
struct bool_
{
static const bool value = C_;
};
typedef bool_<true> true_;
typedef bool_<false> false_;
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>
{
const typename Pair::first_type& operator()(const Pair& 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>
{
const T& operator()(const T& x) const
{ return x; }
};
} //namespace interprocess {
} //namespace boost {
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP

View File

@@ -19,50 +19,43 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <new>
#include <boost/config.hpp>
#include <boost/interprocess/detail/in_place_interface.hpp>
#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>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/bind.hpp>
#include <boost/interprocess/detail/mpl.hpp>
/*!\file
Describes a proxy class that implements named allocation syntax.
*/
namespace boost { namespace interprocess {
namespace boost {
namespace interprocess {
namespace detail {
/*!Function object that makes placement new without arguments*/
template<class T>
struct Ctor0Arg
struct Ctor0Arg : public placement_destroy<T>
{
typedef Ctor0Arg self_t;
typedef T target_t;
enum { is_trivial = boost::has_trivial_constructor<T>::value };
Ctor0Arg(){}
self_t& operator++() { return *this; }
self_t operator++(int) { return *this; }
static inline void construct(T *mem, boost::mpl::false_)
{ new(mem)T; }
static inline void construct(T *mem, boost::mpl::true_)
{}
void operator()(T *mem) const
virtual void construct(void *mem)
{ new(mem)T; }
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
{
typedef boost::mpl::bool_<is_trivial> Result;
Ctor0Arg<T>::construct(mem, Result());
T* memory = static_cast<T*>(mem);
for(constructed = 0; constructed < num; ++constructed)
new(memory++)T;
}
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
private:
char dummy_; // BCB would by default use 8 B for empty structure
#endif
};
#ifndef BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS
@@ -75,17 +68,16 @@ struct Ctor0Arg
// template<class T, bool param_or_it, class P1, class P2>
// struct Ctor2Arg
// {
// enum { is_trivial = false };
// typedef Ctor2Arg self_t;
//
// void do_increment(boost::mpl::false_)
// void do_increment(false_)
// { ++m_p1; ++m_p2; }
//
// void do_increment(boost::mpl::true_){}
// void do_increment(true_){}
//
// self_t& operator++()
// {
// typedef boost::mpl::bool_<param_or_it> Result;
// typedef bool_<param_or_it> Result;
// this->do_increment(Result());
// return *this;
// }
@@ -95,8 +87,21 @@ struct Ctor0Arg
// Ctor2Arg(const P1 &p1, const P2 &p2)
// : p1((P1 &)p_1), p2((P2 &)p_2) {}
//
// void operator()(T* mem) const
// { new (mem) T(m_p1, m_p2); }
// virtual void construct(void *mem)
// { new(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){
// new(memory++)T(m_p1, m_p2);
// typedef bool_<param_or_it> Result;
// this->do_increment(Result());
// }
// }
//
// private:
// P1 &m_p1; P2 &m_p2;
// };
@@ -122,24 +127,27 @@ struct Ctor0Arg
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
#define BOOST_INTERPROCESS_AUX_PARAM_DEREFERENCE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
/**/
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T, bool param_or_it, BOOST_PP_ENUM_PARAMS(n, class P) >\
struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
: public placement_destroy<T> \
{ \
enum { is_trivial = false }; \
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \
typedef T target_t; \
\
void do_increment(boost::mpl::false_) \
void do_increment(false_) \
{ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INC, _); } \
\
void do_increment(boost::mpl::true_){} \
void do_increment(true_){} \
\
self_t& operator++() \
{ \
typedef boost::mpl::bool_<param_or_it> Result; \
typedef bool_<param_or_it> Result; \
this->do_increment(Result()); \
return *this; \
} \
@@ -150,14 +158,27 @@ struct Ctor0Arg
( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_LIST, _) ) \
: BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \
\
void operator()(T* mem) const \
{ new (mem) T(BOOST_PP_ENUM_PARAMS(n, m_p)); } \
virtual void construct(void *mem) \
{ new(mem)T(BOOST_PP_ENUM_PARAMS(n, m_p)); } \
\
private: \
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(memory++)T(BOOST_PP_ENUM_PARAMS(n, m_p)); \
typedef bool_<param_or_it> Result; \
this->do_increment(Result()); \
} \
} \
\
private: \
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()
@@ -166,32 +187,34 @@ struct Ctor0Arg
#undef BOOST_INTERPROCESS_AUX_PARAM_DEFINE
#undef BOOST_INTERPROCESS_AUX_PARAM_INC
/*!Describes a proxy class that implements named allocation syntax.
*/
//!Describes a proxy class that implements named
//!allocation syntax.
template
< class CharType //char type for the name (char, wchar_t...)
< class SegmentManager //segment manager to construct the object
, class T //type of object to build
, class NamedAlloc //class to allocate and construct the object
, bool find //if true, we try to find the object before creating
, bool dothrow //if true, we throw an exception, otherwise, return 0
, bool param_or_it //passing parameters are normal object or iterators?
>
class named_proxy
{
const CharType * mp_name;
NamedAlloc * mp_alloc;
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(const CharType *name, NamedAlloc *alloc)
: mp_name(name), mp_alloc(alloc), m_num(1){}
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_alloc->template
generic_construct<T>(mp_name, m_num, find, dothrow, ctor_obj);
return mp_mngr->template
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
}
/**/
@@ -212,8 +235,8 @@ class named_proxy
<T, param_or_it, BOOST_PP_ENUM (n, BOOST_INTERPROCESS_AUX_TYPE_LIST, _)> \
ctor_obj_t; \
ctor_obj_t ctor_obj (BOOST_PP_ENUM_PARAMS(n, p)); \
return mp_alloc->template generic_construct<T> \
(mp_name, m_num, find, dothrow, ctor_obj); \
return mp_mngr->template generic_construct<T> \
(mp_name, m_num, m_find, m_dothrow, ctor_obj); \
} \
/**/
@@ -234,8 +257,8 @@ class named_proxy
// ctor_obj_t;
// ctor_obj_t ctor_obj(p1, p2);
//
// return mp_alloc->template generic_construct<T>
// (mp_name, m_num, find, dothrow, ctor_obj);
// return mp_mngr->template generic_construct<T>
// (mp_name, m_num, m_find, m_dothrow, ctor_obj);
// }
//
//////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,73 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2007.
// (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>
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 boost::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

View File

@@ -22,37 +22,42 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/get_pointer.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/type_traits/has_nothrow_destructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/call_traits.hpp>
#include <algorithm>
#include <functional>
#include <boost/interprocess/detail/min_max.hpp>
//#include <functional>
#include <utility>
#include <stdexcept>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/intrusive/slist.hpp>
namespace boost { namespace interprocess {
template<class T>
class offset_ptr;
namespace boost {
namespace interprocess {
namespace detail {
/*!Overload for smart pointers to avoid ADL problems with get_pointer*/
template<class Ptr>
inline typename Ptr::value_type *get_pointer(const Ptr &ptr)
{ using boost::get_pointer; return get_pointer(ptr); }
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();}
};
/*!Overload for raw pointers to avoid ADL problems with get_pointer*/
template<class T>
inline T *get_pointer(T *ptr)
{ return ptr; }
struct smart_ptr_type<T*>
{
typedef T value_type;
typedef value_type *pointer;
static pointer get (pointer ptr)
{ return ptr;}
};
/*!To avoid ADL problems with swap*/
//!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)
{
@@ -60,31 +65,30 @@ inline void do_swap(T& x, T& y)
swap(x, y);
}
/*!A deleter for scoped_ptr that deallocates the memory
allocated for an object using a STL allocator.*/
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class Allocator>
struct scoped_deallocator
struct scoped_ptr_deallocator
{
typedef typename Allocator::pointer pointer;
Allocator& m_alloc;
scoped_deallocator(Allocator& a)
scoped_ptr_deallocator(Allocator& a)
: m_alloc(a) {}
void operator()(pointer ptr)
{ if (ptr) m_alloc.deallocate(ptr, 1); }
};
/*!A deleter for scoped_ptr that deallocates the memory
allocated for an array of objects using a STL allocator.*/
//!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
struct scoped_ptr_array_deallocator
{
typedef typename Allocator::pointer pointer;
scoped_array_deallocator(Allocator& a, std::size_t length)
scoped_ptr_array_deallocator(Allocator& a, std::size_t length)
: m_alloc(a), m_length(length) {}
void operator()(pointer &ptr)
@@ -95,46 +99,78 @@ struct scoped_array_deallocator
std::size_t m_length;
};
/*!A deleter for scoped_ptr that destroys
an object using a STL allocator.*/
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an object using a STL allocator.
template <class Allocator>
struct scoped_destructor
struct scoped_deallocator
{
typedef typename Allocator::pointer pointer;
Allocator& m_alloc;
pointer m_ptr;
Allocator& m_alloc;
scoped_destructor(Allocator& a)
: m_alloc(a){}
scoped_deallocator(pointer p, Allocator& a)
: m_ptr(p), m_alloc(a) {}
void operator()(pointer &ptr)
{ m_alloc.destroy(ptr); }
~scoped_deallocator()
{ if (m_ptr) m_alloc.deallocate(m_ptr, 1); }
void release()
{ m_ptr = 0; }
};
/*!A deleter for scoped_ptr that destroys
an object using a STL allocator.*/
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_destructor_n
struct scoped_array_deallocator
{
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
Allocator& m_alloc;
size_type m_n;
scoped_array_deallocator(pointer p, Allocator& a, std::size_t length)
: m_ptr(p), m_alloc(a), m_length(length) {}
scoped_destructor_n(Allocator& a, size_type n)
: m_alloc(a), m_n(n){}
~scoped_array_deallocator()
{ if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
void operator()(pointer ptr)
void release()
{ m_ptr = 0; }
private:
pointer m_ptr;
Allocator& m_alloc;
std::size_t m_length;
};
//!A deleter for scoped_ptr that destroys
//!an object using a STL allocator.
template <class Pointer>
struct scoped_destructor_n
{
typedef Pointer pointer;
pointer m_p;
std::size_t m_n;
scoped_destructor_n(pointer p, std::size_t n)
: m_p(p), m_n(n){}
void release()
{ m_p = 0; }
~scoped_destructor_n()
{
for(size_type i = 0; i < m_n; ++i, ++ptr)
m_alloc.destroy(ptr);
if(!m_p) return;
typedef typename std::iterator_traits<Pointer>::value_type value_type;
value_type *raw_ptr = detail::get_pointer(m_p);
for(std::size_t i = 0; i < m_n; ++i, ++raw_ptr)
raw_ptr->~value_type();
}
};
template <class A>
class allocator_destroyer
{
typedef typename A::value_type value_type;
private:
A & a_;
@@ -143,9 +179,9 @@ class allocator_destroyer
: a_(a)
{}
void operator()(typename A::pointer p)
void operator()(const typename A::pointer &p)
{
a_.destroy(p);
detail::get_pointer(p)->~value_type();
a_.deallocate(p, 1);
}
};
@@ -164,23 +200,6 @@ inline char* char_ptr_cast()
return (char*)(0);
}
template <class Pair>
struct select1st
: public std::unary_function<Pair, typename Pair::first_type>
{
const typename Pair::first_type& operator()(const Pair& x) const
{ return x.first; }
};
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
: public std::unary_function<T,T>
{
const T& operator()(const T& x) const
{ return x; }
};
//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)
{
@@ -191,7 +210,6 @@ inline std::size_t get_truncated_size(std::size_t orig_size, std::size_t multipl
{
return orig_size/multiple*multiple;
}
template <std::size_t OrigSize, std::size_t RoundTo>
struct ct_rounded_size
@@ -259,46 +277,8 @@ struct pointer_to_other< T*, U >
typedef U* type;
};
//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(boost::has_nothrow_destructor<typename Cont::value_type>::value){
if(m_erase) m_cont.erase(m_index_it);
}
else{
//value_eraser is used in exceptions, so we
//disable double-exception danger
BOOST_TRY{ if(m_erase) m_cont.erase(m_index_it); }
BOOST_CATCH(...){}
BOOST_CATCH_END
}
}
void release() { m_erase = false; }
private:
Cont &m_cont;
typename Cont::iterator m_index_it;
bool m_erase;
};
} //namespace detail {
/*!Trait class to detect if an allocator has
a templatized construct function. If this is the case
in node containers we only need just one allocator
instead of three*/
template <class Allocator>
struct has_convertible_construct
{
enum { value = false };
};
/*!Trait class to detect if an index is a node
index. This allows more efficient operations
when deallocating named objects.*/
@@ -351,295 +331,15 @@ class deleter
{ mp_deleter->destroy_ptr(detail::get_pointer(p)); }
};
template <class T, class Difference = std::ptrdiff_t>
class constant_iterator
: public boost::iterator_facade
< constant_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, const T &
, Difference>
{
typedef boost::iterator_facade
< constant_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, const T &
, Difference> super_t;
typedef constant_iterator<T, Difference> this_type;
//Give access to private core functions
friend class boost::iterator_core_access;
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){}
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; }
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 repeat_iterator
: public boost::iterator_facade
< repeat_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, T &
, Difference>
{
typedef boost::iterator_facade
< repeat_iterator<T, Difference>
, T
, boost::random_access_traversal_tag
, T &
, Difference> super_t;
typedef repeat_iterator<T, Difference> this_type;
//Give access to private core functions
friend class boost::iterator_core_access;
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){}
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; }
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 FwdIt, class Count, class T, class Alloc> inline
void uninitialized_fill_n(FwdIt first, Count count,
const T& val, Alloc& al)
{
//Save initial position
FwdIt init = first;
BOOST_TRY{
//Construct objects
for (; count--; ++first){
al.construct(first, val);
}
}
BOOST_CATCH(...){
//Call destructors
for (; init != first; ++init){
al.destroy(init);
}
BOOST_RETHROW;
}
BOOST_CATCH_END
}
template<class InIt, class OutIt>
InIt copy_n(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest)
{
for (; length--; ++dest, ++first)
*dest = *first;
return first;
}
template<class InIt, class FwdIt, class Alloc> inline
typename std::iterator_traits<InIt>::difference_type
n_uninitialized_copy(InIt first, InIt last,
FwdIt dest, Alloc& al)
{
//Save initial destination position
FwdIt dest_init = dest;
typename std::iterator_traits<InIt>::difference_type constructed = 0;
BOOST_TRY{
//Try to build objects
for (; first != last; ++dest, ++first, ++constructed){
al.construct(dest, *first);
}
}
BOOST_CATCH(...){
//Call destructors
for (; dest_init != dest; ++dest_init){
al.destroy(dest_init);
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return (constructed);
}
template<class InIt, class FwdIt, class Alloc> inline
FwdIt uninitialized_copy(InIt first, InIt last,
FwdIt dest, Alloc& al)
{
//Save initial destination position
FwdIt dest_init = dest;
typename std::iterator_traits<InIt>::difference_type constructed = 0;
BOOST_TRY{
//Try to build objects
for (; first != last; ++dest, ++first, ++constructed){
al.construct(dest, *first);
}
}
BOOST_CATCH(...){
//Call destructors
for (; dest_init != dest; ++dest_init){
al.destroy(dest_init);
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return (dest);
}
template<class InIt, class FwdIt, class Alloc> inline
InIt n_uninitialized_copy_n
(InIt first,
typename std::iterator_traits<InIt>::difference_type count,
FwdIt dest, Alloc& al)
{
//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){
al.construct(dest, *first);
}
}
BOOST_CATCH(...){
//Call destructors
new_count = count - new_count;
for (; new_count--; ++dest_init){
al.destroy(dest_init);
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return first;
}
// 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, class Alloc>
FwdIt uninitialized_copy_copy(InpIt1 first1, InpIt1 last1,
InpIt2 first2, InpIt2 last2,
FwdIt result, Alloc &alloc)
{
FwdIt mid = uninitialized_copy(first1, last1, result, alloc);
BOOST_TRY {
return uninitialized_copy(first2, last2, mid, alloc);
}
BOOST_CATCH(...){
for(;result != mid; ++result){
alloc.destroy(&*result);
}
BOOST_RETHROW
}
BOOST_CATCH_END
}
// uninitialized_copy_n_copy_n
// Copies [first1, first1 + n1) into [result, result + n1), and
// copies [first2, first2 + n2) into
// [result + n1, result + n1 + n2).
template <class InpIt1, class InpIt2, class FwdIt, class Alloc>
InpIt2 uninitialized_copy_n_copy_n
(InpIt1 first1,
typename std::iterator_traits<InpIt1>::difference_type n1,
InpIt2 first2,
typename std::iterator_traits<InpIt2>::difference_type n2,
FwdIt result,
Alloc &alloc)
{
typename std::iterator_traits<InpIt1>::difference_type c1 = n1+1;
typename std::iterator_traits<InpIt2>::difference_type c2 = n2+1;
FwdIt dest_init = result;
BOOST_TRY{
//Try to build objects
for (; --c1; ++result, ++first1){
alloc.construct(result, *first1);
}
for (; --c2; ++result, ++first2){
alloc.construct(result, *first2);
}
}
BOOST_CATCH(...){
//Call destructors
typename std::iterator_traits<FwdIt>::
difference_type c = (n1 - c1) + (n2 - c2);
for (; c--; ++dest_init){
alloc.destroy(dest_init);
}
BOOST_RETHROW;
}
BOOST_CATCH_END
return first2;
}
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 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");
*/
{
// if (n > max_size - capacity)
// throw std::length_error("get_next_capacity");
const SizeType m3 = max_size/3;
if (capacity < m3)
@@ -653,44 +353,6 @@ SizeType
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 boost::remove_reference<D>::type>::type type;
};
template <class T1, class T2>
struct pair
{
@@ -713,31 +375,67 @@ struct pair
: first(p.first), second(p.second)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
pair(const detail::moved_object<std::pair<D, S> >& p)
: first(move(p.get().first)), second(move(p.get().second))
{}
#else
template <class D, class S>
pair(std::pair<D, S> && p)
: first(move(p.first)), second(move(p.second))
{}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
pair(const detail::moved_object<pair<D, S> >& p)
: first(move(p.get().first)), second(move(p.get().second))
{}
#else
template <class D, class S>
pair(pair<D, S> && p)
: first(move(p.first)), second(move(p.second))
{}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class U, class V>
pair(const detail::moved_object<U> &x, const detail::moved_object<V> &y)
: first(move(x.get())), second(move(y.get()))
{}
#else
template <class U, class V>
pair(U &&x, V &&y)
: first(move(x)), second(move(y))
{}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
pair(const detail::moved_object<pair> &p)
: first(move(p.get().first)), second(move(p.get().second))
{}
#else
pair(pair &&p)
: first(move(p.first)), second(move(p.second))
{}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
pair& operator=(const detail::moved_object<pair> &p)
{
first = move(p.get().first);
second = move(p.get().second);
return *this;
}
#else
pair& operator=(pair &&p)
{
first = move(p.first);
second = move(p.second);
return *this;
}
#endif
pair& operator=(const pair &p)
{
@@ -746,6 +444,7 @@ struct pair
return *this;
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
pair& operator=(const detail::moved_object<std::pair<D, S> > &p)
{
@@ -753,12 +452,27 @@ struct pair
second = move(p.get().second);
return *this;
}
#else
template <class D, class S>
pair& operator=(std::pair<D, S> &&p)
{
first = move(p.first);
second = move(p.second);
return *this;
}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<pair> &p)
{ std::swap(*this, p.get()); }
void swap(pair& p)
{ std::swap(*this, p); }
#else
void swap(pair &&p)
{ std::swap(*this, p); }
#endif
};
template <class T1, class T2>
@@ -790,6 +504,7 @@ template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{ return pair<T1, T2>(x, y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class T1, class T2>
inline void swap(const detail::moved_object<pair<T1, T2> > &x, pair<T1, T2>& y)
{
@@ -811,6 +526,15 @@ inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
swap(x.second, y.second);
}
#else
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);
}
#endif
} //namespace detail {
//!The pair is movable if any of its members is movable
@@ -832,9 +556,7 @@ struct is_movable<std::pair<T1, T2> >
template <class T>
struct has_trivial_destructor_after_move
: public boost::has_trivial_destructor<T>
{
enum{ value = false };
};
{};
enum create_enum_t
{ DoCreate, DoOpen, DoCreateOrOpen };

View File

@@ -221,11 +221,13 @@ extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned lo
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) long __stdcall InterlockedIncrement( long volatile * );
extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement( long volatile * );
extern "C" __declspec(dllimport) long __stdcall InterlockedCompareExchange( long volatile *, long, long );
extern "C" __declspec(dllimport) long __stdcall InterlockedExchangeAdd(long volatile *, long);
extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long);
*/
} //namespace winapi {
} //namespace interprocess {
@@ -346,19 +348,19 @@ static inline bool unlock_file_ex(void *hnd, unsigned long reserved, unsigned lo
{ return 0 != UnlockFileEx(hnd, reserved, size_low, size_high, overlapped); }
static inline long interlocked_increment(long volatile *addr)
{ return InterlockedIncrement(addr); }
{ return BOOST_INTERLOCKED_INCREMENT(addr); }
static inline long interlocked_decrement(long volatile *addr)
{ return InterlockedDecrement(addr); }
{ return BOOST_INTERLOCKED_DECREMENT(addr); }
static inline long interlocked_compare_exchange(long volatile *addr, long val1, long val2)
{ return InterlockedCompareExchange(addr, val1, val2); }
{ return BOOST_INTERLOCKED_COMPARE_EXCHANGE(addr, val1, val2); }
static inline long interlocked_exchange_add(long volatile* addend, long value)
{ return InterlockedExchangeAdd((long*)addend, value); }
{ return BOOST_INTERLOCKED_EXCHANGE_ADD((long*)addend, value); }
static inline long interlocked_exchange(long volatile* addend, long value)
{ return InterlockedExchange((long*)addend, value); }
{ return BOOST_INTERLOCKED_EXCHANGE((long*)addend, value); }
} //namespace winapi
} //namespace interprocess

View File

@@ -18,19 +18,6 @@
#include <boost/iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#ifndef BOOST_INTERPROCESS_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
#if defined (BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
#define BOOST_INTERPROCESS_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
#endif
#endif
#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
// old Dinkumware
# include <boost/compatibility/cpp_c_headers/cstddef>
#else
# include <cstddef>
#endif
#if !(defined BOOST_WINDOWS) || (defined BOOST_DISABLE_WIN32)
#if defined(_POSIX_THREAD_PROCESS_SHARED) && (_POSIX_THREAD_PROCESS_SHARED - 0 > 0)
#if !defined(__CYGWIN__)
@@ -68,12 +55,26 @@
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)
// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are
// passed on the command line, which in turn defines
// __GXX_EXPERIMENTAL_CXX0X__. Note: __GXX_EXPERIMENTAL_CPP0X__ is
// defined by some very early development versions of GCC 4.3; we will
// remove this part of the check in the near future.
# if defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(__GXX_EXPERIMENTAL_CXX0X__)
# define BOOST_INTERPROCESS_RVALUE_REFERENCE
# define BOOST_INTERPROCESS_VARIADIC_TEMPLATES
# endif
#endif
#if defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) || defined(BOOST_INTERPROCESS_VARIADIC_TEMPLATES)
#define BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif
namespace boost {
namespace interprocess {
namespace workaround{
namespace workaround
{
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*//
// //
// We want generally const_shm_ptr to inherit//

View File

@@ -54,12 +54,18 @@ class file_mapping
/*!Moves the ownership of "moved"'s shared memory object to *this.
After the call, "moved" does not represent any shared memory object.
Does not throw*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
file_mapping(detail::moved_object<file_mapping> &moved)
{ this->swap(moved.get()); }
#else
file_mapping(file_mapping &&moved)
{ this->swap(moved); }
#endif
/*!Moves the ownership of "moved"'s shared memory to *this.
After the call, "moved" does not represent any shared memory.
Does not throw*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
file_mapping &operator=
(detail::moved_object<file_mapping> &moved)
{
@@ -67,6 +73,14 @@ class file_mapping
this->swap(tmp);
return *this;
}
#else
file_mapping &operator=(file_mapping &&moved)
{
file_mapping tmp(move(moved));
this->swap(tmp);
return *this;
}
#endif
/*!Swaps to file_mappings. Does not throw*/
void swap(file_mapping &other);

View File

@@ -33,11 +33,11 @@ struct flat_map_index_aux
typedef typename MapConfig::key_type key_type;
typedef typename MapConfig::mapped_type mapped_type;
typedef typename MapConfig::
restricted_segment_manager restricted_segment_manager;
basic_segment_manager basic_segment_manager;
typedef std::less<key_type> key_less;
typedef std::pair<key_type, mapped_type> value_type;
typedef allocator<value_type
,restricted_segment_manager> allocator_type;
,basic_segment_manager> allocator_type;
typedef flat_map<key_type, mapped_type,
key_less, allocator_type> index_t;
};
@@ -53,12 +53,12 @@ class flat_map_index
typedef flat_map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef typename index_aux::
restricted_segment_manager restricted_segment_manager;
basic_segment_manager basic_segment_manager;
/// @endcond
public:
//!Constructor. Takes a pointer to the segment manager. Can throw
flat_map_index(restricted_segment_manager *segment_mngr)
flat_map_index(basic_segment_manager *segment_mngr)
: base_type(typename index_aux::key_less(),
typename index_aux::allocator_type(segment_mngr))
{}

View File

@@ -34,10 +34,10 @@ template <class MapConfig>
struct iset_index_aux
{
typedef typename
MapConfig::restricted_segment_manager restricted_segment_manager;
MapConfig::basic_segment_manager basic_segment_manager;
typedef typename
restricted_segment_manager::void_pointer void_pointer;
basic_segment_manager::void_pointer void_pointer;
typedef boost::intrusive::set_base_hook
< boost::intrusive::tag
@@ -86,7 +86,7 @@ class iset_index
{
bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
{
std::size_t blen = b.length();
std::size_t blen = b.name_length();
return (i.m_len < blen) ||
(i.m_len == blen &&
std::char_traits<char_type>::compare
@@ -95,7 +95,7 @@ class iset_index
bool operator()(const value_type &b, const intrusive_compare_key_type &i) const
{
std::size_t blen = b.length();
std::size_t blen = b.name_length();
return (blen < i.m_len) ||
(blen == i.m_len &&
std::char_traits<char_type>::compare
@@ -109,7 +109,7 @@ class iset_index
/*!Constructor. Takes a pointer to the
segment manager. Can throw*/
iset_index(typename MapConfig::restricted_segment_manager *)
iset_index(typename MapConfig::basic_segment_manager *)
: index_type(/*typename index_aux::value_compare()*/)
{}

View File

@@ -35,10 +35,10 @@ template <class MapConfig>
struct iunordered_set_index_aux
{
typedef typename
MapConfig::restricted_segment_manager restricted_segment_manager;
MapConfig::basic_segment_manager basic_segment_manager;
typedef typename
restricted_segment_manager::void_pointer void_pointer;
basic_segment_manager::void_pointer void_pointer;
typedef boost::intrusive::unordered_set_base_hook
< boost::intrusive::tag
@@ -59,23 +59,23 @@ struct iunordered_set_index_aux
{
bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
{
return (i.m_len == b.length()) &&
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.length()) &&
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.length() == b2.length()) &&
return (b1.name_length() == b2.name_length()) &&
(std::char_traits<char_type>::compare
(b1.name(), b2.name(), b1.length()) == 0);
(b1.name(), b2.name(), b1.name_length()) == 0);
}
};
@@ -85,7 +85,7 @@ struct iunordered_set_index_aux
std::size_t operator()(const value_type &val) const
{
const char_type *beg = detail::get_pointer(val.name()),
*end = beg + val.length();
*end = beg + val.name_length();
return boost::hash_range(beg, end);
}
@@ -104,11 +104,11 @@ struct iunordered_set_index_aux
typedef typename index_t::bucket_type bucket_type;
typedef allocator
<bucket_type, restricted_segment_manager> allocator_type;
<bucket_type, basic_segment_manager> allocator_type;
struct allocator_holder
{
allocator_holder(restricted_segment_manager *mngr)
allocator_holder(basic_segment_manager *mngr)
: alloc(mngr)
{}
allocator_type alloc;
@@ -131,7 +131,6 @@ class iunordered_set_index
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 index_aux::bucket_type bucket_type;
typedef typename MapConfig::char_type char_type;
typedef typename
iunordered_set_index_aux<MapConfig>::allocator_type allocator_type;
@@ -145,12 +144,13 @@ class iunordered_set_index
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::size_type size_type;
/// @cond
private:
typedef typename index_aux::
restricted_segment_manager restricted_segment_manager;
basic_segment_manager basic_segment_manager;
enum { InitBufferSize = 64};
@@ -160,7 +160,7 @@ class iunordered_set_index
bucket_ptr buckets = alloc.allocate(num);
bucket_ptr buckets_init = buckets;
for(std::size_t i = 0; i < num; ++i){
alloc.construct(buckets_init++);
new(get_pointer(buckets_init++))bucket_type();
}
return buckets;
}
@@ -170,7 +170,7 @@ class iunordered_set_index
{
bucket_ptr buckets_destroy = buckets;
for(std::size_t i = 0; i < num; ++i){
alloc.destroy(buckets_destroy++);
get_pointer(buckets_destroy++)->~bucket_type();
}
alloc.deallocate(buckets, num);
}
@@ -179,7 +179,7 @@ class iunordered_set_index
public:
/*!Constructor. Takes a pointer to the
segment manager. Can throw*/
iunordered_set_index(restricted_segment_manager *mngr)
iunordered_set_index(basic_segment_manager *mngr)
: allocator_holder(mngr)
, index_type
(create_buckets( allocator_holder::alloc

View File

@@ -38,7 +38,7 @@ struct map_index_aux
typedef private_adaptive_pool
<value_type,
typename MapConfig::
restricted_segment_manager> allocator_type;
basic_segment_manager> allocator_type;
typedef boost::interprocess::map
<key_type, mapped_type,
@@ -56,13 +56,13 @@ class map_index
typedef map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef typename MapConfig::
restricted_segment_manager restricted_segment_manager;
basic_segment_manager basic_segment_manager;
/// @endcond
public:
/*!Constructor. Takes a pointer to the
segment manager. Can throw*/
map_index(restricted_segment_manager *segment_mngr)
map_index(basic_segment_manager *segment_mngr)
: base_type(typename index_aux::key_less(),
segment_mngr){}

View File

@@ -28,7 +28,7 @@ class null_index
{
/// @cond
typedef typename MapConfig::
restricted_segment_manager restricted_segment_manager;
basic_segment_manager basic_segment_manager;
/// @endcond
public:
@@ -48,7 +48,7 @@ class null_index
{ return iterator(0); }
/*!Dummy function*/
null_index(restricted_segment_manager *){}
null_index(basic_segment_manager *){}
};
}} //namespace boost { namespace interprocess {

View File

@@ -38,7 +38,7 @@ struct unordered_map_index_aux
typedef private_adaptive_pool
<value_type,
typename MapConfig::
restricted_segment_manager> allocator_type;
basic_segment_manager> allocator_type;
struct hasher
: std::unary_function<key_type, std::size_t>
{
@@ -65,13 +65,13 @@ class unordered_map_index
typedef unordered_map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef typename
MapConfig::restricted_segment_manager restricted_segment_manager;
MapConfig::basic_segment_manager basic_segment_manager;
/// @endcond
public:
/*!Constructor. Takes a pointer to the
segment manager. Can throw*/
unordered_map_index(restricted_segment_manager *segment_mngr)
unordered_map_index(basic_segment_manager *segment_mngr)
: base_type(0,
typename index_aux::hasher(),
typename index_aux::key_equal(),

View File

@@ -22,6 +22,7 @@
#include <boost/interprocess/offset_ptr.hpp>
#include <boost/interprocess/detail/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <algorithm> //std::lower_bound

View File

@@ -65,14 +65,26 @@ class basic_managed_external_buffer
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_external_buffer
(detail::moved_object<basic_managed_external_buffer> &moved)
{ this->swap(moved.get()); }
#else
basic_managed_external_buffer
(basic_managed_external_buffer &&moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_external_buffer &operator=
(detail::moved_object<basic_managed_external_buffer> &moved)
{ this->swap(moved.get()); return *this; }
#else
basic_managed_external_buffer &operator=
(basic_managed_external_buffer &&moved)
{ this->swap(moved); return *this; }
#endif
void grow(std::size_t extra_bytes)
{ base_t::grow(extra_bytes); }

View File

@@ -101,15 +101,26 @@ class basic_managed_heap_memory
}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_heap_memory
(detail::moved_object<basic_managed_heap_memory> &moved)
{ this->swap(moved.get()); }
#else
basic_managed_heap_memory(basic_managed_heap_memory &&moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_heap_memory &operator=
(detail::moved_object<basic_managed_heap_memory> &moved)
{ this->swap(moved.get()); return *this; }
#else
basic_managed_heap_memory &operator=
(basic_managed_heap_memory &&moved)
{ this->swap(moved); return *this; }
#endif
//!Tries to resize internal heap memory so that
//!we have room for more objects.
//!WARNING: If memory is reallocated, all the objects will

View File

@@ -87,14 +87,24 @@ class basic_managed_mapped_file
{}
/*!Moves the ownership of "moved"'s managed memory to *this. Does not throw*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_mapped_file
(detail::moved_object<basic_managed_mapped_file> &moved)
{ this->swap(moved.get()); }
#else
basic_managed_mapped_file(basic_managed_mapped_file &&moved)
{ this->swap(moved); }
#endif
/*!Moves the ownership of "moved"'s managed memory to *this. Does not throw*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_mapped_file &operator=
(detail::moved_object<basic_managed_mapped_file> &moved)
{ this->swap(moved.get()); return *this; }
#else
basic_managed_mapped_file &operator=(basic_managed_mapped_file &&moved)
{ this->swap(moved); return *this; }
#endif
/*!Destructor. Never throws.*/
~basic_managed_mapped_file()

View File

@@ -96,14 +96,24 @@ class basic_managed_shared_memory
{}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_shared_memory
(detail::moved_object<basic_managed_shared_memory> &moved)
{ this->swap(moved.get()); }
#else
basic_managed_shared_memory(basic_managed_shared_memory &&moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_shared_memory &operator=
(detail::moved_object<basic_managed_shared_memory> &moved)
{ this->swap(moved.get()); return *this; }
#else
basic_managed_shared_memory &operator=(basic_managed_shared_memory &&moved)
{ this->swap(moved); return *this; }
#endif
//!Swaps the ownership of the managed shared memories managed by *this and other.
//!Never throws.

View File

@@ -96,14 +96,25 @@ class basic_managed_windows_shared_memory
{}
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_windows_shared_memory
(detail::moved_object<basic_managed_windows_shared_memory> &moved)
{ this->swap(moved.get()); }
#else
basic_managed_windows_shared_memory(basic_managed_windows_shared_memory &&moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s managed memory to *this. Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
basic_managed_windows_shared_memory &operator=
(detail::moved_object<basic_managed_windows_shared_memory> &moved)
{ this->swap(moved.get()); return *this; }
#else
basic_managed_windows_shared_memory &operator=
(basic_managed_windows_shared_memory &&moved)
{ this->swap(moved); return *this; }
#endif
//!Destructor. Never throws.
~basic_managed_windows_shared_memory()

View File

@@ -71,14 +71,22 @@ class mapped_region
/*!Move constructor. *this will be constructed taking ownership of "other"'s
region and "other" will be left in default constructor state.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
mapped_region(detail::moved_object<mapped_region> other);
#else
mapped_region(mapped_region &&other);
#endif
/*!Destroys the mapped region. Does not throw*/
~mapped_region();
/*!Move assignment. If *this owns a memory mapped region, it will be
destroyed and it will take ownership of "other"'s memory mapped region.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
mapped_region &operator=(detail::moved_object<mapped_region> other);
#else
mapped_region &operator=(mapped_region &&other);
#endif
/*!Returns the size of the mapping. Note for windows users: If
windows_shared_memory is mapped using 0 as the size, it returns 0
@@ -128,8 +136,13 @@ class mapped_region
inline void swap(mapped_region &x, mapped_region &y)
{ x.swap(y); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
inline mapped_region &mapped_region::operator=(detail::moved_object<mapped_region> other)
{ this->swap(other.get()); return *this; }
#else
inline mapped_region &mapped_region::operator=(mapped_region &&other)
{ this->swap(other); return *this; }
#endif
inline mapped_region::~mapped_region()
{ this->priv_close(); }
@@ -150,11 +163,19 @@ inline mapped_region::mapped_region()
, m_file_mapping_hnd(0)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
inline mapped_region::mapped_region(detail::moved_object<mapped_region> other)
: m_base(0), m_size(0), m_offset(0)
, m_extra_offset(0)
, m_file_mapping_hnd(0)
{ this->swap(other.get()); }
#else
inline mapped_region::mapped_region(mapped_region &&other)
: m_base(0), m_size(0), m_offset(0)
, m_extra_offset(0)
, m_file_mapping_hnd(0)
{ this->swap(other); }
#endif
template<int dummy>
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
@@ -335,10 +356,17 @@ inline mapped_region::mapped_region()
: m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
inline mapped_region::mapped_region(detail::moved_object<mapped_region> other)
: m_base(MAP_FAILED), m_size(0), m_offset(0)
, m_extra_offset(0)
{ this->swap(other.get()); }
#else
inline mapped_region::mapped_region(mapped_region &&other)
: m_base(MAP_FAILED), m_size(0), m_offset(0)
, m_extra_offset(0)
{ this->swap(other); }
#endif
template<int dummy>
inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()

View File

@@ -24,6 +24,7 @@
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
@@ -137,6 +138,9 @@ class simple_seq_fit_impl
/*!Returns the size of the memory segment*/
std::size_t get_size() const;
/*!Returns the number of free bytes of the memory segment*/
std::size_t get_free_memory() const;
/*!Increases managed memory in extra_size bytes more*/
void grow(std::size_t extra_size);
@@ -148,7 +152,7 @@ class simple_seq_fit_impl
//!Initializes to zero all the memory that's not in use.
//!This function is normally used for security reasons.
void clear_free_memory();
void zero_free_memory();
std::pair<void *, bool>
allocation_command (allocation_type command, std::size_t limit_size,
@@ -288,6 +292,13 @@ template<class MutexFamily, class VoidPointer>
inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::get_size() const
{ return m_header.m_size; }
template<class MutexFamily, class VoidPointer>
inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::get_free_memory() const
{
return m_header.m_size - m_header.m_allocated -
((char*)detail::get_pointer(m_header.m_root.m_next) - (char*)this);
}
template<class MutexFamily, class VoidPointer>
inline std::size_t simple_seq_fit_impl<MutexFamily, VoidPointer>::
get_min_size (std::size_t extra_hdr_bytes)
@@ -309,7 +320,7 @@ inline bool simple_seq_fit_impl<MutexFamily, VoidPointer>::
}
template<class MutexFamily, class VoidPointer>
inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::clear_free_memory()
inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::zero_free_memory()
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
@@ -448,7 +459,6 @@ void* simple_seq_fit_impl<MutexFamily, VoidPointer>::
detail::get_rounded_size(preferred_size - extra_forward, Alignment);
if(!only_preferred_backwards){
needs_backwards =
max_value(detail::get_rounded_size(min_size - extra_forward, Alignment)
,min_value(prev->get_user_bytes(), needs_backwards));
}

View File

@@ -24,6 +24,7 @@
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/detail/gcd_lcm.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
@@ -80,10 +81,10 @@ class rbtree_best_fit
{
//!This block's memory size (including block_ctrl
//!header) in Alignment units
unsigned m_prev_size : sizeof(std::size_t)*CHAR_BIT - 1;
unsigned m_end : 1;
unsigned m_size : sizeof(std::size_t)*CHAR_BIT - 1;
unsigned m_allocated : 1;
std::size_t m_prev_size : sizeof(std::size_t)*CHAR_BIT - 1;
std::size_t m_end : 1;
std::size_t m_size : sizeof(std::size_t)*CHAR_BIT - 1;
std::size_t m_allocated : 1;
};
//!Block control structure
@@ -153,9 +154,12 @@ class rbtree_best_fit
//!Returns the size of the memory segment
std::size_t get_size() const;
//!Returns the number of free bytes of the segment
std::size_t get_free_memory() const;
//!Initializes to zero all the memory that's not in use.
//!This function is normally used for security reasons.
void clear_free_memory();
void zero_free_memory();
//!Increases managed memory in extra_size bytes more
void grow(std::size_t extra_size);
@@ -410,6 +414,13 @@ template<class MutexFamily, class VoidPointer>
inline std::size_t rbtree_best_fit<MutexFamily, VoidPointer>::get_size() const
{ return m_header.m_size; }
template<class MutexFamily, class VoidPointer>
inline std::size_t rbtree_best_fit<MutexFamily, VoidPointer>::get_free_memory() const
{
return m_header.m_size - m_header.m_allocated -
priv_multiple_of_units(sizeof(*this) + m_header.m_extra_hdr_bytes);
}
template<class MutexFamily, class VoidPointer>
inline std::size_t rbtree_best_fit<MutexFamily, VoidPointer>::
get_min_size (std::size_t extra_hdr_bytes)
@@ -510,7 +521,7 @@ inline std::size_t rbtree_best_fit<MutexFamily, VoidPointer>::
}
template<class MutexFamily, class VoidPointer>
inline void rbtree_best_fit<MutexFamily, VoidPointer>::clear_free_memory()
inline void rbtree_best_fit<MutexFamily, VoidPointer>::zero_free_memory()
{
//-----------------------
boost::interprocess::scoped_lock<interprocess_mutex> guard(m_header);
@@ -1182,7 +1193,7 @@ void* rbtree_best_fit<MutexFamily, VoidPointer>::priv_check_and_allocate
priv_check_alignment(block);
//Clear the memory occupied by the tree hook, since this won't be
//cleared with clear_free_memory
//cleared with zero_free_memory
TreeHook *t = static_cast<TreeHook*>(block);
std::memset(t, 0, sizeof(*t));
return priv_get_user_buffer(block);

View File

@@ -23,9 +23,6 @@
#include <boost/interprocess/detail/cast_tags.hpp>
#include <boost/interprocess/detail/generic_cast.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/alignment_of.hpp>
/*!\file
Describes a smart pointer that stores the offset between this pointer and
@@ -33,6 +30,13 @@
*/
namespace boost {
//Predeclarations
template <class T>
struct has_trivial_constructor;
template <class T>
struct has_trivial_destructor;
namespace interprocess {
/*!A smart pointer that stores the offset between between the pointer and the
@@ -320,15 +324,13 @@ inline boost::interprocess::offset_ptr<T>
/// @cond
//!has_trivial_constructor<> == true_type specialization for optimizations
template <class T>
struct has_trivial_constructor
< boost::interprocess::offset_ptr<T> >
struct has_trivial_constructor< boost::interprocess::offset_ptr<T> >
: public true_type
{};
///has_trivial_destructor<> == true_type specialization for optimizations
template <class T>
struct has_trivial_destructor
< boost::interprocess::offset_ptr<T> >
struct has_trivial_destructor< boost::interprocess::offset_ptr<T> >
: public true_type
{};
@@ -380,13 +382,13 @@ class cast_to< offset_ptr<T> >
namespace intrusive {
//Predeclaration to avoid including header
template<class Pointer>
template<class VoidPointer, std::size_t N>
struct has_pointer_plus_bit;
template<class T>
struct has_pointer_plus_bit<boost::interprocess::offset_ptr<T> >
template<std::size_t N>
struct has_pointer_plus_bit<boost::interprocess::offset_ptr<void>, N>
{
enum { value = (boost::alignment_of<T>::value % 4u) == 0 };
enum { value = (N % 4u) == 0 };
};
//Predeclaration

File diff suppressed because it is too large Load Diff

View File

@@ -75,13 +75,19 @@ class shared_memory_object
//!Moves the ownership of "moved"'s shared memory object to *this.
//!After the call, "moved" does not represent any shared memory object.
//!Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
shared_memory_object
(detail::moved_object<shared_memory_object> &moved)
{ this->swap(moved.get()); }
#else
shared_memory_object(shared_memory_object &&moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s shared memory to *this.
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
shared_memory_object &operator=
(detail::moved_object<shared_memory_object> &moved)
{
@@ -89,6 +95,14 @@ class shared_memory_object
this->swap(tmp);
return *this;
}
#else
shared_memory_object &operator=(shared_memory_object &&moved)
{
shared_memory_object tmp(move(moved));
this->swap(tmp);
return *this;
}
#endif
//!Swaps the shared_memory_objects. Does not throw
void swap(shared_memory_object &other);
@@ -122,8 +136,8 @@ class shared_memory_object
bool priv_open_or_create(create_enum_t type, const char *filename, mode_t mode);
file_handle_t m_handle;
mode_t m_mode;
std::string m_filename;
mode_t m_mode;
std::string m_filename;
/// @endcond
};
@@ -261,10 +275,15 @@ inline bool shared_memory_object::priv_open_or_create
const char *filename,
mode_t mode)
{
m_filename = filename;
bool slash_added = filename[0] != '/';
//First add precedding "/"
m_filename.clear();
if(slash_added){
m_filename = '/';
}
m_filename += filename;
//Create new mapping
int oflag = 0;
if(mode == read_only){
oflag |= O_RDONLY;
@@ -295,7 +314,7 @@ inline bool shared_memory_object::priv_open_or_create
}
//Open file using POSIX API
m_handle = shm_open(filename, oflag, S_IRWXO | S_IRWXG | S_IRWXU);
m_handle = shm_open(m_filename.c_str(), oflag, S_IRWXO | S_IRWXG | S_IRWXU);
//Check for error
if(m_handle == -1){
@@ -304,13 +323,28 @@ inline bool shared_memory_object::priv_open_or_create
throw interprocess_exception(err);
}
if(slash_added){
m_filename.erase(m_filename.begin());
}
m_mode = mode;
return true;
}
inline bool shared_memory_object::remove(const char *filename)
{
return 0 != shm_unlink(filename);
try{
std::string file_str;
//First add precedding "/"
if(filename[0] != '/'){
file_str = '/';
}
file_str += filename;
return 0 != shm_unlink(file_str.c_str());
}
catch(...){
return false;
}
}
inline void shared_memory_object::truncate(offset_t length)

View File

@@ -1,135 +0,0 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// This file is the adaptation for shared memory memory mapped
// files of boost/detail/sp_counted_base_pt.hpp
//
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright 2006 Ion Gaztanaga
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <typeinfo>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
namespace boost{
namespace interprocess{
namespace detail{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
mutable pthread_mutex_t m_mut;
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
detail::mutexattr_wrapper mut_attr;
detail::mutex_initializer mut(m_mut, mut_attr);
mut.release();
}
~sp_counted_base() // nothrow
{
int res = pthread_mutex_destroy(&m_mut);
assert(res == 0);(void)res;
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
/*
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
*/
void add_ref_copy()
{
pthread_mutex_lock( &m_mut );
++use_count_;
pthread_mutex_unlock( &m_mut );
}
bool add_ref_lock() // true on success
{
pthread_mutex_lock( &m_mut );
bool r = use_count_ == 0? false: ( ++use_count_, true );
pthread_mutex_unlock( &m_mut );
return r;
}
bool ref_release() // nothrow
{
pthread_mutex_lock( &m_mut );
long new_use_count = --use_count_;
pthread_mutex_unlock( &m_mut );
return new_use_count == 0;
}
void weak_add_ref() // nothrow
{
pthread_mutex_lock( &m_mut );
++weak_count_;
pthread_mutex_unlock( &m_mut );
}
bool weak_release() // nothrow
{
pthread_mutex_lock( &m_mut );
long new_weak_count = --weak_count_;
pthread_mutex_unlock( &m_mut );
return new_weak_count == 0;
}
long use_count() const // nothrow
{
pthread_mutex_lock( &m_mut );
long r = use_count_;
pthread_mutex_unlock( &m_mut );
return r;
}
};
} // namespace detail
} // namespace interprocess
} // namespace boost
#include <boost/interprocess/detail/config_end.hpp>
#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED

View File

@@ -1,119 +0,0 @@
#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// This file is the adaptation for shared memory memory mapped
// files of boost/detail/sp_counted_base_w32.hpp
//
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright 2006 Ion Gaztanaga
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/win32_api.hpp>
#include <typeinfo>
namespace boost {
namespace interprocess {
namespace detail {
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{}
~sp_counted_base() // nothrow
{}
/*
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( std::type_info const & ti ) = 0;
*/
void add_ref_copy()
{
winapi::interlocked_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
for( ;; )
{
long tmp = static_cast< long const volatile& >( use_count_ );
if( tmp == 0 ) return false;
if( winapi::interlocked_compare_exchange( &use_count_, tmp + 1, tmp ) == tmp ) return true;
}
}
bool ref_release() // nothrow
{ return winapi::interlocked_decrement( &use_count_ ) == 0; }
/*
void release() // nothrow
{
if(ref_release()){
//dispose();
weak_release();
}
}
*/
void weak_add_ref() // nothrow
{ winapi::interlocked_increment( &weak_count_ ); }
bool weak_release() // nothrow
{ return winapi::interlocked_decrement( &weak_count_ ) == 0; }
long use_count() const // nothrow
{ return static_cast<long const volatile &>( use_count_ ); }
};
} // namespace detail
} // namespace interprocess
} // namespace boost
#include <boost/interprocess/detail/config_end.hpp>
#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED

View File

@@ -28,8 +28,7 @@
#include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
#include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <functional>
#include <boost/detail/no_exceptions_support.hpp>
#include <functional> // std::less
namespace boost {
@@ -84,7 +83,7 @@ class shared_count
m_pi = alloc.allocate(1);
//Anti-exception deallocator
scoped_ptr<counted_impl,
scoped_deallocator<counted_impl_allocator> >
scoped_ptr_deallocator<counted_impl_allocator> >
deallocator(m_pi, alloc);
//It's more correct to use A::construct but
//this needs copy constructor and we don't like it

View File

@@ -84,8 +84,9 @@ class sp_counted_impl_pd
this_pointer this_ptr (this);
//Do it now!
scoped_ptr<this_type,
scoped_deallocator<this_allocator> >(this_ptr, a_copy);
a_copy.destroy(this_ptr);
scoped_ptr_deallocator<this_allocator> >(this_ptr, a_copy);
typedef typename this_allocator::value_type value_type;
detail::get_pointer(this_ptr)->~value_type();
}
void release() // nothrow

View File

@@ -20,10 +20,11 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/assert.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/pointer_type.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/compressed_pair.hpp>
#include <boost/static_assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <cstddef>
@@ -103,7 +104,7 @@ class unique_ptr
{}
unique_ptr(pointer p
,typename boost::mpl::if_<boost::is_reference<D>
,typename if_<boost::is_reference<D>
,D
,typename boost::add_reference<const D>::type>::type d)
: ptr_(p, d)
@@ -113,9 +114,15 @@ class unique_ptr
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter())
{}
*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
unique_ptr(detail::moved_object<unique_ptr> u)
: ptr_(u.get().release(), u.get().get_deleter())
{}
#else
unique_ptr(unique_ptr &&u)
: ptr_(u.release(), u.get_deleter())
{}
#endif
/*
template <class U, class E>
unique_ptr(const unique_ptr<U, E>& u,
@@ -132,6 +139,7 @@ class unique_ptr
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), u.get_deleter())
{}
*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class U, class E>
unique_ptr(const detail::moved_object<unique_ptr<U, E> >& u,
typename boost::enable_if_c<
@@ -146,6 +154,22 @@ class unique_ptr
>::type = nat())
: ptr_(const_cast<unique_ptr<U,E>&>(u.get()).release(), u.get().get_deleter())
{}
#else
template <class U, class E>
unique_ptr(unique_ptr<U, E> && u,
typename boost::enable_if_c<
boost::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
boost::is_convertible<E, D>::value &&
(
!boost::is_reference<D>::value ||
boost::is_same<D, E>::value
)
,
nat
>::type = nat())
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), u.get_deleter())
{}
#endif
// destructor
~unique_ptr()
@@ -211,11 +235,16 @@ class unique_ptr
}
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(unique_ptr& u)
{ ptr_.swap(u.ptr_); }
void swap(detail::moved_object<unique_ptr> mu)
{ ptr_.swap(mu.get().ptr_); }
#else
void swap(unique_ptr&&u)
{ ptr_.swap(u.ptr_); }
#endif
/// @cond
private:
@@ -247,7 +276,7 @@ public:
// constructors
unique_ptr() : ptr_(pointer()) {}
explicit unique_ptr(pointer p) : ptr_(p) {}
unique_ptr(pointer p, typename boost::mpl::if_<
unique_ptr(pointer p, typename if_<
boost::is_reference<D>,
D,
typename boost::add_reference<const D>::type>::type d)
@@ -326,7 +355,7 @@ public:
// constructors
unique_ptr() : ptr_(pointer()) {}
explicit unique_ptr(pointer p) : ptr_(p) {}
unique_ptr(pointer p, typename boost::mpl::if_<
unique_ptr(pointer p, typename if_<
boost::is_reference<D>,
D,
typename boost::add_reference<const D>::type>::type d)

View File

@@ -18,6 +18,7 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/smart_ptr/shared_ptr.hpp>
#include <boost/detail/no_exceptions_support.hpp>
namespace boost{
namespace interprocess{

View File

@@ -127,9 +127,15 @@ class scoped_lock
can be moved with the expression: "move(lock);". This
constructor does not alter the state of the mutex, only potentially
who owns it.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
explicit scoped_lock(detail::moved_object<scoped_lock<Mutex> > scop)
: mp_mutex(0), m_locked(scop.get().owns())
{ mp_mutex = scop.get().release(); }
#else
explicit scoped_lock(scoped_lock<Mutex> &&scop)
: mp_mutex(0), m_locked(scop.owns())
{ mp_mutex = scop.release(); }
#endif
/*!Effects: If upgr.owns() then calls unlock_upgradable_and_lock() on the
referenced mutex. upgr.release() is called.
@@ -143,6 +149,7 @@ class scoped_lock
the expression: "move(lock);" This constructor may block if
other threads hold a sharable_lock on this mutex (sharable_lock's can
share ownership with an upgradable_lock).*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
explicit scoped_lock(detail::moved_object<upgradable_lock<Mutex> > upgr)
: mp_mutex(0), m_locked(false)
{
@@ -153,6 +160,18 @@ class scoped_lock
}
mp_mutex = u_lock.release();
}
#else
explicit scoped_lock(upgradable_lock<Mutex> &&upgr)
: mp_mutex(0), m_locked(false)
{
upgradable_lock<mutex_type> &u_lock = upgr;
if(u_lock.owns()){
u_lock.mutex()->unlock_upgradable_and_lock();
m_locked = true;
}
mp_mutex = u_lock.release();
}
#endif
/*!Effects: If upgr.owns() then calls try_unlock_upgradable_and_lock() on the
referenced mutex:
@@ -169,6 +188,7 @@ class scoped_lock
first place, the mutex merely changes type to an unlocked "write lock".
If the "read lock" is held, then mutex transfer occurs only if it can
do so in a non-blocking manner.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
scoped_lock(detail::moved_object<upgradable_lock<Mutex> > upgr
,detail::try_to_lock_type)
: mp_mutex(0), m_locked(false)
@@ -183,6 +203,22 @@ class scoped_lock
u_lock.release();
}
}
#else
scoped_lock(upgradable_lock<Mutex> &&upgr
,detail::try_to_lock_type)
: mp_mutex(0), m_locked(false)
{
upgradable_lock<mutex_type> &u_lock = upgr;
if(u_lock.owns()){
if((m_locked = u_lock.mutex()->try_unlock_upgradable_and_lock()) == true){
mp_mutex = u_lock.release();
}
}
else{
u_lock.release();
}
}
#endif
/*!Effects: If upgr.owns() then calls timed_unlock_upgradable_and_lock(abs_time)
on the referenced mutex:
@@ -198,6 +234,7 @@ class scoped_lock
"write lock". If the "read lock" isn't held in the first place, the mutex
merely changes type to an unlocked "write lock". If the "read lock" is held,
then mutex transfer occurs only if it can do so in a non-blocking manner.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
scoped_lock(detail::moved_object<upgradable_lock<Mutex> > upgr
,boost::posix_time::ptime &abs_time)
: mp_mutex(0), m_locked(false)
@@ -212,6 +249,22 @@ class scoped_lock
u_lock.release();
}
}
#else
scoped_lock(upgradable_lock<Mutex> &&upgr
,boost::posix_time::ptime &abs_time)
: mp_mutex(0), m_locked(false)
{
upgradable_lock<mutex_type> &u_lock = upgr;
if(u_lock.owns()){
if((m_locked = u_lock.mutex()->timed_unlock_upgradable_and_lock(abs_time)) == true){
mp_mutex = u_lock.release();
}
}
else{
u_lock.release();
}
}
#endif
/*!Effects: If shar.owns() then calls try_unlock_sharable_and_lock() on the
referenced mutex.
@@ -228,6 +281,7 @@ class scoped_lock
first place, the mutex merely changes type to an unlocked "write lock".
If the "read lock" is held, then mutex transfer occurs only if it can
do so in a non-blocking manner.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
scoped_lock(detail::moved_object<sharable_lock<Mutex> > shar
,detail::try_to_lock_type)
: mp_mutex(0), m_locked(false)
@@ -242,6 +296,22 @@ class scoped_lock
s_lock.release();
}
}
#else
scoped_lock(sharable_lock<Mutex> &&shar
,detail::try_to_lock_type)
: mp_mutex(0), m_locked(false)
{
sharable_lock<mutex_type> &s_lock = shar;
if(s_lock.owns()){
if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock()) == true){
mp_mutex = s_lock.release();
}
}
else{
s_lock.release();
}
}
#endif
/*!Effects: if (owns()) mp_mutex->unlock().
Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
@@ -257,6 +327,7 @@ class scoped_lock
the same mutex before the assignment. In this case, this will own the
mutex after the assignment (and scop will not), but the mutex's lock
count will be decremented by one.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
scoped_lock &operator=(detail::moved_object<scoped_lock<Mutex> > scop)
{
if(this->owns())
@@ -265,6 +336,16 @@ class scoped_lock
mp_mutex = scop.get().release();
return *this;
}
#else
scoped_lock &operator=(scoped_lock<Mutex> &&scop)
{
if(this->owns())
this->unlock();
m_locked = scop.owns();
mp_mutex = scop.release();
return *this;
}
#endif
/*!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
exception. Calls lock() on the referenced mutex.
@@ -348,11 +429,20 @@ class scoped_lock
/*!Effects: Swaps state with moved lock.
Throws: Nothing.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<scoped_lock<mutex_type> > other)
{
std::swap(mp_mutex, other.get().mp_mutex);
std::swap(m_locked, other.get().m_locked);
}
#else
void swap(scoped_lock<mutex_type> &&other)
{
std::swap(mp_mutex, other.mp_mutex);
std::swap(m_locked, other.m_locked);
}
#endif
/// @cond
private:
mutex_type *mp_mutex;

View File

@@ -130,9 +130,15 @@ class sharable_lock
signature. An non-moved sharable_lock can be moved with the expression:
"move(lock);". This constructor does not alter the state of the mutex,
only potentially who owns it.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
explicit sharable_lock(detail::moved_object<sharable_lock<mutex_type> > upgr)
: mp_mutex(0), m_locked(upgr.get().owns())
{ mp_mutex = upgr.get().release(); }
#else
explicit sharable_lock(sharable_lock<mutex_type> &&upgr)
: mp_mutex(0), m_locked(upgr.owns())
{ mp_mutex = upgr.release(); }
#endif
/*!Effects: If upgr.owns() then calls unlock_upgradable_and_lock_sharable() on the
referenced mutex.
@@ -143,6 +149,7 @@ class sharable_lock
unlocking upgr. Only a moved sharable_lock's will match this
signature. An non-moved upgradable_lock can be moved with the expression:
"move(lock);".*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
explicit sharable_lock(detail::moved_object<upgradable_lock<mutex_type> > upgr)
: mp_mutex(0), m_locked(false)
{
@@ -153,6 +160,18 @@ class sharable_lock
}
mp_mutex = u_lock.release();
}
#else
explicit sharable_lock(upgradable_lock<mutex_type> &&upgr)
: mp_mutex(0), m_locked(false)
{
upgradable_lock<mutex_type> &u_lock = upgr;
if(u_lock.owns()){
u_lock.mutex()->unlock_upgradable_and_lock_sharable();
m_locked = true;
}
mp_mutex = u_lock.release();
}
#endif
/*!Effects: If scop.owns() then calls unlock_and_lock_sharable() on the
referenced mutex.
@@ -164,6 +183,7 @@ class sharable_lock
Only a moved scoped_lock's will match this
signature. An non-moved scoped_lock can be moved with the expression:
"move(lock);".*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
explicit sharable_lock(detail::moved_object<scoped_lock<mutex_type> > scop)
: mp_mutex(0), m_locked(false)
{
@@ -174,6 +194,18 @@ class sharable_lock
}
mp_mutex = e_lock.release();
}
#else
explicit sharable_lock(scoped_lock<mutex_type> &&scop)
: mp_mutex(0), m_locked(false)
{
scoped_lock<mutex_type> &e_lock = scop;
if(e_lock.owns()){
e_lock.mutex()->unlock_and_lock_sharable();
m_locked = true;
}
mp_mutex = e_lock.release();
}
#endif
/*!Effects: if (owns()) mp_mutex->unlock_sharable().
Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
@@ -190,6 +222,7 @@ class sharable_lock
Notes: With a recursive mutex it is possible that both this and upgr own the mutex
before the assignment. In this case, this will own the mutex after the assignment
(and upgr will not), but the mutex's lock count will be decremented by one.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
sharable_lock &operator=(detail::moved_object<sharable_lock<mutex_type> > upgr)
{
if(this->owns())
@@ -198,6 +231,16 @@ class sharable_lock
mp_mutex = upgr.get().release();
return *this;
}
#else
sharable_lock &operator=(sharable_lock<mutex_type> &&upgr)
{
if(this->owns())
this->unlock();
m_locked = upgr.owns();
mp_mutex = upgr.release();
return *this;
}
#endif
/*!Effects: If mutex() == 0 or already locked, throws a lock_exception()
exception. Calls lock_sharable() on the referenced mutex.
@@ -284,11 +327,20 @@ class sharable_lock
/*!Effects: Swaps state with moved lock.
Throws: Nothing.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<sharable_lock<mutex_type> > other)
{
std::swap(mp_mutex, other.get().mp_mutex);
std::swap(m_locked, other.get().m_locked);
}
#else
void swap(sharable_lock<mutex_type> &&other)
{
std::swap(mp_mutex, other.mp_mutex);
std::swap(m_locked, other.m_locked);
}
#endif
/// @cond
private:
mutex_type *mp_mutex;

View File

@@ -125,9 +125,15 @@ class upgradable_lock
signature. An non-moved upgradable_lock can be moved with the
expression: "move(lock);". This constructor does not alter the
state of the mutex, only potentially who owns it.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
explicit upgradable_lock(detail::moved_object<upgradable_lock<mutex_type> > upgr)
: mp_mutex(0), m_locked(upgr.get().owns())
{ mp_mutex = upgr.get().release(); }
#else
explicit upgradable_lock(upgradable_lock<mutex_type> &&upgr)
: mp_mutex(0), m_locked(upgr.owns())
{ mp_mutex = upgr.release(); }
#endif
/*!Effects: If scop.owns(), m_.unlock_and_lock_upgradable().
Postconditions: mutex() == the value scop.mutex() had before the construction.
@@ -138,6 +144,7 @@ class upgradable_lock
Only a moved sharable_lock's will match this
signature. An non-moved sharable_lock can be moved with the
expression: "move(lock);".*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
explicit upgradable_lock(detail::moved_object<scoped_lock<mutex_type> > scop)
: mp_mutex(0), m_locked(false)
{
@@ -148,6 +155,18 @@ class upgradable_lock
}
mp_mutex = u_lock.release();
}
#else
explicit upgradable_lock(scoped_lock<mutex_type> &&scop)
: mp_mutex(0), m_locked(false)
{
scoped_lock<mutex_type> &u_lock = scop;
if(u_lock.owns()){
u_lock.mutex()->unlock_and_lock_upgradable();
m_locked = true;
}
mp_mutex = u_lock.release();
}
#endif
/*!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable()
on the referenced mutex.
@@ -164,6 +183,7 @@ class upgradable_lock
in the first place, the mutex merely changes type to an unlocked
"upgradable lock". If the "read lock" is held, then mutex transfer
occurs only if it can do so in a non-blocking manner.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
upgradable_lock( detail::moved_object<sharable_lock<mutex_type> > shar
, detail::try_to_lock_type)
: mp_mutex(0), m_locked(false)
@@ -178,6 +198,22 @@ class upgradable_lock
s_lock.release();
}
}
#else
upgradable_lock( sharable_lock<mutex_type> &&shar
, detail::try_to_lock_type)
: mp_mutex(0), m_locked(false)
{
sharable_lock<mutex_type> &s_lock = shar;
if(s_lock.owns()){
if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){
mp_mutex = s_lock.release();
}
}
else{
s_lock.release();
}
}
#endif
/*!Effects: if (owns()) m_->unlock_upgradable().
Notes: The destructor behavior ensures that the mutex lock is not leaked.*/
@@ -195,6 +231,7 @@ class upgradable_lock
mutex before the assignment. In this case, this will own the mutex
after the assignment (and upgr will not), but the mutex's upgradable lock
count will be decremented by one.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
upgradable_lock &operator=(detail::moved_object<upgradable_lock<mutex_type> > upgr)
{
if(this->owns())
@@ -203,6 +240,16 @@ class upgradable_lock
mp_mutex = upgr.get().release();
return *this;
}
#else
upgradable_lock &operator=(upgradable_lock<mutex_type> &&upgr)
{
if(this->owns())
this->unlock();
m_locked = upgr.owns();
mp_mutex = upgr.release();
return *this;
}
#endif
/*!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
exception. Calls lock_upgradable() on the referenced mutex.
@@ -289,11 +336,20 @@ class upgradable_lock
/*!Effects: Swaps state with moved lock.
Throws: Nothing.*/
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(detail::moved_object<upgradable_lock<mutex_type> > other)
{
std::swap(mp_mutex, other.get().mp_mutex);
std::swap(m_locked, other.get().m_locked);
}
#else
void swap(upgradable_lock<mutex_type> &&other)
{
std::swap(mp_mutex, other.mp_mutex);
std::swap(m_locked, other.m_locked);
}
#endif
/// @cond
private:
mutex_type *mp_mutex;

View File

@@ -77,13 +77,19 @@ class windows_shared_memory
//!Moves the ownership of "moved"'s shared memory object to *this.
//!After the call, "moved" does not represent any shared memory object.
//!Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
windows_shared_memory
(detail::moved_object<windows_shared_memory> &moved)
{ this->swap(moved.get()); }
#else
windows_shared_memory(windows_shared_memory &&moved)
{ this->swap(moved); }
#endif
//!Moves the ownership of "moved"'s shared memory to *this.
//!After the call, "moved" does not represent any shared memory.
//!Does not throw
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
windows_shared_memory &operator=
(detail::moved_object<windows_shared_memory> &moved)
{
@@ -91,6 +97,14 @@ class windows_shared_memory
this->swap(tmp);
return *this;
}
#else
windows_shared_memory &operator=(windows_shared_memory &&moved)
{
windows_shared_memory tmp(move(moved));
this->swap(tmp);
return *this;
}
#endif
//!Swaps to shared_memory_objects. Does not throw
void swap(windows_shared_memory &other);

View File

@@ -1,8 +1,9 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
<meta http-equiv="refresh" content="0; URL=../../doc/html/interprocess.html">
</head>
<body>
Automatic redirection failed, please go to <a href="doc/html/index.html">doc/html/interprocess.html</a>
Automatic redirection failed, please go to
<a href="../../../doc/html/interprocess.html">../../doc/html/interprocess.html</a>
</body>
</html>

View File

@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="ProcessA"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792619}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/ProcessA"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessA_d.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/ProcessA.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/ProcessA"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessA.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\example\process_a_example.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="ProcessAFixed"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792618}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/ProcessAFixed"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessAFixed_d.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/ProcessAFixed.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/ProcessAFixed"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessAFixed.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\example\process_a_fixed_example.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,132 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="ProcessB"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792617}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/ProcessB"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessB_d.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/ProcessB.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/ProcessB"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessB.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\example\process_b_example.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,132 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="ProcessBFixed"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792616}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/ProcessBFixed"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessBFixed_d.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/ProcessBFixed.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/ProcessBFixed"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/ProcessBFixed.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\example\process_b_fixed_example.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,134 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="allocate_ex"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792663}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/allocate_ex"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/allocate_ex_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/allocate_ex.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/allocate_ex"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/allocate_ex.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\example\alloc_example.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,134 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="file_lock_test"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792639}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/file_lock_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/file_lock_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/file_lock_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/file_lock_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/file_lock_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{7FCFEF41-3746-C7A5-8B8E-A352A2F22D7F}">
<File
RelativePath="..\..\test\file_lock_test.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{95393980-8912-4b74-66A0-607BE52EB5FB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,134 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="hash_table_test"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792636}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/hash_table_ex"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/hash_table_ex_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/hash_table_ex.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/hash_table_ex"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/hash_table_ex.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\test\hash_table_test.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="intersegment_ptr_test"
ProjectGUID="{58CCE183-6092-12FE-A4F7-BA0D3A767634}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/intersegment_ptr_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/intersegment_ptr_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/intersegment_ptr_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/intersegment_ptr_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/intersegment_ptr_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-CAA5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\test\intersegment_ptr_test.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-8ABD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,134 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="named_allocate_ex"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792626}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/named_allocate_ex"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/named_allocate_ex_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/named_allocate_ex.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/named_allocate_ex"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/named_allocate_ex.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\example\named_alloc_example.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,134 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="read_write_mutex_test"
ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792615}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/shared_read_write_mutex_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/shared_read_write_mutex_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/shared_read_write_mutex_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/shared_read_write_mutex_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/shared_read_write_mutex_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="..\..\test\read_write_mutex_test.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,134 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="sharable_mutex_test"
ProjectGUID="{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/sharable_mutex_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/sharable_mutex_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/sharable_mutex_test.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/sharable_mutex_test"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/sharable_mutex_test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4737FCF1-C7A5-A606-4376-2A3252AD72FF}">
<File
RelativePath="..\..\test\sharable_mutex_test.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{98903953-8D9B-88EB-4b04-6BBF2E52E5FB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -275,10 +275,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_managed_heap_memory", "
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocate_ex", "allocate_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792663}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocexcept_test", "allocexcept_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792662}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
@@ -335,10 +331,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_where_allocate", "doc_w
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file_lock_test", "file_lock_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792639}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file_mapping_test", "file_mapping_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792638}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
@@ -347,14 +339,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hash_table_test", "hash_table_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792636}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intersegment_ptr_test", "intersegment_ptr_test.vcproj", "{58CCE183-6092-12FE-A4F7-BA0D3A767634}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intrusive_ptr_test", "intrusive_ptr_test.vcproj", "{5821C383-6092-12FE-A877-BA0D33467633}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
@@ -383,34 +367,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mutex_test", "mutex_test.vc
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_allocate_ex", "named_allocate_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792626}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "null_index_test", "null_index_test.vcproj", "{0000058C-0000-0000-0000-000000000021}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessA", "ProcessA.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792619}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessAFixed", "ProcessAFixed.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792618}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessB", "ProcessB.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792617}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessBFixed", "ProcessBFixed.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792616}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "read_write_mutex_test", "read_write_mutex_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792615}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recursive_mutex_test", "recursive_mutex_test.vcproj", "{83581CCE-487E-3292-A4E7-BA07926D3A14}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
@@ -419,10 +379,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "semaphore_test", "semaphore
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sharable_mutex_test", "sharable_mutex.vcproj", "{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@@ -707,10 +663,6 @@ Global
{58CCE183-6092-48FE-A4FC-BA0D3A792647}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4FC-BA0D3A792647}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4FC-BA0D3A792647}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792663}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792663}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792663}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792663}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792662}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792662}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792662}.Release.ActiveCfg = Release|Win32
@@ -767,10 +719,6 @@ Global
{58CCE183-6092-48FE-A677-BA0D3A832640}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A677-BA0D3A832640}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A677-BA0D3A832640}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792638}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792638}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792638}.Release.ActiveCfg = Release|Win32
@@ -779,14 +727,6 @@ Global
{58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792636}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792636}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792636}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792636}.Release.Build.0 = Release|Win32
{58CCE183-6092-12FE-A4F7-BA0D3A767634}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-12FE-A4F7-BA0D3A767634}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-12FE-A4F7-BA0D3A767634}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-12FE-A4F7-BA0D3A767634}.Release.Build.0 = Release|Win32
{5821C383-6092-12FE-A877-BA0D33467633}.Debug.ActiveCfg = Debug|Win32
{5821C383-6092-12FE-A877-BA0D33467633}.Debug.Build.0 = Debug|Win32
{5821C383-6092-12FE-A877-BA0D33467633}.Release.ActiveCfg = Release|Win32
@@ -815,34 +755,10 @@ Global
{83581CCE-487E-3292-A4E7-BA07926D3A27}.Debug.Build.0 = Debug|Win32
{83581CCE-487E-3292-A4E7-BA07926D3A27}.Release.ActiveCfg = Release|Win32
{83581CCE-487E-3292-A4E7-BA07926D3A27}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792626}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792626}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792626}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792626}.Release.Build.0 = Release|Win32
{0000058C-0000-0000-0000-000000000021}.Debug.ActiveCfg = Debug|Win32
{0000058C-0000-0000-0000-000000000021}.Debug.Build.0 = Debug|Win32
{0000058C-0000-0000-0000-000000000021}.Release.ActiveCfg = Release|Win32
{0000058C-0000-0000-0000-000000000021}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792619}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792619}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792619}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792619}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792618}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792618}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792618}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792618}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792617}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792617}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792617}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792617}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792616}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792616}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792616}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792616}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792615}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792615}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792615}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792615}.Release.Build.0 = Release|Win32
{83581CCE-487E-3292-A4E7-BA07926D3A14}.Debug.ActiveCfg = Debug|Win32
{83581CCE-487E-3292-A4E7-BA07926D3A14}.Debug.Build.0 = Debug|Win32
{83581CCE-487E-3292-A4E7-BA07926D3A14}.Release.ActiveCfg = Release|Win32
@@ -851,10 +767,6 @@ Global
{5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Debug.Build.0 = Debug|Win32
{5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Release.ActiveCfg = Release|Win32
{5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Release.Build.0 = Release|Win32
{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Debug.ActiveCfg = Debug|Win32
{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Debug.Build.0 = Debug|Win32
{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Release.ActiveCfg = Release|Win32
{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection

View File

@@ -1,134 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="doc_shared_memory"
ProjectGUID="{58CCE183-6032-12FE-4FC7-83A79F760B61}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/doc_shared_memory"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_shared_memory_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/doc_shared_memory.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/doc_shared_memory"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_shared_memory.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4F7371DF-A5DA-6437-60A6-22A352A2D7FF}">
<File
RelativePath="..\..\example\doc_shared_memory.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93909538-DA9B-44D0-8EB8-E55F262BEBFB}">
</Filter>
</Files>
<Globals>
</Globals>
ProjectType="Visual C++"
Version="7.10"
Name="doc_shared_memory"
ProjectGUID="{58CCE183-6032-12FE-4FC7-83A79F760B61}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/doc_shared_memory"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_shared_memory_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/doc_shared_memory.pdb"
SubSystem="1"
TargetMachine="1"
FixedBaseAddress="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../../Bin/Win32/Release"
IntermediateDirectory="Release/doc_shared_memory"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../.."
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/doc_shared_memory.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4F7371DF-A5DA-6437-60A6-22A352A2D7FF}">
<File
RelativePath="..\..\example\doc_shared_memory.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93909538-DA9B-44D0-8EB8-E55F262BEBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -331,9 +331,6 @@
<Filter
Name="Memory algorithms"
Filter="">
<File
RelativePath="..\..\..\..\boost\interprocess\mem_algo\multi_simple_seq_fit.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\mem_algo\rbtree_best_fit.hpp">
</File>
@@ -395,9 +392,15 @@
<Filter
Name="Detail"
Filter="">
<File
RelativePath="..\..\..\..\boost\interprocess\detail\algorithms.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\atomic.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\basic_segment_manager.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\cast_tags.hpp">
</File>
@@ -407,21 +410,36 @@
<File
RelativePath="..\..\..\..\boost\interprocess\detail\config_end.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\construction_table.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\creation_tags.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\file_wrapper.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\gcd_lcm.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\generic_cast.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\in_place_interface.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\iterators.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\managed_memory_impl.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\managed_open_or_create_impl.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\min_max.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\move.hpp">
</File>
@@ -431,6 +449,9 @@
<File
RelativePath="..\..\..\..\boost\interprocess\detail\moved_default_iterator.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\mpl.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\named_proxy.hpp">
</File>
@@ -443,6 +464,9 @@
<File
RelativePath="..\..\..\..\boost\interprocess\detail\os_thread_functions.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\pointer_type.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\interprocess\detail\posix_time_types_wrk.hpp">
</File>
@@ -461,13 +485,6 @@
<File
RelativePath="..\..\..\..\boost\interprocess\detail\workaround.hpp">
</File>
<Filter
Name="IPC"
Filter="">
<File
RelativePath="..\..\..\..\boost\interprocess\ipc\message_queue.hpp">
</File>
</Filter>
</Filter>
<Filter
Name="Documentation"
@@ -633,6 +650,13 @@
RelativePath="..\..\example\Jamfile.v2">
</File>
</Filter>
<Filter
Name="IPC"
Filter="">
<File
RelativePath="..\..\..\..\boost\interprocess\ipc\message_queue.hpp">
</File>
</Filter>
<File
RelativePath="..\..\..\..\boost\interprocess\interprocess_fwd.hpp">
</File>

View File

@@ -77,6 +77,10 @@ int main ()
if(InstanceCounter::counter != 0)
return 1;
}
catch(std::length_error &){
if(InstanceCounter::counter != 0)
return 1;
}
}
catch(...){
shared_memory_object::remove(shMemName);

View File

@@ -111,18 +111,6 @@ int list_test (bool copied_allocators_equal = true)
MyStdList *stdlist = new MyStdList;
/*
{
typedef typename MyShmList::value_type IntType;
for(int i = 0; i < max; ++i){
IntType move_me(i);
shmlist->push_front(move(move_me));
stdlist->push_front(i);
}
if(!CheckEqualContainers(shmlist, stdlist)) return 1;
return 0;
}*/
if(push_data_t::execute(max, shmlist, stdlist)){
return 1;
}

View File

@@ -19,6 +19,7 @@
#include "print_container.hpp"
#include <boost/interprocess/detail/move_iterator.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/iterators.hpp>
template<class T1, class T2, class T3, class T4>
bool operator ==(std::pair<T1, T2> &p1, std::pair<T1, T2> &p2)

View File

@@ -49,6 +49,7 @@ template<class Allocator>
bool test_allocation_direct_deallocation(Allocator &a)
{
std::vector<void*> buffers;
std::size_t free_memory = a.get_free_memory();
for(int i = 0; true; ++i){
void *ptr = a.allocate(i, std::nothrow);
@@ -63,7 +64,8 @@ bool test_allocation_direct_deallocation(Allocator &a)
a.deallocate(buffers[j]);
}
return a.all_memory_deallocated() && a.check_sanity();
return free_memory == a.get_free_memory() &&
a.all_memory_deallocated() && a.check_sanity();
}
//This test allocates until there is no more memory
@@ -453,7 +455,7 @@ bool test_continuous_aligned_allocation(Allocator &a)
}
//This test allocates memory, writes it with a non-zero value and
//tests clear_free_memory initializes to zero for the next allocation
//tests zero_free_memory initializes to zero for the next allocation
template<class Allocator>
bool test_clear_free_memory(Allocator &a)
{
@@ -484,7 +486,7 @@ bool test_clear_free_memory(Allocator &a)
return false;
//Now clear all free memory
a.clear_free_memory();
a.zero_free_memory();
if(!a.all_memory_deallocated() && a.check_sanity())
return false;

View File

@@ -33,13 +33,24 @@ class movable_int
explicit movable_int(int a)
: m_int(a)
{}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_int(const detail::moved_object<movable_int> &mmi)
: m_int(mmi.get().m_int)
{ mmi.get().m_int = 0; }
#else
movable_int(movable_int &&mmi)
: m_int(mmi.m_int)
{ mmi.m_int = 0; }
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_int & operator= (const detail::moved_object<movable_int> &mmi)
{ this->m_int = mmi.get().m_int; mmi.get().m_int = 0; return *this; }
#else
movable_int & operator= (movable_int &&mmi)
{ this->m_int = mmi.m_int; mmi.m_int = 0; return *this; }
#endif
bool operator ==(const movable_int &mi) const
{ return this->m_int == mi.m_int; }
@@ -93,13 +104,24 @@ class movable_and_copyable_int
movable_and_copyable_int &operator= (const movable_and_copyable_int& mi)
{ this->m_int = mi.m_int; return *this; }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_and_copyable_int(const detail::moved_object<movable_and_copyable_int> &mmi)
: m_int(mmi.get().m_int)
{ mmi.get().m_int = 0; }
#else
movable_and_copyable_int(movable_and_copyable_int &&mmi)
: m_int(mmi.m_int)
{ mmi.m_int = 0; }
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
movable_and_copyable_int & operator= (const detail::moved_object<movable_and_copyable_int> &mmi)
{ this->m_int = mmi.get().m_int; mmi.get().m_int = 0; return *this; }
#else
movable_and_copyable_int & operator= (movable_and_copyable_int &&mmi)
{ this->m_int = mmi.m_int; mmi.m_int = 0; return *this; }
#endif
bool operator ==(const movable_and_copyable_int &mi) const
{ return this->m_int == mi.m_int; }

View File

@@ -15,11 +15,15 @@
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <vector>
#include <iostream>
#include <cstdio>
#include <new>
#include <utility>
#include <iterator>
#include <set>
#include <string>
namespace boost { namespace interprocess { namespace test {
@@ -28,23 +32,36 @@ namespace boost { namespace interprocess { namespace test {
template<class ManagedMemory>
bool test_names_and_types(ManagedMemory &m)
{
typedef typename ManagedMemory::char_type char_type;
typedef std::char_traits<char_type> char_traits_type;
std::vector<char*> buffers;
const int BufferLen = 100;
char name[BufferLen];
char_type name[BufferLen];
basic_bufferstream<char_type> formatter(name, BufferLen);
for(int i = 0; true; ++i){
std::sprintf(name, "%s%010d", "prefix_name_", i);
formatter.seekp(0);
formatter << "prefix_name_" << i << std::ends;
char *ptr = m.template construct<char>(name, std::nothrow)(i);
if(!ptr)
break;
if(std::strcmp(m.get_name(ptr), name) != 0)
return false;
std::size_t namelen = char_traits_type::length(m.get_name(ptr));
if(namelen != char_traits_type::length(name)){
return 1;
}
if(char_traits_type::compare(m.get_name(ptr), name, namelen) != 0){
return 1;
}
if(m.template find<char>(name).first == 0)
return false;
if(m.get_type(ptr) != named_type)
if(m.get_type(ptr) != detail::named_type)
return false;
buffers.push_back(ptr);
@@ -64,17 +81,92 @@ bool test_names_and_types(ManagedMemory &m)
return true;
}
//This test allocates until there is no more memory
//and after that deallocates all in the same order
template<class ManagedMemory>
bool test_named_iterators(ManagedMemory &m)
{
typedef typename ManagedMemory::char_type char_type;
typedef std::char_traits<char_type> char_traits_type;
std::vector<char*> buffers;
const int BufferLen = 100;
char_type name[BufferLen];
typedef std::basic_string<char_type> string_type;
std::set<string_type> names;
basic_bufferstream<char_type> formatter(name, BufferLen);
string_type aux_str;
for(int i = 0; true; ++i){
formatter.seekp(0);
formatter << "prefix_name_" << i << std::ends;
char *ptr = m.template construct<char>(name, std::nothrow)(i);
if(!ptr)
break;
aux_str = name;
names.insert(aux_str);
buffers.push_back(ptr);
}
if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
return false;
typedef typename ManagedMemory::const_named_iterator const_named_iterator;
const_named_iterator named_beg = m.named_begin();
const_named_iterator named_end = m.named_end();
if(std::distance(named_beg, named_end) != (int)buffers.size()){
return 1;
}
for(; named_beg != named_end; ++named_beg){
const char_type *name = named_beg->name();
aux_str = name;
if(names.find(aux_str) == names.end()){
return 1;
}
if(aux_str.size() != named_beg->name_length()){
return 1;
}
const void *found_value = m.template find<char>(name).first;
if(found_value == 0)
return false;
if(found_value != named_beg->value())
return false;
}
for(int j = 0, max = (int)buffers.size()
;j < max
;++j){
m.destroy_ptr(buffers[j]);
}
if(m.get_num_named_objects() != 0 || !m.check_sanity())
return false;
return true;
}
//This test allocates until there is no more memory
//and after that deallocates all in the same order
template<class ManagedMemory>
bool test_direct_named_allocation_destruction(ManagedMemory &m)
{
typedef typename ManagedMemory::char_type char_type;
typedef std::char_traits<char_type> char_traits_type;
std::vector<char*> buffers;
const int BufferLen = 100;
char name[BufferLen];
char_type name[BufferLen];
basic_bufferstream<char_type> formatter(name, BufferLen);
for(int i = 0; true; ++i){
std::sprintf(name, "%s%010d", "prefix_name_", i);
formatter.seekp(0);
formatter << "prefix_name_" << i << std::ends;
char *ptr = m.template construct<char>(name, std::nothrow)(i);
if(!ptr)
break;
@@ -102,12 +194,18 @@ bool test_direct_named_allocation_destruction(ManagedMemory &m)
template<class ManagedMemory>
bool test_named_allocation_inverse_destruction(ManagedMemory &m)
{
typedef typename ManagedMemory::char_type char_type;
typedef std::char_traits<char_type> char_traits_type;
std::vector<char*> buffers;
const int BufferLen = 100;
char name[BufferLen];
char_type name[BufferLen];
basic_bufferstream<char_type> formatter(name, BufferLen);
for(int i = 0; true; ++i){
std::sprintf(name, "%s%010d", "prefix_name_", i);
formatter.seekp(0);
formatter << "prefix_name_" << i << std::ends;
char *ptr = m.template construct<char>(name, std::nothrow)(i);
if(!ptr)
break;
@@ -133,12 +231,18 @@ bool test_named_allocation_inverse_destruction(ManagedMemory &m)
template<class ManagedMemory>
bool test_named_allocation_mixed_destruction(ManagedMemory &m)
{
typedef typename ManagedMemory::char_type char_type;
typedef std::char_traits<char_type> char_traits_type;
std::vector<char*> buffers;
const int BufferLen = 100;
char name[BufferLen];
char_type name[BufferLen];
basic_bufferstream<char_type> formatter(name, BufferLen);
for(int i = 0; true; ++i){
std::sprintf(name, "%s%010d", "prefix_name_", i);
formatter.seekp(0);
formatter << "prefix_name_" << i << std::ends;
char *ptr = m.template construct<char>(name, std::nothrow)(i);
if(!ptr)
break;
@@ -166,13 +270,18 @@ bool test_named_allocation_mixed_destruction(ManagedMemory &m)
template<class ManagedMemory>
bool test_inverse_named_allocation_destruction(ManagedMemory &m)
{
typedef typename ManagedMemory::char_type char_type;
typedef std::char_traits<char_type> char_traits_type;
std::vector<char*> buffers;
const int BufferLen = 100;
char name[BufferLen];
const unsigned int FirstNumber = (unsigned int)-1;
char_type name[BufferLen];
basic_bufferstream<char_type> formatter(name, BufferLen);
for(unsigned int i = 0; true; ++i){
std::sprintf(name, "%s%010u", "prefix_name_", FirstNumber - i);
formatter.seekp(0);
formatter << "prefix_name_" << i << std::ends;
char *ptr = m.template construct<char>(name, std::nothrow)(i);
if(!ptr)
break;
@@ -242,6 +351,12 @@ bool test_all_named_allocation(ManagedMemory &m)
return false;
}
if(!test_named_iterators(m)){
std::cout << "test_named_iterators failed. Class: "
<< typeid(m).name() << std::endl;
return false;
}
return true;
}
@@ -275,7 +390,7 @@ bool test_named_allocation()
throw;
}
shared_memory_object::remove(shMemName);
/*
//Now test it with wchar_t
try
{
@@ -300,7 +415,7 @@ bool test_named_allocation()
throw;
}
shared_memory_object::remove(shMemName);
*/
return true;
}