diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 0f9bd77..0d0220b 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -36,7 +36,7 @@ doxygen interprocess_doxygen xml interprocess_xml : interprocess.qbk ; -boostbook standalone +boostbook interprocess : interprocess_xml interprocess_doxygen diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index 8e89142..1629adc 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -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 -* [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 - void construct(pointer ptr, const Convertible &value) - -and define a specialization of `boost::interprocess::has_convertible_construct<...>` -defined in `` file: - -[c++] - - namespace boost{ namespace interprocess{ - - template - struct has_convertible_construct - > - { - 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. diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index eb9d49c..387f761 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -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 diff --git a/example/doc_cont.cpp b/example/doc_cont.cpp index ce3d45e..6b899ae 100644 --- a/example/doc_cont.cpp +++ b/example/doc_cont.cpp @@ -11,6 +11,7 @@ #include //[doc_cont #include +#include #include int main () diff --git a/example/doc_map.cpp b/example/doc_map.cpp index a56f9ad..5a7da62 100644 --- a/example/doc_map.cpp +++ b/example/doc_map.cpp @@ -34,7 +34,7 @@ int main () //so the allocator must allocate that pair. typedef int KeyType; typedef float MappedType; - typedef std::pair ValueType; + typedef std::pair 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(i, (float)i)); + mymap->insert(std::pair(i, (float)i)); } } catch(...){ diff --git a/example/doc_scoped_ptr.cpp b/example/doc_scoped_ptr.cpp index 3bf60e5..3eb423f 100644 --- a/example/doc_scoped_ptr.cpp +++ b/example/doc_scoped_ptr.cpp @@ -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_object")(); + my_class * my_object2 = shmem.construct(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 diff --git a/example/doc_vectorstream.cpp b/example/doc_vectorstream.cpp index 17678de..435eaec 100644 --- a/example/doc_vectorstream.cpp +++ b/example/doc_vectorstream.cpp @@ -12,6 +12,7 @@ //[doc_vectorstream #include #include +#include #include #include #include diff --git a/include/boost/interprocess/allocators/adaptive_pool.hpp b/include/boost/interprocess/allocators/adaptive_pool.hpp index dc4554e..855c29f 100644 --- a/include/boost/interprocess/allocators/adaptive_pool.hpp +++ b/include/boost/interprocess/allocators/adaptive_pool.hpp @@ -301,18 +301,6 @@ bool operator!=(const adaptive_pool &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 -struct has_convertible_construct - > -{ - enum { value = true }; -}; -/// @endcond - } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/allocators/allocator.hpp b/include/boost/interprocess/allocators/allocator.hpp index 4f23d13..b7f95ee 100644 --- a/include/boost/interprocess/allocators/allocator.hpp +++ b/include/boost/interprocess/allocators/allocator.hpp @@ -26,7 +26,7 @@ #include #include #include -#include + #include #include #include @@ -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 - 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 &alloc1, const allocator &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 -struct has_convertible_construct - > -{ - enum { value = true }; -}; -/// @endcond - } //namespace interprocess { /// @cond + +template +struct has_trivial_destructor; + template struct has_trivial_destructor > diff --git a/include/boost/interprocess/allocators/cached_adaptive_pool.hpp b/include/boost/interprocess/allocators/cached_adaptive_pool.hpp index a9bc489..204d8f2 100644 --- a/include/boost/interprocess/allocators/cached_adaptive_pool.hpp +++ b/include/boost/interprocess/allocators/cached_adaptive_pool.hpp @@ -390,18 +390,6 @@ bool operator!=(const cached_adaptive_pool &alloc1, const cached_adaptive_pool &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 -struct has_convertible_construct - > -{ - enum { value = true }; -}; -/// @endcond - } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/allocators/cached_node_allocator.hpp b/include/boost/interprocess/allocators/cached_node_allocator.hpp index 4448897..2be6dd8 100644 --- a/include/boost/interprocess/allocators/cached_node_allocator.hpp +++ b/include/boost/interprocess/allocators/cached_node_allocator.hpp @@ -388,18 +388,6 @@ bool operator!=(const cached_node_allocator &alloc1, const cached_node_allocator &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 -struct has_convertible_construct - > -{ - enum { value = true }; -}; -/// @endcond - } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/allocators/detail/node_pool.hpp b/include/boost/interprocess/allocators/detail/node_pool.hpp index 8a21442..3d4c0eb 100644 --- a/include/boost/interprocess/allocators/detail/node_pool.hpp +++ b/include/boost/interprocess/allocators/detail/node_pool.hpp @@ -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); } } diff --git a/include/boost/interprocess/allocators/node_allocator.hpp b/include/boost/interprocess/allocators/node_allocator.hpp index b83ceea..899096c 100644 --- a/include/boost/interprocess/allocators/node_allocator.hpp +++ b/include/boost/interprocess/allocators/node_allocator.hpp @@ -298,19 +298,6 @@ bool operator!=(const node_allocator &alloc1, const node_allocator &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 -struct has_convertible_construct - > -{ - enum { value = true }; -}; -/// @endcond - } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/allocators/private_adaptive_pool.hpp b/include/boost/interprocess/allocators/private_adaptive_pool.hpp index cf6289e..180fd96 100644 --- a/include/boost/interprocess/allocators/private_adaptive_pool.hpp +++ b/include/boost/interprocess/allocators/private_adaptive_pool.hpp @@ -235,16 +235,6 @@ bool operator!=(const private_adaptive_pool &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 -struct has_convertible_construct - > -{ enum { value = true }; }; -/// @endcond - } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/allocators/private_node_allocator.hpp b/include/boost/interprocess/allocators/private_node_allocator.hpp index 3af36eb..fa10359 100644 --- a/include/boost/interprocess/allocators/private_node_allocator.hpp +++ b/include/boost/interprocess/allocators/private_node_allocator.hpp @@ -236,18 +236,6 @@ bool operator!=(const private_node_allocator &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 -struct has_convertible_construct - > -{ - enum { value = true }; -}; -/// @endcond - } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/containers/deque.hpp b/include/boost/interprocess/containers/deque.hpp index a2038ac..0572c72 100644 --- a/include/boost/interprocess/containers/deque.hpp +++ b/include/boost/interprocess/containers/deque.hpp @@ -52,6 +52,10 @@ #include #include +#include +#include +#include +#include #include #include #include @@ -64,7 +68,6 @@ #include #include #include -#include namespace boost { @@ -84,10 +87,8 @@ inline std::size_t deque_buf_size(std::size_t size) // exception safety easier. template class deque_base - : public boost::detail::allocator:: - rebind_to::type, - public boost::detail::allocator:: - rebind_to::type + : public Alloc::template rebind::other, + public Alloc::template rebind::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::type ptr_alloc; + typedef typename Alloc::template rebind + ::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::type allocator_type; + typedef typename Alloc::template + rebind::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::value }; - typedef typename boost::detail::allocator:: - rebind_to::type map_allocator_type; + typedef typename Alloc::template + rebind::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 &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 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::type ptr_alloc; + typedef typename Alloc::template + rebind::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 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 &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 { //Dispatch depending on integer/iterator const bool aux_boolean = boost::is_integral::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->priv_initialize_dispatch(first, last, Result()); } @@ -621,8 +640,13 @@ class deque : protected deque_base return *this; } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE deque& operator= (const detail::moved_object &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 std::swap(this->m_map_size, x.m_map_size); } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object &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 void assign(InpIt first, InpIt last) { //Dispatch depending on integer/iterator const bool aux_boolean = boost::is_integral::value; - typedef boost::mpl::bool_ Result; + typedef bool_ 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 &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 &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(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 void pop_front() { if (this->m_start.m_cur != this->m_start.m_last - 1) { - static_cast(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 } } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator position, const detail::moved_object &mx) { if (position.m_cur == this->m_start.m_cur) { @@ -740,6 +794,24 @@ class deque : protected deque_base 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 { //Dispatch depending on integer/iterator const bool aux_boolean = boost::is_integral::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->priv_insert_dispatch(pos, first, last, Result()); } @@ -873,7 +945,7 @@ class deque : protected deque_base 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 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 } template - 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 - 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::iterator_category ItCat; this->priv_range_initialize(first, last, ItCat()); } void priv_destroy_range(iterator p, iterator p2) - { for(;p != p2; ++p) static_cast(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(this)->destroy(p); } + { + for(;p != p2; ++p) + detail::get_pointer(&*p)->~value_type(); + } template - 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 - 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::iterator_category ItCat; this->priv_assign_aux(first, last, ItCat()); @@ -973,7 +1051,7 @@ class deque : protected deque_base template 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 template void priv_insert_dispatch(iterator pos, InpIt first, InpIt last, - boost::mpl::false_) + false_) { typedef typename std::iterator_traits::iterator_category ItCat; this->insert(pos, first, last, ItCat()); @@ -994,6 +1072,7 @@ class deque : protected deque_base return iterator(this->begin() + n); } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator priv_insert_aux(iterator pos, const detail::moved_object &mx) { typedef repeat_iterator r_iterator; @@ -1005,6 +1084,19 @@ class deque : protected deque_base ,move_it(r_iterator())); return iterator(this->begin() + n); } + #else + iterator priv_insert_aux(iterator pos, value_type &&mx) + { + typedef repeat_iterator r_iterator; + typedef detail::move_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 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 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 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 ++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 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 } // 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 &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 } 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 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 BOOST_CATCH_END } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void priv_push_front_aux(const detail::moved_object &mt) { this->priv_reserve_map_at_front(); @@ -1198,7 +1309,7 @@ class deque : protected deque_base 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 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 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(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 // must have at least two nodes. void priv_pop_front_aux() { - static_cast(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 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(this)->destroy(&*first2); + detail::get_pointer(&*first2)->~value_type(); } } BOOST_CATCH_END @@ -1355,13 +1484,13 @@ class deque : protected deque_base 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(this)->destroy(&*result); + detail::get_pointer(&*result)->~value_type(); } BOOST_RETHROW } @@ -1377,13 +1506,13 @@ class deque : protected deque_base 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(this)->destroy(&*result); + detail::get_pointer(&*result)->~value_type(); } BOOST_RETHROW } diff --git a/include/boost/interprocess/containers/detail/flat_tree.hpp b/include/boost/interprocess/containers/detail/flat_tree.hpp index b496051..c3a5477 100644 --- a/include/boost/interprocess/containers/detail/flat_tree.hpp +++ b/include/boost/interprocess/containers/detail/flat_tree.hpp @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -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 &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& 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& other) { this->swap(other.get()); } + #else + void swap(flat_tree &&other) + { this->swap(other); } + #endif - public: + public: // insert/erase std::pair insert_unique(const value_type& val) { @@ -213,6 +228,7 @@ class flat_tree return ret; } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE std::pair insert_unique(const detail::moved_object& mval) { insert_commit_data data; @@ -222,6 +238,18 @@ class flat_tree } return ret; } + #else + std::pair insert_unique(value_type && mval) + { + insert_commit_data data; + std::pair 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& 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& 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 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& 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 void insert_unique(InIt first, InIt last) @@ -468,10 +526,17 @@ class flat_tree } } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template 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 + iterator priv_insert_commit + (insert_commit_data &commit_data, Convertible &&convertible) + { return this->m_data.m_vect.insert(commit_data.position, forward(convertible)); } + #endif template RanIt priv_lower_bound(RanIt first, RanIt last, diff --git a/include/boost/interprocess/containers/detail/tree.hpp b/include/boost/interprocess/containers/detail/tree.hpp index d306818..a3c5cb4 100644 --- a/include/boost/interprocess/containers/detail/tree.hpp +++ b/include/boost/interprocess/containers/detail/tree.hpp @@ -47,16 +47,11 @@ #include #include -#include -#include #include #include #include #include -#include -#include #include -#include #include #include @@ -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 - ::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(*this); } - bool operator()(const value_type &a, const value_type &b) const + template + 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 @@ -109,9 +96,15 @@ struct rbtree_node typedef T value_type; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template rbtree_node(const Convertible &conv) : m_data(conv){} + #else + template + rbtree_node(Convertible &&conv) + : m_data(forward(conv)){} + #endif rbtree_node &operator=(const rbtree_node &other) { do_assign(other.m_data); return *this; } @@ -133,21 +126,20 @@ struct rbtree_node template struct rbtree_alloc - : public boost::detail::allocator:: - rebind_to::type::pointer> - >::type + : public A::template rebind::type> + >::other { typedef rbtree_alloc self_t; typedef typename A::value_type value_type; typedef rbtree_node - ::type::pointer> Node; - typedef typename boost::detail::allocator:: - rebind_to::type::pointer VoidPointer; - typedef typename boost::detail::allocator:: - rebind_to::type NodeAlloc; + ::type> Node; + typedef typename A::template rebind::other NodeAlloc; + typedef typename detail::pointer_to_other + ::type VoidPointer; typedef A ValAlloc; typedef typename NodeAlloc::pointer NodePtr; typedef detail::scoped_deallocator 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::value && - boost::has_trivial_destructor::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 &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 &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 static void construct(const NodePtr &ptr, const Convertible &value) { new(detail::get_pointer(ptr)) Node(value); } + #else + template + static void construct(const NodePtr &ptr, Convertible &&value) + { new(detail::get_pointer(ptr)) Node(forward(value)); } + #endif + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template static void construct(const NodePtr &ptr, const detail::moved_object > &value) @@ -225,25 +230,49 @@ struct rbtree_alloc new((void*)detail::get_pointer(ptr)) hack_node_t(value); } + #else + template + static void construct(const NodePtr &ptr, + std::pair &&value) + { + //std::pair is not movable so we define our own type and overwrite it + typedef detail::pair hack_pair_t; + + typedef rbtree_node 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 NodePtr create_node(const Convertible& x) { NodePtr p = NodeAlloc::allocate(1); - scoped_ptrnode_deallocator(p, *this); + Deallocator node_deallocator(p, *this); self_t::construct(p, x); node_deallocator.release(); return (p); } + #else + template + NodePtr create_node(Convertible &&x) + { + NodePtr p = NodeAlloc::allocate(1); + Deallocator node_deallocator(p, *this); + self_t::construct(p, forward(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& 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& 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& 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 iterator insert_unique_commit (const detail::moved_object& 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 + iterator insert_unique_commit + (MovableConvertible && mv, insert_commit_data &data) + { + NodePtr tmp = AllocHolder::create_node(forward(mv)); + iiterator it(this->m_irbtree.insert_unique_commit(*tmp, data)); + return iterator(it); + } + #endif std::pair 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 std::pair insert_unique (const detail::moved_object& mv) @@ -653,6 +710,19 @@ class rbtree return std::pair (this->insert_unique_commit(mv, data), true); } + #else + template + std::pair insert_unique(MovableConvertible &&mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(KeyOfValue()(mv), data); + if(!ret.second) + return ret; + return std::pair + (this->insert_unique_commit(forward(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 iterator insert_unique (const_iterator hint, const detail::moved_object &mv) @@ -675,6 +746,19 @@ class rbtree return ret.first; return this->insert_unique_commit(mv, data); } + #else + template + iterator insert_unique + (const_iterator hint, MovableConvertible &&mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, KeyOfValue()(mv), data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(forward(mv), data); + } + #endif template 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 iterator insert_equal(const detail::moved_object &mv) { NodePtr p(AllocHolder::create_node(mv)); return iterator(this->m_irbtree.insert_equal_upper_bound(*p)); } + #else + template + iterator insert_equal(MovableConvertible &&mv) + { + NodePtr p(AllocHolder::create_node(forward(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 iterator insert_equal(const_iterator hint, const detail::moved_object &mv) { NodePtr p(AllocHolder::create_node(mv)); return iterator(this->m_irbtree.insert_equal(hint.get(), *p)); } + #else + template + 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 void insert_equal(InputIterator first, InputIterator last) diff --git a/include/boost/interprocess/containers/flat_map.hpp b/include/boost/interprocess/containers/flat_map.hpp index 6314f3c..8d1dac2 100644 --- a/include/boost/interprocess/containers/flat_map.hpp +++ b/include/boost/interprocess/containers/flat_map.hpp @@ -22,9 +22,9 @@ #include #include #include -#include #include #include +#include #include 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, - detail::select1st< detail::pair >, + select1st< detail::pair >, Pred, - typename boost::detail::allocator:: - rebind_to >::type> impl_tree_t; + typename Alloc::template + rebind >::other> impl_tree_t; //This is the tree that we should store if pair was movable typedef detail::flat_tree, - detail::select1st< std::pair >, + select1st< std::pair >, 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_moved_value_type; -/* - template - static D &force(S &s) - { return *(reinterpret_cast(&s)); } -*/ + #else + typedef impl_value_type&& impl_moved_value_type; + #endif + template static D &force(const S &s) { return *const_cast((reinterpret_cast(&s))); } + + #ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + static D &&force(S &&s) + { return reinterpret_cast(s); } + #endif /// @endcond public: @@ -158,9 +164,15 @@ class flat_map //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_map(const detail::moved_object >& x) : m_flat_tree(move(x.get().m_flat_tree)) {} + #else + flat_map(flat_map && x) + : m_flat_tree(move(x.m_flat_tree)) {} + #endif + //! Effects: Makes *this a copy of x. //! //! Complexity: Linear in x.size(). @@ -173,8 +185,13 @@ class flat_map //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_map& operator=(const detail::moved_object >& mx) { m_flat_tree = move(mx.get().m_flat_tree); return *this; } + #else + flat_map& operator=(flat_map && mx) + { m_flat_tree = move(mx.m_flat_tree); return *this; } + #endif //! Effects: 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& 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(k), move(T()))); + return (*i).second; + } + #endif //! Effects: 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 //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& x) { m_flat_tree.swap(x.get().m_flat_tree); } + #else + void swap(flat_map && x) + { m_flat_tree.swap(x.m_flat_tree); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE std::pair insert(const detail::moved_object& x) { return force >( m_flat_tree.insert_unique(force(x))); } + #else + std::pair insert(value_type &&x) + { return force >( + m_flat_tree.insert_unique(force(move(x)))); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator position, const detail::moved_object& x) { return force( m_flat_tree.insert_unique(force(position), force(x))); } + #else + iterator insert(iterator position, value_type &&x) + { return force( + m_flat_tree.insert_unique(force(position), force(move(x)))); } + #endif //! Requires: i, j are not iterators into *this. //! @@ -571,6 +623,7 @@ inline bool operator>=(const flat_map& x, const flat_map& y) { return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(flat_map& x, flat_map& y) @@ -585,6 +638,12 @@ template inline void swap(flat_map& x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(flat_map&&x, + flat_map&&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, - detail::select1st< detail::pair >, + select1st< detail::pair >, Pred, - typename boost::detail::allocator:: - rebind_to >::type> impl_tree_t; + typename Alloc::template + rebind >::other> impl_tree_t; typedef detail::flat_tree, - detail::select1st< std::pair >, + select1st< std::pair >, 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_moved_value_type; -/* - template - static D &force(S &s) - { return *(reinterpret_cast(&s)); } -*/ + #else + typedef impl_value_type&& impl_moved_value_type; + #endif + template static D &force(const S &s) { return *const_cast((reinterpret_cast(&s))); } + + #ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + static D &&force(S &&s) + { return reinterpret_cast(s); } + #endif /// @endcond public: @@ -726,8 +791,13 @@ class flat_multimap //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_multimap(const detail::moved_object >& x) : m_flat_tree(move(x.get().m_flat_tree)) { } + #else + flat_multimap(flat_multimap && x) + : m_flat_tree(move(x.m_flat_tree)) { } + #endif //! Effects: Makes *this a copy of x. //! @@ -739,9 +809,15 @@ class flat_multimap //! Effects: this->swap(x.get()). //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_multimap& operator=(const detail::moved_object >& mx) { m_flat_tree = move(mx.get().m_flat_tree); return *this; } + #else + flat_multimap& + operator=(flat_multimap && mx) + { m_flat_tree = move(mx.m_flat_tree); return *this; } + #endif //! Effects: Returns the comparison object out //! of which a was constructed. @@ -871,8 +947,13 @@ class flat_multimap //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& x) { m_flat_tree.swap(x.get().m_flat_tree); } + #else + void swap(flat_multimap && x) + { m_flat_tree.swap(x.m_flat_tree); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(const detail::moved_object& x) { return force(m_flat_tree.insert_equal(force(x))); } + #else + iterator insert(value_type &&x) + { return force(m_flat_tree.insert_equal(force(move(x)))); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator position, const detail::moved_object& x) { return force(m_flat_tree.insert_equal(force(position), force(x))); } + #else + iterator insert(iterator position, value_type &&x) + { return force(m_flat_tree.insert_equal(force(position), force(move(x)))); } + #endif //! Requires: i, j are not iterators into *this. //! @@ -1098,6 +1189,7 @@ inline bool operator>=(const flat_multimap& x, const flat_multimap& y) { return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(flat_multimap& x, flat_multimap& y) @@ -1113,6 +1205,12 @@ template inline void swap(flat_multimap& x, const detail::moved_object > & y) { x.swap(y.get()); } +#else +template +inline void swap(flat_multimap&&x, + flat_multimap&&y) + { x.swap(y); } +#endif /// @cond //!This class is movable diff --git a/include/boost/interprocess/containers/flat_set.hpp b/include/boost/interprocess/containers/flat_set.hpp index 969aeb1..8a76042 100644 --- a/include/boost/interprocess/containers/flat_set.hpp +++ b/include/boost/interprocess/containers/flat_set.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -60,7 +61,7 @@ class flat_set /// @cond private: typedef detail::flat_tree, Pred, Alloc> tree_t; + identity, Pred, Alloc> tree_t; tree_t m_flat_tree; // flat tree representing flat_set /// @endcond @@ -114,8 +115,13 @@ class flat_set //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_set(const detail::moved_object >& mx) : m_flat_tree(move(mx.get().m_flat_tree)) {} + #else + flat_set(flat_set && mx) + : m_flat_tree(move(mx.m_flat_tree)) {} + #endif //! Effects: Makes *this a copy of x. //! @@ -126,9 +132,16 @@ class flat_set //! Effects: Makes *this a copy of x. //! //! Complexity: Linear in x.size(). + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_set& operator=(const detail::moved_object > &mx) { m_flat_tree = move(mx.get().m_flat_tree); return *this; } + #else + flat_set& operator=(flat_set &&mx) + { m_flat_tree = move(mx.m_flat_tree); return *this; } + + #endif + //! Effects: Returns the comparison object out //! of which a was constructed. //! @@ -257,8 +270,13 @@ class flat_set //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& mx) { this->swap(mx.get()); } + #else + void swap(flat_set && mx) + { this->swap(mx); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE std::pair insert(const detail::moved_object& x) { return m_flat_tree.insert_unique(x); } + #else + std::pair insert(value_type && x) + { return m_flat_tree.insert_unique(move(x)); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator position, const detail::moved_object& 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 //! Requires: i, j are not iterators into *this. //! @@ -490,6 +518,7 @@ inline bool operator>=(const flat_set& x, const flat_set& y) { return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(flat_set& x, flat_set& y) @@ -504,6 +533,12 @@ template inline void swap(flat_set& x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(flat_set&&x, + flat_set&&y) + { x.swap(y); } +#endif /// @cond /*!This class is movable*/ @@ -543,7 +578,7 @@ class flat_multiset /// @cond private: typedef detail::flat_tree, Pred, Alloc> tree_t; + identity, 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& x) : m_flat_tree(x.m_flat_tree) {} + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_multiset(const detail::moved_object >& x) : m_flat_tree(move(x.get().m_flat_tree)) {} + #else + flat_multiset(flat_multiset && x) + : m_flat_tree(move(x.m_flat_tree)) {} + #endif flat_multiset& operator=(const flat_multiset& x) { m_flat_tree = x.m_flat_tree; return *this; } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE flat_multiset& operator=(const detail::moved_object >& mx) { m_flat_tree = move(mx.get().m_flat_tree); return *this; } + #else + flat_multiset& operator=(flat_multiset && mx) + { m_flat_tree = move(mx.m_flat_tree); return *this; } + #endif //! Effects: Returns the comparison object out //! of which a was constructed. @@ -717,8 +762,13 @@ class flat_multiset //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& mx) { this->swap(mx.get()); } + #else + void swap(flat_multiset && mx) + { this->swap(mx); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(const detail::moved_object& x) { return m_flat_tree.insert_equal(x); } + #else + iterator insert(value_type && x) + { return m_flat_tree.insert_equal(move(x)); } + #endif //! Effects: 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. //! //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator position, const detail::moved_object& 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 //! Requires: i, j are not iterators into *this. //! @@ -942,6 +1002,7 @@ inline bool operator>=(const flat_multiset& x, const flat_multiset& y) { return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(flat_multiset& x, flat_multiset& y) @@ -956,6 +1017,12 @@ template inline void swap(flat_multiset& x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(flat_multiset&&x, + flat_multiset&&y) + { x.swap(y); } +#endif /// @cond /*!This class is movable*/ diff --git a/include/boost/interprocess/containers/list.hpp b/include/boost/interprocess/containers/list.hpp index 975e012..601d460 100644 --- a/include/boost/interprocess/containers/list.hpp +++ b/include/boost/interprocess/containers/list.hpp @@ -55,17 +55,10 @@ #include #include #include -#include #include -#include #include -#include -#include -#include -#include +#include #include -#include - #include #include @@ -91,54 +84,66 @@ struct list_node , boost::intrusive::safe_link , VoidPointer> IlistData; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template list_node(const Convertible &conv) : m_data(conv) {} + #else + template + list_node(Convertible &&conv) + : m_data(forward(conv)) + {} + #endif T m_data; }; template struct list_alloc - : public boost::detail::allocator:: - rebind_to::type::pointer> - >::type + : public A::template rebind::type> + >::other { typedef list_alloc self_t; typedef typename A::value_type value_type; typedef list_node - ::type::pointer> Node; - typedef typename boost::detail::allocator:: - rebind_to::type NodeAlloc; + ::type> Node; + typedef typename A::template rebind::other NodeAlloc; typedef A ValAlloc; typedef typename NodeAlloc::pointer NodePtr; typedef detail::scoped_deallocator Deallocator; - enum { - node_has_trivial_destructor = - boost::has_trivial_destructor::value && - boost::has_trivial_destructor::value - }; - list_alloc(const ValAlloc &a) : NodeAlloc(a) {} + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE list_alloc(const detail::moved_object &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 &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 static void construct(const NodePtr &ptr, const Convertible &value) { new(detail::get_pointer(ptr)) Node(value); } + #else + template + static void construct(const NodePtr &ptr, Convertible &&value) + { new(detail::get_pointer(ptr)) Node(forward(value)); } + #endif static void destroy(const NodePtr &ptr) { detail::get_pointer(ptr)->~Node(); } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template NodePtr create_node(const Convertible& x) { NodePtr p = NodeAlloc::allocate(1); - scoped_ptrnode_deallocator(p, *this); + Deallocator node_deallocator(p, *this); self_t::construct(p, x); node_deallocator.release(); return (p); } + #else + template + NodePtr create_node(Convertible &&x) + { + NodePtr p = NodeAlloc::allocate(1); + Deallocator node_deallocator(p, *this); + self_t::construct(p, forward(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 //! Throws: If allocator_type's default constructor throws. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE list(const detail::moved_object &x) : AllocHolder(move((AllocHolder&)x.get())) {} + #else + list(list &&x) + : AllocHolder(move((AllocHolder&)x)) + {} + #endif //! Effects: 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 //! Throws: If memory allocation throws. //! //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void push_front(const detail::moved_object& x) { this->insert(this->begin(), x); } + #else + void push_front(T &&x) + { this->insert(this->begin(), move(x)); } + #endif //! Effects: Removes the last element from the list. //! @@ -597,8 +629,13 @@ class list //! Throws: Nothing. //! //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void push_back (const detail::moved_object& x) { this->insert(this->end(), x); } + #else + void push_back (T &&x) + { this->insert(this->end(), move(x)); } + #endif //! Effects: Removes the first element from the list. //! @@ -758,12 +795,21 @@ class list //! Throws: If allocator_type's copy constructor throws. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE ThisType& operator=(const detail::moved_object& mx) { this->clear(); this->swap(mx.get()); return *this; } + #else + ThisType& operator=(ThisType &&mx) + { + this->clear(); + this->swap(mx); + return *this; + } + #endif //! Requires: 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->priv_insert_dispatch(p, first, last, Result()); } @@ -811,11 +857,19 @@ class list //! Throws: If memory allocation throws. //! //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator p, const detail::moved_object& 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 //! Requires: 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->priv_assign_dispatch(first, last, Result()); } @@ -1143,7 +1197,7 @@ class list template 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 - 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 - 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 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& x, const list& y) return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(list& x, list& y) { @@ -1265,6 +1320,14 @@ inline void swap(list& x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(list &&x, list &&y) +{ + x.swap(y); +} + +#endif /// @cond /*!This class is movable*/ diff --git a/include/boost/interprocess/containers/map.hpp b/include/boost/interprocess/containers/map.hpp index 8778a96..a300ceb 100644 --- a/include/boost/interprocess/containers/map.hpp +++ b/include/boost/interprocess/containers/map.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gazta�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 #include #include +#include #include namespace boost { namespace interprocess { @@ -89,7 +90,7 @@ class map private: typedef detail::rbtree, - detail::select1st< std::pair >, + select1st< std::pair >, Pred, Alloc> tree_t; tree_t m_tree; // red-black tree representing map @@ -161,9 +162,15 @@ class map //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE map(const detail::moved_object >& x) : m_tree(move(x.get().m_tree)) {} + #else + map(map &&x) + : m_tree(move(x.m_tree)) + {} + #endif //! Effects: Makes *this a copy of x. //! @@ -174,8 +181,13 @@ class map //! Effects: this->swap(x.get()). //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE map& operator=(const detail::moved_object >& x) { m_tree = move(x.get().m_tree); return *this; } + #else + map& operator=(map &&x) + { m_tree = move(x.m_tree); return *this; } + #endif //! Effects: 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& 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 //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& x) { m_tree.swap(x.get().m_tree); } + #else + void swap(map &&x) + { m_tree.swap(x.m_tree); } + #endif //! Effects: 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. //! //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE std::pair insert(const detail::moved_object > &x) { return m_tree.insert_unique(x); } + #else + std::pair insert(std::pair &&x) + { return m_tree.insert_unique(move(x)); } + #endif //! Effects: 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. //! //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE std::pair insert(const detail::moved_object& x) { return m_tree.insert_unique(x); } + #else + std::pair insert(value_type &&x) + { return m_tree.insert_unique(move(x)); } + #endif //! Effects: 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 //! //! Complexity: 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 > &x) { return m_tree.insert_unique(position, x); } + #else + iterator insert(iterator position, std::pair &&x) + { return m_tree.insert_unique(position, move(x)); } + #endif //! Effects: 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 //! Returns: An iterator pointing to the element with key equivalent to the key of x. //! //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator position, const detail::moved_object& 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 //! Requires: i, j are not iterators into *this. //! @@ -603,6 +656,7 @@ inline bool operator>=(const map& x, const map& y) { return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(map& x, map& y) @@ -617,6 +671,15 @@ template inline void swap(map& x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(map&&x, + map&&y) + { x.swap(y); } +#endif + + + /// @cond /*!This class is movable*/ @@ -667,7 +730,7 @@ class multimap private: typedef detail::rbtree, - detail::select1st< std::pair >, + select1st< std::pair >, Pred, Alloc> tree_t; tree_t m_tree; // red-black tree representing map @@ -740,9 +803,15 @@ class multimap //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE multimap(const detail::moved_object >& x) : m_tree(move(x.get().m_tree)) {} + #else + multimap(multimap && x) + : m_tree(move(x.m_tree)) + {} + #endif //! Effects: Makes *this a copy of x. //! @@ -754,9 +823,15 @@ class multimap //! Effects: this->swap(x.get()). //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE multimap& operator=(const detail::moved_object >& x) { m_tree = move(x.get().m_tree); return *this; } + #else + multimap& + operator=(multimap && x) + { m_tree = move(x.m_tree); return *this; } + #endif //! Effects: Returns the comparison object out //! of which a was constructed. @@ -886,8 +961,13 @@ class multimap //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& x) { m_tree.swap(x.get().m_tree); } + #else + void swap(multimap && x) + { m_tree.swap(x.m_tree); } + #endif //! Effects: 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. //! //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(const detail::moved_object >& x) { return m_tree.insert_equal(x); } + #else + iterator insert(std::pair && x) + { return m_tree.insert_equal(move(x)); } + #endif //! Effects: 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 //! //! Complexity: 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 >& x) { return m_tree.insert_equal(position, x); } + #else + iterator insert(iterator position, std::pair && x) + { return m_tree.insert_equal(position, move(x)); } + #endif //! Requires: i, j are not iterators into *this. //! @@ -1088,6 +1178,8 @@ inline bool operator>=(const multimap& x, const multimap& y) { return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(multimap& x, multimap& y) @@ -1102,6 +1194,12 @@ template inline void swap(multimap& x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(multimap&&x, + multimap&&y) +{ x.swap(y); } +#endif /// @cond template diff --git a/include/boost/interprocess/containers/set.hpp b/include/boost/interprocess/containers/set.hpp index 47b19ba..f49d601 100644 --- a/include/boost/interprocess/containers/set.hpp +++ b/include/boost/interprocess/containers/set.hpp @@ -49,15 +49,17 @@ #include #include -#include #include + #include #include #include + +#include +#include #include #include - namespace boost { namespace interprocess { /// @cond @@ -84,7 +86,7 @@ class set /// @cond private: typedef detail::rbtree, Pred, Alloc> tree_t; + identity, Pred, Alloc> tree_t; tree_t m_tree; // red-black tree representing set /// @endcond @@ -138,9 +140,15 @@ class set //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE set(const detail::moved_object >& x) : m_tree(move(x.get().m_tree)) {} + #else + set(set &&x) + : m_tree(move(x.m_tree)) + {} + #endif //! Effects: Makes *this a copy of x. //! @@ -151,8 +159,13 @@ class set //! Effects: this->swap(x.get()). //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE set& operator=(const detail::moved_object >& x) { m_tree = move(x.get().m_tree); return *this; } + #else + set& operator=(set &&x) + { m_tree = move(x.m_tree); return *this; } + #endif //! Effects: Returns the comparison object out //! of which a was constructed. @@ -282,8 +295,13 @@ class set //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& x) { m_tree.swap(x.get().m_tree); } + #else + void swap(set &&x) + { m_tree.swap(x.m_tree); } + #endif //! Effects: 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. //! //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE std::pair insert(const detail::moved_object& x) { return m_tree.insert_unique(x); } + #else + std::pair insert(value_type &&x) + { return m_tree.insert_unique(move(x)); } + #endif //! Effects: 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 //! Returns: An iterator pointing to the element with key equivalent to the key of x. //! //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(const_iterator p, const detail::moved_object& 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 //! Requires: i, j are not iterators into *this. //! @@ -473,6 +501,7 @@ inline bool operator>=(const set& x, const set& y) { return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(set& x, set& y) @@ -488,6 +517,13 @@ inline void swap(detail::moved_object >& y, set& x) { y.swap(x.get()); } +#else +template +inline void swap(set&&x, + set&&y) +{ x.swap(y); } +#endif + /// @cond /*!This class is movable*/ template @@ -530,7 +566,7 @@ class multiset /// @cond private: typedef detail::rbtree, Pred, Alloc> tree_t; + identity, Pred, Alloc> tree_t; tree_t m_tree; // red-black tree representing multiset /// @endcond @@ -585,9 +621,15 @@ class multiset //! Complexity: Construct. //! //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE multiset(const detail::moved_object >& x) : m_tree(move(x.get().m_tree)) {} + #else + multiset(multiset &&x) + : m_tree(move(x.m_tree)) + {} + #endif //! Effects: Makes *this a copy of x. //! @@ -598,8 +640,13 @@ class multiset //! Effects: this->swap(x.get()). //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE multiset& operator=(const detail::moved_object >& x) { m_tree = move(x.get().m_tree); return *this; } + #else + multiset& operator=(multiset &&x) + { m_tree = move(x.m_tree); return *this; } + #endif //! Effects: Returns the comparison object out //! of which a was constructed. @@ -729,8 +776,13 @@ class multiset //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& x) { m_tree.swap(x.get().m_tree); } + #else + void swap(multiset && x) + { m_tree.swap(x.m_tree); } + #endif //! Effects: Inserts x and returns the iterator pointing to the //! newly inserted element. @@ -746,8 +798,13 @@ class multiset //! //! Complexity: Logarithmic in general, but amortized constant if t //! is inserted right before p. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(const detail::moved_object& x) { return m_tree.insert_equal(x); } + #else + iterator insert(value_type && x) + { return m_tree.insert_equal(move(x)); } + #endif //! Effects: 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 //! //! Complexity: 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& 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 //! Requires: i, j are not iterators into *this. //! @@ -916,6 +978,7 @@ inline bool operator>=(const multiset& x, const multiset& y) { return !(x < y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(multiset& x, multiset& y) @@ -930,6 +993,12 @@ template inline void swap(detail::moved_object >& y, multiset& x) { y.swap(x.get()); } +#else +template +inline void swap(multiset&&x, + multiset&&y) +{ x.swap(y); } +#endif /// @cond /*!This class is movable*/ diff --git a/include/boost/interprocess/containers/slist.hpp b/include/boost/interprocess/containers/slist.hpp index aa59563..75157aa 100644 --- a/include/boost/interprocess/containers/slist.hpp +++ b/include/boost/interprocess/containers/slist.hpp @@ -54,12 +54,12 @@ #include #include #include -#include #include #include +#include +#include #include #include -#include #include #include @@ -83,54 +83,65 @@ struct slist_node , boost::intrusive::safe_link , VoidPointer> IslistData; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template slist_node(const Convertible &value) : m_data(value){} + #else + template + slist_node(Convertible &&value) + : m_data(forward(value)){} + #endif T m_data; }; template struct slist_alloc - : public boost::detail::allocator:: - rebind_to::type::pointer> - >::type + : public A::template rebind::type> + >::other { typedef slist_alloc self_t; typedef typename A::value_type value_type; typedef slist_node - ::type::pointer> Node; - typedef typename boost::detail::allocator:: - rebind_to::type NodeAlloc; + ::type> Node; + typedef typename A::template rebind::other NodeAlloc; typedef A ValAlloc; typedef typename A::size_type SizeType; typedef typename NodeAlloc::pointer NodePtr; typedef detail::scoped_deallocator Deallocator; - enum { - node_has_trivial_destructor = - boost::has_trivial_destructor::value && - boost::has_trivial_destructor::value - }; - slist_alloc(const ValAlloc &a) : NodeAlloc(a) {} + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE slist_alloc(const detail::moved_object &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 &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 static void construct(const NodePtr &ptr, const Convertible &value) { new(detail::get_pointer(ptr)) Node(value); } + #else + template + static void construct(const NodePtr &ptr, Convertible &&value) + { new(detail::get_pointer(ptr)) Node(forward(value)); } + #endif static void destroy(const NodePtr &ptr) { detail::get_pointer(ptr)->~Node(); } + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template NodePtr create_node(const Convertible& x) { NodePtr p = NodeAlloc::allocate(1); - scoped_ptrnode_deallocator(p, *this); + Deallocator node_deallocator(p, *this); self_t::construct(p, x); node_deallocator.release(); return (p); } + #else + template + NodePtr create_node(Convertible &&x) + { + NodePtr p = NodeAlloc::allocate(1); + Deallocator node_deallocator(p, *this); + self_t::construct(p, forward(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 //! Throws: If allocator_type's default constructor throws. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE slist(const detail::moved_object &x) : AllocHolder(move((AllocHolder&)x.get())) {} + #else + slist(slist &&x) + : AllocHolder(move((AllocHolder&)x)) + {} + #endif //! Effects: Makes *this contain the same elements as x. //! @@ -456,6 +489,7 @@ class slist //! Throws: If memory allocation throws or T's copy constructor throws. //! //! Complexity: Linear to the number of elements in x. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE slist& operator= (const detail::moved_object& 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 //! Effects: 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->assign_dispatch(first, last, Result()); } @@ -629,8 +673,13 @@ class slist //! Throws: If memory allocation throws. //! //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void push_front(const detail::moved_object& 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 //! Effects: Removes the first element from the list. //! @@ -689,8 +738,13 @@ class slist //! //! Note: 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& 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 //! Requires: prev_pos must be a valid iterator of *this. //! @@ -738,8 +792,13 @@ class slist //! Throws: If memory allocation throws. //! //! Complexity: Linear to the elements before p. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE iterator insert(iterator p, const detail::moved_object& x) { return insert_after(previous(p), x); } + #else + iterator insert(iterator p, value_type && x) + { return insert_after(previous(p), move(x)); } + #endif //! Requires: p must be a valid iterator of *this. //! @@ -1223,12 +1282,12 @@ class slist } template - 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 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->insert_after_range(prev_pos, first, last, Result()); } template - 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 - 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& sL1, const slist& sL2) { return !(sL1 < sL2); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(slist& x, slist& y) { x.swap(y); } @@ -1360,6 +1420,11 @@ inline void swap(const detail::moved_object >& x, slist& y) template inline void swap(slist& x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(slist&&x, slist&&y) + { x.swap(y); } +#endif /// @cond /*!This class is movable*/ diff --git a/include/boost/interprocess/containers/string.hpp b/include/boost/interprocess/containers/string.hpp index 3064cd2..0f6eafa 100644 --- a/include/boost/interprocess/containers/string.hpp +++ b/include/boost/interprocess/containers/string.hpp @@ -30,15 +30,18 @@ #include #include -#include -#include #include #include #include +#include +#include +#include #include #include +#include #include #include + #include #include #include @@ -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 >& b) : allocator_type(static_cast(b.get())) { init(); this->swap(b.get()); } + #else + basic_string_base(basic_string_base && b) + : allocator_type(static_cast(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 //! Throws: If allocator_type's copy constructor throws. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE basic_string(const detail::moved_object& s) : base_t(move((base_t&)s.get())) {} + #else + basic_string(basic_string && s) + : base_t(move((base_t&)s)) + {} + #endif //! Effects: 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->priv_initialize_dispatch(f, l, Result()); } @@ -600,6 +621,7 @@ class basic_string //! Throws: If allocator_type's copy constructor throws. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE basic_string& operator=(const detail::moved_object& 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 //! Effects: 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); } //! Effects: Moves the resources from ms *this. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE basic_string& assign(const detail::moved_object& ms) { return this->operator=(ms);} + #else + basic_string& assign(basic_string && ms) + { return this->operator=(ms);} + #endif //! Effects: 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ 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::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; return this->priv_replace_dispatch(first, last, f, l, Result()); } @@ -1210,8 +1247,13 @@ class basic_string { base_t::swap(s); } //! Effects: Swaps the contents of two strings. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object& ms) { this->swap(ms.get()); } + #else + void swap(basic_string && ms) + { this->swap(ms); } + #endif //! Returns: 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(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 - 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(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 - 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 inline - void priv_uninitialized_fill_n(FwdIt first, Count count, - const CharT val, Alloc& al) + template 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 inline - size_type priv_uninitialized_copy(InpIt first, InpIt last, - FwdIt dest, Alloc& al) + template 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 - 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 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 void priv_insert_dispatch(iterator p, Integer n, Integer x, - boost::mpl::true_) + true_) { insert(p, (size_type) n, (CharT) x); } template void priv_insert_dispatch(iterator p, InputIter first, InputIter last, - boost::mpl::false_) + false_) { typedef typename std::iterator_traits::iterator_category Category; priv_insert(p, first, last, Category()); @@ -1799,13 +1838,13 @@ class basic_string template 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 basic_string& priv_replace_dispatch(iterator first, iterator last, InputIter f, InputIter l, - boost::mpl::false_) + false_) { typedef typename std::iterator_traits::iterator_category Category; return this->priv_replace(first, last, f, l, Category()); @@ -1872,6 +1911,7 @@ operator+(const basic_string& x, return result; } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline detail::moved_object > operator+(const detail::moved_object >& mx, @@ -1880,15 +1920,36 @@ operator+(const detail::moved_object >& mx, mx.get() += y; return mx; } +#else +template +basic_string && +operator+(basic_string && mx, + const basic_string& y) +{ + mx += y; + return move(mx); +} +#endif +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline detail::moved_object > operator+(const basic_string& x, const detail::moved_object >& my) { - my.get() += x; - return my; + typedef typename basic_string::size_type size_type; + return my.get().replace(size_type(0), size_type(0), x); } +#else +template +inline basic_string && +operator+(const basic_string& x, + basic_string && my) +{ + typedef typename basic_string::size_type size_type; + return my.replace(size_type(0), size_type(0), x); +} +#endif template inline basic_string @@ -1904,6 +1965,26 @@ operator+(const CharT* s, const basic_string& y) return result; } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const CharT* s, + const detail::moved_object >& my) +{ + typedef typename basic_string::size_type size_type; + return my.get().replace(size_type(0), size_type(0), s); +} +#else +template +inline basic_string && +operator+(const CharT* s, + basic_string && my) +{ + typedef typename basic_string::size_type size_type; + return move(my.get().replace(size_type(0), size_type(0), s)); +} +#endif + template inline basic_string operator+(CharT c, const basic_string& y) @@ -1917,6 +1998,26 @@ operator+(CharT c, const basic_string& y) return result; } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(CharT c, + const detail::moved_object >& my) +{ + typedef typename basic_string::size_type size_type; + return my.get().replace(size_type(0), size_type(0), &c, &c + 1); +} +#else +template +inline basic_string && +operator+(CharT c, + basic_string && my) +{ + typedef typename basic_string::size_type size_type; + return my.replace(size_type(0), size_type(0), &c, &c + 1); +} +#endif + template inline basic_string operator+(const basic_string& x, const CharT* s) @@ -1931,6 +2032,26 @@ operator+(const basic_string& x, const CharT* s) return result; } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const detail::moved_object >& mx, + const CharT* s) +{ + mx.get() += s; + return mx; +} +#else +template +basic_string && +operator+(basic_string && mx, + const CharT* s) +{ + mx += s; + return move(mx); +} +#endif + template inline basic_string operator+(const basic_string& x, const CharT c) @@ -1944,6 +2065,25 @@ operator+(const basic_string& x, const CharT c) return result; } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const detail::moved_object >& mx, + const CharT c) +{ + mx.get() += c; + return mx; +} +#else +template +basic_string && +operator+(basic_string && mx, const CharT c) +{ + mx += c; + return move(mx); +} +#endif + // Operator== and operator!= template @@ -2076,7 +2216,7 @@ operator>=(const basic_string& x, const CharT* s) { return !(x < s); } // Swap. - +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(basic_string& x, basic_string& y) @@ -2091,7 +2231,12 @@ template inline void swap(basic_string& x, const detail::moved_object >& my) { x.swap(my.get()); } - +#else +template +inline void swap(basic_string && x, + basic_string &&y) +{ x.swap(y); } +#endif /// @cond // I/O. @@ -2118,7 +2263,11 @@ interprocess_string_fill(std::basic_ostream& os, template std::basic_ostream& operator<<(std::basic_ostream& os, + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE const basic_string& s) + #else + const basic_string&&s) + #endif { typename std::basic_ostream::sentry sentry(os); bool ok = false; @@ -2150,16 +2299,23 @@ operator<<(std::basic_ostream& os, return os; } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template std::basic_ostream& operator<<(std::basic_ostream& os, const detail::moved_object >& ms) { return os << ms.get(); } +#endif + template std::basic_istream& operator>>(std::basic_istream& is, + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE basic_string& s) + #else + basic_string&&s) + #endif { typename std::basic_istream::sentry sentry(is); @@ -2204,16 +2360,22 @@ operator>>(std::basic_istream& is, return is; } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template std::basic_istream& operator>>(std::basic_istream& is, const detail::moved_object >& ms) { return is >> ms.get(); } +#endif template std::basic_istream& getline(std::istream& is, + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE basic_string& s, + #else + basic_string&&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 +std::basic_istream& +getline(std::istream& is, + const detail::moved_object >& ms, + CharT delim) +{ return getline(is, ms.get(), delim); } +#endif + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline std::basic_istream& getline(std::basic_istream& is, @@ -2256,15 +2428,15 @@ getline(std::basic_istream& is, template std::basic_istream& getline(std::istream& is, - const detail::moved_object >& ms, - CharT delim) -{ return getline(is, ms.get(), delim); } - + const detail::moved_object >& ms) +{ return getline(is, ms.get()); } +#else template std::basic_istream& getline(std::istream& is, - const detail::moved_object >& ms) -{ return getline(is, ms.get()); } + basic_string && ms) +{ return getline(is, ms); } +#endif template inline std::size_t hash_value(basic_string, A> const& v) diff --git a/include/boost/interprocess/containers/vector.hpp b/include/boost/interprocess/containers/vector.hpp index 119caed..2332bfe 100644 --- a/include/boost/interprocess/containers/vector.hpp +++ b/include/boost/interprocess/containers/vector.hpp @@ -45,27 +45,31 @@ #include #include -#include -#include -#include -#include -#include -#include -#include + #include #include #include #include #include #include + #include -#include -#include -#include -#include -#include +#include +#include #include #include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include 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 }; + enum { trivial_dctr_after_move = + has_trivial_destructor_after_move::value || + boost::has_trivial_destructor::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 > &h) : A(move((A&)h.get())), m_start(0), m_size(0), m_capacity(0) {} + #else + vector_alloc_holder(vector_alloc_holder &&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) - A::destroy(p); + detail::get_pointer(p)->~value_type(); } void destroy_n(pointer p, size_type n) { if(!has_trivial_destructor::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 //! Throws: If allocator_type's copy constructor throws. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE vector(const detail::moved_object >& mx) : base_t(move((base_t&)mx.get())) { @@ -420,6 +433,19 @@ class vector : private detail::vector_alloc_holder x.m_size = 0; x.m_capacity = 0; } + #else + vector(vector && mx) + : base_t(move((base_t&)mx)) + { + vector &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 //! Effects: 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 //There is not enough memory, allocate a new //buffer or expand the old one. bool same_buffer_start; + size_type real_cap; std::pair 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 //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 //! Throws: If allocator_type's copy constructor throws. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE vector& operator=(const detail::moved_object >& mx) { vector &x = mx.get(); @@ -715,6 +743,19 @@ class vector : private detail::vector_alloc_holder } return *this; } + #else + vector& operator=(vector && mx) + { + vector &x = mx; + + if (&x != this){ + this->swap(x); + x.clear(); +//? base_t::prot_deallocate(); + } + return *this; + } + #endif //! Effects: Assigns the n copies of val to *this. //! @@ -735,7 +776,7 @@ class vector : private detail::vector_alloc_holder { //Dispatch depending on integer/iterator const bool aux_boolean = boost::is_integral::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->priv_assign_dispatch(first, last, Result()); } @@ -749,7 +790,7 @@ class vector : private detail::vector_alloc_holder { 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 //! Throws: If memory allocation throws. //! //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void push_back(const detail::moved_object & 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 + //! Effects: 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 //! Throws: Nothing. //! //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object >& mx) { vector &x = mx.get(); this->swap(x); } + #else + void swap(vector && mx) + { + vector &x = mx; + this->swap(x); + } + #endif //! Requires: position must be a valid iterator of *this. //! @@ -832,6 +895,7 @@ class vector : private detail::vector_alloc_holder //! //! Complexity: 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 &mx) { typedef repeat_iterator r_iterator; @@ -843,6 +907,19 @@ class vector : private detail::vector_alloc_holder ,move_it(r_iterator())); return iterator(this->m_start + n); } + #else + iterator insert(iterator position, T &&mx) + { + typedef repeat_iterator r_iterator; + typedef detail::move_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 //! Requires: pos must be a valid iterator of *this. //! @@ -857,7 +934,7 @@ class vector : private detail::vector_alloc_holder { //Dispatch depending on integer/iterator const bool aux_boolean = boost::is_integral::value; - typedef boost::mpl::bool_ Result; + typedef bool_ Result; this->priv_insert_dispatch(pos, first, last, Result()); } @@ -999,7 +1076,7 @@ class vector : private detail::vector_alloc_holder size_type remaining = this->m_capacity - this->m_size; bool same_buffer_start; std::pair 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 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 //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 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(*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 //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(*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(*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 { typedef detail::move_iterator move_it; //Anti-exception rollback - scoped_ptr 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(*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(*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(*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 } 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 (pointer new_start, size_type new_capacity, pointer pos, FwdIt first, FwdIt last, size_type n) { - typedef detail::scoped_destructor_n - ValueArrayDestructor; + typedef detail::scoped_destructor_n ValueArrayDestructor; typedef detail::move_iterator move_it; //Backup old data pointer old_start = this->m_start; @@ -1134,9 +1213,7 @@ class vector : private detail::vector_alloc_holder //If anything goes wrong, this object will destroy //all the old objects to fulfill previous vector state - scoped_ptr - old_values_destroyer - (old_start, ValueArrayDestructor(static_cast(*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 // //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(*this)); - scoped_ptr - new_values_destroyer(new_start - ,ValueArrayDestructor(static_cast(*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(*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 // //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(*this)); - scoped_ptr - new_values_destroyer(new_start - ,ValueArrayDestructor(static_cast(*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(*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 // //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(*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 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(*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 // //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(*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 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(*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 size_type remaining = this->m_capacity - this->m_size; bool same_buffer_start; std::pair 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 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(*this)); + boost::interprocess::n_uninitialized_copy + (mid, last, this->m_start + this->m_size); this->m_size = n; } } else if(!ret.second){ - scoped_ptr scoped_alloc(ret.first, dealloc_t(*this, new_cap)); - n_uninitialized_copy(first, last, ret.first, static_cast(*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 - ValueArrayDestructor; + typedef detail::scoped_destructor_n ValueArrayDestructor; pointer old_start = this->m_start; size_type old_size = this->m_size; - scoped_ptr - old_values_destroyer(old_start - ,ValueArrayDestructor(static_cast(*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(*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 //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(*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 } template - 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 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 template 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 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 } template - 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 template 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 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 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 scoped_alloc(result, dealloc_t(*this, cap)); - n_uninitialized_copy(first, last, result, static_cast(*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& x, const vector& y) y.begin(), y.end()); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(vector& x, vector& y) { x.swap(y); } @@ -1677,6 +1739,11 @@ inline void swap(const detail::moved_object >& x, vector& y) template inline void swap(vector &x, const detail::moved_object >& y) { x.swap(y.get()); } +#else +template +inline void swap(vector&&x, vector&&y) +{ x.swap(y); } +#endif /// @cond /*!This class is movable*/ diff --git a/include/boost/interprocess/detail/Attic/basic_segment_manager.hpp b/include/boost/interprocess/detail/Attic/basic_segment_manager.hpp new file mode 100644 index 0000000..0405699 --- /dev/null +++ b/include/boost/interprocess/detail/Attic/basic_segment_manager.hpp @@ -0,0 +1,389 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP +#define BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include //std::size_t +#include //char_traits +#include //std::nothrow +#include //std::pair +#ifndef BOOST_NO_EXCEPTIONS +#include +#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 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 + 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 + std::size_t total_size_with_header() const + { + return get_rounded_size + ( sizeof(Header) + , boost::alignment_of::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 + CharType *name() const + { + return reinterpret_cast + (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 + 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::compare + (name(), b.name(), m_num_char) < 0); + } + + template + bool equal(const block_header &b) const + { + return m_num_char == b.m_num_char && + std::char_traits::compare + (name(), b.name(), m_num_char) == 0; + } + + template + static block_header *block_header_from_value(T *value) + { return block_header_from_value(value, sizeof(T), boost::alignment_of::value); } + + static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) + { + block_header * hdr = + reinterpret_cast(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 + static block_header *from_first_header(Header *header) + { + block_header * hdr = + reinterpret_cast(detail::char_ptr_cast(header) + + get_rounded_size(sizeof(Header), boost::alignment_of::value)); + //Some sanity checks + return hdr; + } + + template + static Header *to_first_header(block_header *bheader) + { + Header * hdr = + reinterpret_cast(detail::char_ptr_cast(bheader) - + get_rounded_size(sizeof(Header), boost::alignment_of::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 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) == 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 + 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 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 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 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 + +#endif //#ifndef BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP + diff --git a/include/boost/interprocess/detail/Attic/generic_cast.hpp b/include/boost/interprocess/detail/Attic/generic_cast.hpp index 0ac9c89..5781ffa 100644 --- a/include/boost/interprocess/detail/Attic/generic_cast.hpp +++ b/include/boost/interprocess/detail/Attic/generic_cast.hpp @@ -18,9 +18,6 @@ #include #include -#include - - namespace boost{ namespace interprocess{ diff --git a/include/boost/interprocess/detail/algorithms.hpp b/include/boost/interprocess/detail/algorithms.hpp new file mode 100644 index 0000000..8629885 --- /dev/null +++ b/include/boost/interprocess/detail/algorithms.hpp @@ -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 +#include +#include +#include + +namespace boost { +namespace interprocess { + +template +void uninitialized_fill(FwdIt first, FwdIt last, const T& val) +{ + typedef typename std::iterator_traits::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 +void uninitialized_fill_n(FwdIt first, Count count, + const T& val) +{ + typedef typename std::iterator_traits::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 +InIt copy_n(InIt first, typename std::iterator_traits::difference_type length, OutIt dest) +{ + for (; length--; ++dest, ++first) + *dest = *first; + return first; +} + +template +typename std::iterator_traits::difference_type + n_uninitialized_copy(InIt first, InIt last, FwdIt dest) +{ + typedef typename std::iterator_traits::value_type value_type; + //Save initial destination position + FwdIt dest_init = dest; + typename std::iterator_traits::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 inline +FwdIt uninitialized_copy(InIt first, InIt last, FwdIt dest) +{ + typedef typename std::iterator_traits::value_type value_type; + //Save initial destination position + FwdIt dest_init = dest; + typename std::iterator_traits::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 inline +InIt n_uninitialized_copy_n + (InIt first, + typename std::iterator_traits::difference_type count, + FwdIt dest) +{ + typedef typename std::iterator_traits::value_type value_type; + //Save initial destination position + FwdIt dest_init = dest; + typename std::iterator_traits::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 +FwdIt uninitialized_copy_copy(InpIt1 first1, InpIt1 last1, + InpIt2 first2, InpIt2 last2, + FwdIt result) +{ + typedef typename std::iterator_traits::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 +InpIt2 uninitialized_copy_n_copy_n + (InpIt1 first1, + typename std::iterator_traits::difference_type n1, + InpIt2 first2, + typename std::iterator_traits::difference_type n2, + FwdIt result) +{ + typedef typename std::iterator_traits::value_type value_type; + typename std::iterator_traits::difference_type c1 = n1+1; + typename std::iterator_traits::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:: + 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 + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP + diff --git a/include/boost/interprocess/detail/atomic.hpp b/include/boost/interprocess/detail/atomic.hpp index 49e4dd1..61f0bb1 100644 --- a/include/boost/interprocess/detail/atomic.hpp +++ b/include/boost/interprocess/detail/atomic.hpp @@ -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 +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(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(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(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(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(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(mem), val); } //! Atomically set an boost::uint32_t in memory //! "mem": pointer to the object diff --git a/include/boost/interprocess/detail/basic_segment_manager.hpp b/include/boost/interprocess/detail/basic_segment_manager.hpp new file mode 100644 index 0000000..0405699 --- /dev/null +++ b/include/boost/interprocess/detail/basic_segment_manager.hpp @@ -0,0 +1,389 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP +#define BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include //std::size_t +#include //char_traits +#include //std::nothrow +#include //std::pair +#ifndef BOOST_NO_EXCEPTIONS +#include +#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 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 + 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 + std::size_t total_size_with_header() const + { + return get_rounded_size + ( sizeof(Header) + , boost::alignment_of::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 + CharType *name() const + { + return reinterpret_cast + (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 + 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::compare + (name(), b.name(), m_num_char) < 0); + } + + template + bool equal(const block_header &b) const + { + return m_num_char == b.m_num_char && + std::char_traits::compare + (name(), b.name(), m_num_char) == 0; + } + + template + static block_header *block_header_from_value(T *value) + { return block_header_from_value(value, sizeof(T), boost::alignment_of::value); } + + static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) + { + block_header * hdr = + reinterpret_cast(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 + static block_header *from_first_header(Header *header) + { + block_header * hdr = + reinterpret_cast(detail::char_ptr_cast(header) + + get_rounded_size(sizeof(Header), boost::alignment_of::value)); + //Some sanity checks + return hdr; + } + + template + static Header *to_first_header(block_header *bheader) + { + Header * hdr = + reinterpret_cast(detail::char_ptr_cast(bheader) - + get_rounded_size(sizeof(Header), boost::alignment_of::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 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) == 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 + 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 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 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 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 + +#endif //#ifndef BOOST_INTERPROCESS_BASIC_SEGMENT_MANAGER_HPP + diff --git a/include/boost/interprocess/detail/config_begin.hpp b/include/boost/interprocess/detail/config_begin.hpp index 7eaab8b..313d37d 100644 --- a/include/boost/interprocess/detail/config_begin.hpp +++ b/include/boost/interprocess/detail/config_begin.hpp @@ -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 diff --git a/include/boost/interprocess/detail/config_end.hpp b/include/boost/interprocess/detail/config_end.hpp index 0c45cfa..14eceb1 100644 --- a/include/boost/interprocess/detail/config_end.hpp +++ b/include/boost/interprocess/detail/config_end.hpp @@ -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 diff --git a/include/boost/interprocess/detail/file_wrapper.hpp b/include/boost/interprocess/detail/file_wrapper.hpp index 8c2b2e0..15d6a4d 100644 --- a/include/boost/interprocess/detail/file_wrapper.hpp +++ b/include/boost/interprocess/detail/file_wrapper.hpp @@ -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 &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 &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); diff --git a/include/boost/interprocess/detail/in_place_interface.hpp b/include/boost/interprocess/detail/in_place_interface.hpp new file mode 100644 index 0000000..fc0ee2e --- /dev/null +++ b/include/boost/interprocess/detail/in_place_interface.hpp @@ -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 +#include +#include +#include //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 +struct placement_destroy : public in_place_interface +{ + placement_destroy() + : in_place_interface(boost::alignment_of::value, sizeof(T), typeid(T).name()) + {} + + virtual void destroy(void *mem) + { static_cast(mem)->~T(); } + + virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) + { + T* memory = static_cast(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 + +#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP diff --git a/include/boost/interprocess/detail/iterators.hpp b/include/boost/interprocess/detail/iterators.hpp new file mode 100644 index 0000000..998d844 --- /dev/null +++ b/include/boost/interprocess/detail/iterators.hpp @@ -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 +#include + +#include +#include + +namespace boost { +namespace interprocess { + +template +class constant_iterator + : public boost::iterator_facade + < constant_iterator + , T + , boost::random_access_traversal_tag + , const T & + , Difference> +{ + typedef boost::iterator_facade + < constant_iterator + , T + , boost::random_access_traversal_tag + , const T & + , Difference> super_t; + + typedef constant_iterator 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 repeat_iterator + : public boost::iterator_facade + < repeat_iterator + , T + , boost::random_access_traversal_tag + , T & + , Difference> +{ + typedef boost::iterator_facade + < repeat_iterator + , T + , boost::random_access_traversal_tag + , T & + , Difference> super_t; + + typedef repeat_iterator 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 + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP + diff --git a/include/boost/interprocess/detail/managed_memory_impl.hpp b/include/boost/interprocess/detail/managed_memory_impl.hpp index a91417c..912ac1f 100644 --- a/include/boost/interprocess/detail/managed_memory_impl.hpp +++ b/include/boost/interprocess/detail/managed_memory_impl.hpp @@ -84,10 +84,15 @@ class basic_managed_memory_impl public: typedef typename segment_manager_type ::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 - typename segment_manager::template construct_proxy::type + typename segment_manager::template construct_proxy::type construct(char_ptr_holder_t name) { return mp_header->construct(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 - typename segment_manager::template find_construct_proxy::type + typename segment_manager::template construct_proxy::type find_or_construct(char_ptr_holder_t name) { return mp_header->find_or_construct(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 - typename segment_manager::template construct_proxy::type + typename segment_manager::template construct_proxy::type construct(char_ptr_holder_t name, std::nothrow_t nothrow) { return mp_header->construct(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 - typename segment_manager::template find_construct_proxy::type + typename segment_manager::template construct_proxy::type find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow) { return mp_header->find_or_construct(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 - typename segment_manager::template construct_iter_proxy::type + typename segment_manager::template construct_iter_proxy::type construct_it(char_ptr_holder_t name) { return mp_header->construct_it(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 - typename segment_manager::template find_construct_iter_proxy::type + typename segment_manager::template construct_iter_proxy::type find_or_construct_it(char_ptr_holder_t name) { return mp_header->find_or_construct_it(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 - typename segment_manager::template construct_iter_proxy::type + typename segment_manager::template construct_iter_proxy::type construct_it(char_ptr_holder_t name, std::nothrow_t nothrow) { return mp_header->construct_it(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 - typename segment_manager::template find_construct_iter_proxy::type + typename segment_manager::template construct_iter_proxy::type find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow) { return mp_header->find_or_construct_it(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 - 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: diff --git a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp index 475e99a..328cffe 100644 --- a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -19,8 +19,8 @@ #include #include #include +#include #include -#include 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 &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 &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 - static void write_whole_device(DeviceAbstraction &, std::size_t, boost::mpl::false_) + static void write_whole_device(DeviceAbstraction &, std::size_t, false_) {} //Empty template - 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 - static void truncate_device(DeviceAbstraction &, std::size_t, boost::mpl::false_) + static void truncate_device(DeviceAbstraction &, std::size_t, false_) {} //Empty template - 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 - 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 - 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_ file_like_t; + typedef bool_ file_like_t; (void)mode; error_info err; bool created = false; diff --git a/include/boost/interprocess/detail/min_max.hpp b/include/boost/interprocess/detail/min_max.hpp new file mode 100644 index 0000000..92eb959 --- /dev/null +++ b/include/boost/interprocess/detail/min_max.hpp @@ -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 +#include + +namespace boost { +namespace interprocess { + +template +const T &max_value(const T &a, const T &b) +{ return a > b ? a : b; } + +template +const T &min_value(const T &a, const T &b) +{ return a < b ? a : b; } + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP + diff --git a/include/boost/interprocess/detail/move.hpp b/include/boost/interprocess/detail/move.hpp index 812598f..4268821 100644 --- a/include/boost/interprocess/detail/move.hpp +++ b/include/boost/interprocess/detail/move.hpp @@ -17,7 +17,6 @@ #include #include -#include /*!\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 + +namespace boost { +namespace interprocess { namespace detail { /*!An object that represents a moved object.*/ @@ -54,11 +62,7 @@ template struct move_type { public: // metafunction result - typedef typename mpl::if_< - is_movable - , moved_object - , T& - >::type type; + typedef typename if_, moved_object, T&>::type type; }; template @@ -87,14 +91,15 @@ struct return_type { public: // metafunction result - typedef typename boost::mpl::if_ - - , move_return - , T - >::type type; + typedef typename if_, move_return, 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::type move } //namespace interprocess { } //namespace boost { +#else //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + +#include + +namespace boost { +namespace interprocess { + +template +inline typename boost::remove_reference::type&& +move(T&& t) +{ return t; } + +template +inline +T&& +forward(typename identity::type&& t) +{ return t; } + +} //namespace interprocess { +} //namespace boost { + +#endif //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + #include #endif //#ifndef BOOST_INTERPROCESS_MOVE_HPP diff --git a/include/boost/interprocess/detail/move_iterator.hpp b/include/boost/interprocess/detail/move_iterator.hpp index 3b1a4b1..ce5ae71 100644 --- a/include/boost/interprocess/detail/move_iterator.hpp +++ b/include/boost/interprocess/detail/move_iterator.hpp @@ -25,7 +25,11 @@ class move_iterator public: typedef typename boost::remove_reference::type iterator_type; typedef typename std::iterator_traits::value_type value_type; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE typedef typename move_type::type reference; + #else + typedef value_type && reference; + #endif typedef typename std::iterator_traits::pointer pointer; typedef typename std::iterator_traits::difference_type difference_type; typedef typename std::iterator_traits::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; } diff --git a/include/boost/interprocess/detail/mpl.hpp b/include/boost/interprocess/detail/mpl.hpp new file mode 100644 index 0000000..6f05e6c --- /dev/null +++ b/include/boost/interprocess/detail/mpl.hpp @@ -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 + +namespace boost { +namespace interprocess { + +template< bool C_ > +struct bool_ +{ + static const bool value = C_; +}; + +typedef bool_ true_; +typedef bool_ false_; + +template< + bool C + , typename T1 + , typename T2 + > +struct if_c +{ + typedef T1 type; +}; + +template< + typename T1 + , typename T2 + > +struct if_c +{ + typedef T2 type; +}; + +template< + typename T1 + , typename T2 + , typename T3 + > +struct if_ +{ + typedef typename if_c<0 != T1::value, T2, T3>::type type; +}; + + +template +struct select1st + : public std::unary_function +{ + 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 +struct identity + : public std::unary_function +{ + const T& operator()(const T& x) const + { return x; } +}; + +} //namespace interprocess { +} //namespace boost { + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP + diff --git a/include/boost/interprocess/detail/named_proxy.hpp b/include/boost/interprocess/detail/named_proxy.hpp index 25debed..0797a49 100644 --- a/include/boost/interprocess/detail/named_proxy.hpp +++ b/include/boost/interprocess/detail/named_proxy.hpp @@ -19,50 +19,43 @@ #include #include -#include +#include #include #include #include #include #include -#include -#include -#include -#include +#include /*!\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 -struct Ctor0Arg +struct Ctor0Arg : public placement_destroy { typedef Ctor0Arg self_t; typedef T target_t; - enum { is_trivial = boost::has_trivial_constructor::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_ Result; - Ctor0Arg::construct(mem, Result()); + T* memory = static_cast(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 // 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_ Result; +// typedef bool_ 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(mem); +// for(constructed = 0; constructed < num; ++constructed){ +// new(memory++)T(m_p1, m_p2); +// typedef bool_ 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\ struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ + : public placement_destroy \ { \ - 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_ Result; \ + typedef bool_ 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(mem); \ + for(constructed = 0; constructed < num; ++constructed){ \ + new(memory++)T(BOOST_PP_ENUM_PARAMS(n, m_p)); \ + typedef bool_ 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 ctor_obj; - return mp_alloc->template - generic_construct(mp_name, m_num, find, dothrow, ctor_obj); + return mp_mngr->template + generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj); } /**/ @@ -212,8 +235,8 @@ class named_proxy \ ctor_obj_t; \ ctor_obj_t ctor_obj (BOOST_PP_ENUM_PARAMS(n, p)); \ - return mp_alloc->template generic_construct \ - (mp_name, m_num, find, dothrow, ctor_obj); \ + return mp_mngr->template generic_construct \ + (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 - // (mp_name, m_num, find, dothrow, ctor_obj); + // return mp_mngr->template generic_construct + // (mp_name, m_num, m_find, m_dothrow, ctor_obj); // } // ////////////////////////////////////////////////////////////////////////// diff --git a/include/boost/interprocess/detail/pointer_type.hpp b/include/boost/interprocess/detail/pointer_type.hpp new file mode 100644 index 0000000..68fc434 --- /dev/null +++ b/include/boost/interprocess/detail/pointer_type.hpp @@ -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 +#include + +namespace boost { +namespace interprocess { +namespace detail { + +struct two {char _[2];}; + +namespace pointer_type_imp { + +template static two test(...); +template static char test(typename U::pointer* = 0); + +} //namespace pointer_type_imp { + +template +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test(0)) == 1; +}; + +namespace pointer_type_imp { + +template ::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template +struct pointer_type +{ + typedef T* type; +}; + +} //namespace pointer_type_imp { + +template +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type::type>::type type; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP + diff --git a/include/boost/interprocess/detail/utilities.hpp b/include/boost/interprocess/detail/utilities.hpp index 76f8c44..6c84dbc 100644 --- a/include/boost/interprocess/detail/utilities.hpp +++ b/include/boost/interprocess/detail/utilities.hpp @@ -22,37 +22,42 @@ #include #include -#include -#include #include -#include #include -#include -#include -#include +#include +//#include #include #include -#include -#include - -namespace boost { namespace interprocess { - -template -class offset_ptr; +namespace boost { +namespace interprocess { namespace detail { -/*!Overload for smart pointers to avoid ADL problems with get_pointer*/ -template -inline typename Ptr::value_type *get_pointer(const Ptr &ptr) -{ using boost::get_pointer; return get_pointer(ptr); } +template +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 -inline T *get_pointer(T *ptr) -{ return ptr; } +struct smart_ptr_type +{ + 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 +inline typename smart_ptr_type::pointer +get_pointer(const Ptr &ptr) +{ return smart_ptr_type::get(ptr); } + +//!To avoid ADL problems with swap template 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 -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 -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 -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 -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 +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::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 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 -struct select1st - : public std::unary_function -{ - 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 -struct identity - : public std::unary_function -{ - 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 struct ct_rounded_size @@ -259,46 +277,8 @@ struct pointer_to_other< T*, U > typedef U* type; }; -//Anti-exception node eraser -template -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::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 -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 constant_iterator - : public boost::iterator_facade - < constant_iterator - , T - , boost::random_access_traversal_tag - , const T & - , Difference> -{ - typedef boost::iterator_facade - < constant_iterator - , T - , boost::random_access_traversal_tag - , const T & - , Difference> super_t; - - typedef constant_iterator 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 repeat_iterator - : public boost::iterator_facade - < repeat_iterator - , T - , boost::random_access_traversal_tag - , T & - , Difference> -{ - typedef boost::iterator_facade - < repeat_iterator - , T - , boost::random_access_traversal_tag - , T & - , Difference> super_t; - - typedef repeat_iterator 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 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 -InIt copy_n(InIt first, typename std::iterator_traits::difference_type length, OutIt dest) -{ - for (; length--; ++dest, ++first) - *dest = *first; - return first; -} - - -template inline -typename std::iterator_traits::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::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 inline -FwdIt uninitialized_copy(InIt first, InIt last, - FwdIt dest, Alloc& al) -{ - //Save initial destination position - FwdIt dest_init = dest; - typename std::iterator_traits::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 inline -InIt n_uninitialized_copy_n - (InIt first, - typename std::iterator_traits::difference_type count, - FwdIt dest, Alloc& al) -{ - //Save initial destination position - FwdIt dest_init = dest; - typename std::iterator_traits::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 -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 -InpIt2 uninitialized_copy_n_copy_n - (InpIt1 first1, - typename std::iterator_traits::difference_type n1, - InpIt2 first2, - typename std::iterator_traits::difference_type n2, - FwdIt result, - Alloc &alloc) -{ - typename std::iterator_traits::difference_type c1 = n1+1; - typename std::iterator_traits::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:: - difference_type c = (n1 - c1) + (n2 - c2); - for (; c--; ++dest_init){ - alloc.destroy(dest_init); - } - BOOST_RETHROW; - } - BOOST_CATCH_END - return first2; -} - -template -const T &max_value(const T &a, const T &b) -{ return a > b ? a : b; } - -template -const T &min_value(const T &a, const T &b) -{ return a < b ? a : b; } - template 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 static two test(...); -template static char test(typename U::pointer* = 0); - -} //namespace pointer_type_imp { - -template -struct has_pointer_type -{ - static const bool value = sizeof(pointer_type_imp::test(0)) == 1; -}; - -namespace pointer_type_imp { - -template ::value> -struct pointer_type -{ - typedef typename D::pointer type; -}; - -template -struct pointer_type -{ - typedef T* type; -}; - -} //namespace pointer_type_imp { - -template -struct pointer_type -{ - typedef typename pointer_type_imp::pointer_type::type>::type type; -}; - template struct pair { @@ -713,31 +375,67 @@ struct pair : first(p.first), second(p.second) {} + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template pair(const detail::moved_object >& p) : first(move(p.get().first)), second(move(p.get().second)) {} + #else + template + pair(std::pair && p) + : first(move(p.first)), second(move(p.second)) + {} + #endif + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template pair(const detail::moved_object >& p) : first(move(p.get().first)), second(move(p.get().second)) {} + #else + template + pair(pair && p) + : first(move(p.first)), second(move(p.second)) + {} + #endif + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template pair(const detail::moved_object &x, const detail::moved_object &y) : first(move(x.get())), second(move(y.get())) {} + #else + template + pair(U &&x, V &&y) + : first(move(x)), second(move(y)) + {} + #endif + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE pair(const detail::moved_object &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 &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 pair& operator=(const detail::moved_object > &p) { @@ -753,12 +452,27 @@ struct pair second = move(p.get().second); return *this; } + #else + template + pair& operator=(std::pair &&p) + { + first = move(p.first); + second = move(p.second); + return *this; + } + #endif + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object &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 @@ -790,6 +504,7 @@ template inline pair make_pair(T1 x, T2 y) { return pair(x, y); } +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(const detail::moved_object > &x, pair& y) { @@ -811,6 +526,15 @@ inline void swap(pair& x, pair& y) swap(x.second, y.second); } +#else +template +inline void swap(pair&&x, pair&&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 > template struct has_trivial_destructor_after_move : public boost::has_trivial_destructor -{ - enum{ value = false }; -}; +{}; enum create_enum_t { DoCreate, DoOpen, DoCreateOrOpen }; diff --git a/include/boost/interprocess/detail/win32_api.hpp b/include/boost/interprocess/detail/win32_api.hpp index 6cf3a6d..ee85b88 100644 --- a/include/boost/interprocess/detail/win32_api.hpp +++ b/include/boost/interprocess/detail/win32_api.hpp @@ -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 diff --git a/include/boost/interprocess/detail/workaround.hpp b/include/boost/interprocess/detail/workaround.hpp index 3f8ec6d..b50d5f9 100644 --- a/include/boost/interprocess/detail/workaround.hpp +++ b/include/boost/interprocess/detail/workaround.hpp @@ -18,19 +18,6 @@ #include #include -#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 -#else -# include -#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// diff --git a/include/boost/interprocess/file_mapping.hpp b/include/boost/interprocess/file_mapping.hpp index 3a7b914..d1a4085 100644 --- a/include/boost/interprocess/file_mapping.hpp +++ b/include/boost/interprocess/file_mapping.hpp @@ -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 &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 &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); diff --git a/include/boost/interprocess/indexes/flat_map_index.hpp b/include/boost/interprocess/indexes/flat_map_index.hpp index 5b1bf0b..84ed397 100644 --- a/include/boost/interprocess/indexes/flat_map_index.hpp +++ b/include/boost/interprocess/indexes/flat_map_index.hpp @@ -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_less; typedef std::pair value_type; typedef allocator allocator_type; + ,basic_segment_manager> allocator_type; typedef flat_map index_t; }; @@ -53,12 +53,12 @@ class flat_map_index typedef flat_map_index_aux 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)) {} diff --git a/include/boost/interprocess/indexes/iset_index.hpp b/include/boost/interprocess/indexes/iset_index.hpp index 7f6acc7..ff1c1a4 100644 --- a/include/boost/interprocess/indexes/iset_index.hpp +++ b/include/boost/interprocess/indexes/iset_index.hpp @@ -34,10 +34,10 @@ template 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::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::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()*/) {} diff --git a/include/boost/interprocess/indexes/iunordered_set_index.hpp b/include/boost/interprocess/indexes/iunordered_set_index.hpp index 744b982..b74d8d0 100644 --- a/include/boost/interprocess/indexes/iunordered_set_index.hpp +++ b/include/boost/interprocess/indexes/iunordered_set_index.hpp @@ -35,10 +35,10 @@ template 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::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::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::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 - allocator_type; + 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::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 diff --git a/include/boost/interprocess/indexes/map_index.hpp b/include/boost/interprocess/indexes/map_index.hpp index c26b3b0..3f00c18 100644 --- a/include/boost/interprocess/indexes/map_index.hpp +++ b/include/boost/interprocess/indexes/map_index.hpp @@ -38,7 +38,7 @@ struct map_index_aux typedef private_adaptive_pool allocator_type; + basic_segment_manager> allocator_type; typedef boost::interprocess::map 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){} diff --git a/include/boost/interprocess/indexes/null_index.hpp b/include/boost/interprocess/indexes/null_index.hpp index acd0e9f..43165ce 100644 --- a/include/boost/interprocess/indexes/null_index.hpp +++ b/include/boost/interprocess/indexes/null_index.hpp @@ -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 { diff --git a/include/boost/interprocess/indexes/unordered_map_index.hpp b/include/boost/interprocess/indexes/unordered_map_index.hpp index 204eb24..9561775 100644 --- a/include/boost/interprocess/indexes/unordered_map_index.hpp +++ b/include/boost/interprocess/indexes/unordered_map_index.hpp @@ -38,7 +38,7 @@ struct unordered_map_index_aux typedef private_adaptive_pool allocator_type; + basic_segment_manager> allocator_type; struct hasher : std::unary_function { @@ -65,13 +65,13 @@ class unordered_map_index typedef unordered_map_index_aux 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(), diff --git a/include/boost/interprocess/ipc/message_queue.hpp b/include/boost/interprocess/ipc/message_queue.hpp index 7016a88..3229ada 100644 --- a/include/boost/interprocess/ipc/message_queue.hpp +++ b/include/boost/interprocess/ipc/message_queue.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include //std::lower_bound diff --git a/include/boost/interprocess/managed_external_buffer.hpp b/include/boost/interprocess/managed_external_buffer.hpp index b2f75e7..6c9c819 100644 --- a/include/boost/interprocess/managed_external_buffer.hpp +++ b/include/boost/interprocess/managed_external_buffer.hpp @@ -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 &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 &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); } diff --git a/include/boost/interprocess/managed_heap_memory.hpp b/include/boost/interprocess/managed_heap_memory.hpp index 1337f53..f313909 100644 --- a/include/boost/interprocess/managed_heap_memory.hpp +++ b/include/boost/interprocess/managed_heap_memory.hpp @@ -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 &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 &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 diff --git a/include/boost/interprocess/managed_mapped_file.hpp b/include/boost/interprocess/managed_mapped_file.hpp index 1427835..4c6fb07 100644 --- a/include/boost/interprocess/managed_mapped_file.hpp +++ b/include/boost/interprocess/managed_mapped_file.hpp @@ -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 &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 &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() diff --git a/include/boost/interprocess/managed_shared_memory.hpp b/include/boost/interprocess/managed_shared_memory.hpp index 97c108e..70e32d9 100644 --- a/include/boost/interprocess/managed_shared_memory.hpp +++ b/include/boost/interprocess/managed_shared_memory.hpp @@ -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 &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 &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. diff --git a/include/boost/interprocess/managed_windows_shared_memory.hpp b/include/boost/interprocess/managed_windows_shared_memory.hpp index 15f2a14..9ba4b26 100644 --- a/include/boost/interprocess/managed_windows_shared_memory.hpp +++ b/include/boost/interprocess/managed_windows_shared_memory.hpp @@ -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 &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 &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() diff --git a/include/boost/interprocess/mapped_region.hpp b/include/boost/interprocess/mapped_region.hpp index 30e27b6..de43d8d 100644 --- a/include/boost/interprocess/mapped_region.hpp +++ b/include/boost/interprocess/mapped_region.hpp @@ -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 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 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 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 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 inline std::size_t mapped_region::page_size_holder::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 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 inline std::size_t mapped_region::page_size_holder::get_page_size() diff --git a/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp index dae41f3..f43d340 100644 --- a/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp +++ b/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -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 allocation_command (allocation_type command, std::size_t limit_size, @@ -288,6 +292,13 @@ template inline std::size_t simple_seq_fit_impl::get_size() const { return m_header.m_size; } +template +inline std::size_t simple_seq_fit_impl::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 inline std::size_t simple_seq_fit_impl:: get_min_size (std::size_t extra_hdr_bytes) @@ -309,7 +320,7 @@ inline bool simple_seq_fit_impl:: } template -inline void simple_seq_fit_impl::clear_free_memory() +inline void simple_seq_fit_impl::zero_free_memory() { //----------------------- boost::interprocess::scoped_lock guard(m_header); @@ -448,7 +459,6 @@ void* simple_seq_fit_impl:: 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)); } diff --git a/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp index 947b908..e71c4df 100644 --- a/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp +++ b/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -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 inline std::size_t rbtree_best_fit::get_size() const { return m_header.m_size; } +template +inline std::size_t rbtree_best_fit::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 inline std::size_t rbtree_best_fit:: get_min_size (std::size_t extra_hdr_bytes) @@ -510,7 +521,7 @@ inline std::size_t rbtree_best_fit:: } template -inline void rbtree_best_fit::clear_free_memory() +inline void rbtree_best_fit::zero_free_memory() { //----------------------- boost::interprocess::scoped_lock guard(m_header); @@ -1182,7 +1193,7 @@ void* rbtree_best_fit::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(block); std::memset(t, 0, sizeof(*t)); return priv_get_user_buffer(block); diff --git a/include/boost/interprocess/offset_ptr.hpp b/include/boost/interprocess/offset_ptr.hpp index 6172ed5..d007104 100644 --- a/include/boost/interprocess/offset_ptr.hpp +++ b/include/boost/interprocess/offset_ptr.hpp @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include /*!\file Describes a smart pointer that stores the offset between this pointer and @@ -33,6 +30,13 @@ */ namespace boost { +//Predeclarations +template +struct has_trivial_constructor; + +template +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 /// @cond //!has_trivial_constructor<> == true_type specialization for optimizations template -struct has_trivial_constructor - < boost::interprocess::offset_ptr > +struct has_trivial_constructor< boost::interprocess::offset_ptr > : public true_type {}; ///has_trivial_destructor<> == true_type specialization for optimizations template -struct has_trivial_destructor - < boost::interprocess::offset_ptr > +struct has_trivial_destructor< boost::interprocess::offset_ptr > : public true_type {}; @@ -380,13 +382,13 @@ class cast_to< offset_ptr > namespace intrusive { //Predeclaration to avoid including header -template +template struct has_pointer_plus_bit; -template -struct has_pointer_plus_bit > +template +struct has_pointer_plus_bit, N> { - enum { value = (boost::alignment_of::value % 4u) == 0 }; + enum { value = (N % 4u) == 0 }; }; //Predeclaration diff --git a/include/boost/interprocess/segment_manager.hpp b/include/boost/interprocess/segment_manager.hpp index 09dc96b..89a9a08 100644 --- a/include/boost/interprocess/segment_manager.hpp +++ b/include/boost/interprocess/segment_manager.hpp @@ -8,8 +8,8 @@ // ////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTERPROCESS_NAMED_OBJECT_ALGO_HPP -#define BOOST_INTERPROCESS_NAMED_OBJECT_ALGO_HPP +#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP +#define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP #if (defined _MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -19,28 +19,20 @@ #include #include -#include -#include -#include -#include #include -#include -#include +#include + +#include +#include #include #include #include #include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include //std::size_t +#include //char_traits +#include //std::nothrow +#include //std::pair #ifndef BOOST_NO_EXCEPTIONS #include #endif @@ -51,11 +43,27 @@ multi-segment allocations. */ -namespace boost{ namespace interprocess { +namespace boost{ +namespace interprocess{ +namespace detail{ -/// @cond -/*!An integer that describes the type of the instance constructed in memory*/ -enum InstanceType { anonymous_type, named_type, unique_type, max_allocation_type }; +//Anti-exception node eraser +template +class value_eraser +{ + public: + value_eraser(Cont & cont, typename Cont::iterator it) + : m_cont(cont), m_index_it(it), m_erase(true){} + ~value_eraser() + { if(m_erase) m_cont.erase(m_index_it); } + + void release() { m_erase = false; } + + private: + Cont &m_cont; + typename Cont::iterator m_index_it; + bool m_erase; +}; template struct intrusive_compare_key @@ -70,233 +78,43 @@ struct intrusive_compare_key std::size_t m_len; }; -namespace detail{ - -struct empty{}; - -/*! - This struct indicates an anonymous object creation allocation -*/ -class anonymous_instance_t +//!This struct indicates an anonymous object creation +//!allocation +template +class instance_t { - private: - anonymous_instance_t(){} + instance_t(){} }; -/*! - This struct indicates an unique type indexed instance allocation -*/ -class unique_instance_t +template +struct char_if_void { - private: - unique_instance_t(){} + typedef T type; }; -} //namespace detail{ -/// @endcond - -//These pointers are the ones the user will use to -//indicate previous allocation types -static const detail::anonymous_instance_t *anonymous_instance; -static const detail::unique_instance_t *unique_instance; - -}} //namespace boost{ namespace interprocess{ - -namespace boost { namespace interprocess { namespace detail { - -/// @cond -/*!The key of the the named allocation information index. Stores an offset pointer - to a null terminated string and the length of the string to speed up sorting*/ -template -struct index_key +template<> +struct char_if_void { - typedef typename detail:: - pointer_to_other::type const_char_ptr_t; - typedef CharT char_type; - - private: - //Offset pointer to the object's name - const_char_ptr_t mp_str; - //Length of the name buffer (null NOT included) - std::size_t m_len; - public: - - /*!Constructor of the key*/ - index_key (const char_type *name, std::size_t length) - : mp_str(name), m_len(length) {} - - /*!Less than function for index ordering*/ - bool operator < (const index_key & right) const - { - return (m_len < right.m_len) || - (m_len == right.m_len && - std::char_traits::compare - (detail::get_pointer(mp_str) - ,detail::get_pointer(right.mp_str), m_len) < 0); - } - - /*!Equal to function for index ordering*/ - bool operator == (const index_key & right) const - { - return m_len == right.m_len && - std::char_traits::compare - (detail::get_pointer(mp_str), - detail::get_pointer(right.mp_str), m_len) == 0; - } - - void name(const CharT *name) - { mp_str = name; } - - void length(std::size_t len) - { m_len = len; } - - const CharT *name() const - { return detail::get_pointer(mp_str); } - - std::size_t length() const - { return m_len; } + typedef char type; }; -/*!The index_data stores a pointer to a buffer and the element count needed - to know how many destructors must be called when calling destroy*/ -template -struct index_data -{ - typedef VoidPointer void_ptr; - void_ptr m_ptr; - index_data(void *ptr) : m_ptr(ptr){} -}; - -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 - block_header &operator= (const T& ) - { return *this; } - - std::size_t total_size() const - { - if(allocation_type() != anonymous_type){ - return name_offset() + (m_num_char+1)*sizeof_char(); - } - else{ - return value_offset() + m_value_bytes; - } - } - - template - std::size_t total_size_with_header() const - { - return get_rounded_size - ( sizeof(Header) - , boost::alignment_of::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 - CharType *name() const - { - return reinterpret_cast - (detail::char_ptr_cast(this) + name_offset()); - } - - std::size_t 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 - 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::compare - (name(), b.name(), m_num_char) < 0); - } - - template - bool equal(const block_header &b) const - { - return m_num_char == b.m_num_char && - std::char_traits::compare - (name(), b.name(), m_num_char) == 0; - } - - template - static block_header *block_header_from_value(T *value) - { - block_header * hdr = - reinterpret_cast(detail::char_ptr_cast(value) - - get_rounded_size(sizeof(block_header), boost::alignment_of::value)); - //Some sanity checks - assert(hdr->m_value_alignment == boost::alignment_of::value); - assert(hdr->m_value_bytes % sizeof(T) == 0); - return hdr; - } - - template - static block_header *from_first_header(Header *header) - { - block_header * hdr = - reinterpret_cast(detail::char_ptr_cast(header) + - get_rounded_size(sizeof(Header), boost::alignment_of::value)); - //Some sanity checks - return hdr; - } - - template - static Header *to_first_header(block_header *bheader) - { - Header * hdr = - reinterpret_cast(detail::char_ptr_cast(bheader) - - get_rounded_size(sizeof(Header), boost::alignment_of::value)); - //Some sanity checks - return hdr; - } -}; +typedef instance_t anonymous_instance_t; +typedef instance_t unique_instance_t; template struct intrusive_value_type_impl : public Hook { + private: + //Non-copyable + intrusive_value_type_impl(const intrusive_value_type_impl &); + intrusive_value_type_impl& operator=(const intrusive_value_type_impl &); + + public: + typedef CharType char_type; + + intrusive_value_type_impl(){} + enum { BlockHdrAlignment = boost::alignment_of::value }; block_header *get_block_header() const @@ -320,32 +138,11 @@ struct intrusive_value_type_impl CharType *name() const { return get_block_header()->template name(); } - std::size_t length() const - { return get_block_header()->length(); } -}; + std::size_t name_length() const + { return get_block_header()->name_length(); } -template -struct get_construct_name; - -template -struct get_construct_name -{ - static const OutPtr *get(const OutPtr *name) - { return name; } -}; - -template -struct get_construct_name -{ - static const OutPtr *get(const anonymous_instance_t *) - { return reinterpret_cast(0); } -}; - -template -struct get_construct_name -{ - static const OutPtr *get(const unique_instance_t *) - { return reinterpret_cast(-1); } + void *value() const + { return get_block_header()->value(); } }; template @@ -353,15 +150,15 @@ class char_ptr_holder { public: char_ptr_holder(const CharType *name) - : m_name(detail::get_construct_name::get(name)) + : m_name(name) {} - char_ptr_holder(const detail::anonymous_instance_t *name) - : m_name(detail::get_construct_name::get(name)) + char_ptr_holder(const detail::anonymous_instance_t *) + : m_name((CharType*)0) {} - char_ptr_holder(const detail::unique_instance_t *name) - : m_name(detail::get_construct_name::get(name)) + char_ptr_holder(const detail::unique_instance_t *) + : m_name((CharType*)-1) {} operator const CharType *() @@ -371,264 +168,74 @@ class char_ptr_holder const CharType *m_name; }; -} //namespace detail { - - -template -class restricted_segment_manager - : private MemoryAlgorithm +//!The key of the the named allocation information index. Stores an offset pointer +//!to a null terminated string and the length of the string to speed up sorting +template +struct index_key { - //typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex; + typedef typename detail:: + pointer_to_other::type const_char_ptr_t; + typedef CharT char_type; + + private: + //Offset pointer to the object's name + const_char_ptr_t mp_str; + //Length of the name buffer (null NOT included) + std::size_t m_len; public: - struct raw_deleter_t + + //!Constructor of the key + index_key (const char_type *name, std::size_t length) + : mp_str(name), m_len(length) {} + + //!Less than function for index ordering + bool operator < (const index_key & right) const { - typedef void * pointer; + return (m_len < right.m_len) || + (m_len == right.m_len && + std::char_traits::compare + (detail::get_pointer(mp_str) + ,detail::get_pointer(right.mp_str), m_len) < 0); + } - raw_deleter_t(restricted_segment_manager &mngr) - : m_mngr(mngr) - {} - - void operator()(pointer p) - { m_mngr.deallocate(p); } - - private: - restricted_segment_manager &m_mngr; - }; - - public: - typedef typename MemoryAlgorithm::void_pointer void_pointer; - typedef typename MemoryAlgorithm::mutex_family mutex_family; - - enum { PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation }; - - restricted_segment_manager(std::size_t size, std::size_t reserved_bytes) - : MemoryAlgorithm(size, reserved_bytes) + //!Equal to function for index ordering + bool operator == (const index_key & right) const { - assert((sizeof(restricted_segment_manager) == sizeof(MemoryAlgorithm))); + return m_len == right.m_len && + std::char_traits::compare + (detail::get_pointer(mp_str), + detail::get_pointer(right.mp_str), m_len) == 0; } - /*!Returns the size of the memory segment*/ - std::size_t get_size() const - { return MemoryAlgorithm::get_size(); } + void name(const CharT *name) + { mp_str = name; } - /*!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); } + void name_length(std::size_t len) + { m_len = len; } - /*!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); } + const CharT *name() const + { return detail::get_pointer(mp_str); } - /*!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 - 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 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 clear_free_memory() - { MemoryAlgorithm::clear_free_memory(); } - - /// @cond - /*!Generic anonymous "new" function.*/ - template - T * anonymous_construct(std::size_t num, - bool dothrow, - CtorFunc &ctor) - { - typedef detail::block_header block_header_t; - block_header_t block_info ( sizeof(T)*num - , boost::alignment_of::value - , anonymous_type - , 1 - , 0); - - //------------------------------- - //boost::interprocess::scoped_lock guard(m_header); - //------------------------------- - - //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 - boost::interprocess::scoped_ptr mem(ptr_struct, *this); - - //Now construct the header - block_header_t * hdr = new(ptr_struct) block_header_t(block_info); - T *ptr = static_cast(hdr->value()); - - if(!CtorFunc::is_trivial){ - //Construct array, this can throw - this->template array_construct(ptr, num, ctor); - } - - //All constructors successful, we don't want erase memory - mem.release(); - return ptr; - } - - /*!Calls the destructor and makes an anonymous deallocate*/ - template - bool anonymous_destroy(const T *object) - { - 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); - - //------------------------------- - //boost::interprocess::scoped_lock guard(m_header); - //------------------------------- - - if(ctrl_data->allocation_type() != anonymous_type){ - //This is not an anonymous object, the pointer is wrong! - assert(0); - return false; - } - - //Call destructors and free memory - this->array_destroy - (ctrl_data, object, ctrl_data->m_value_bytes/sizeof(T)); - return true; - } - - template - void array_destroy(const void * memory, T *objects, std::size_t count) - { - //Build scoped ptr to avoid leaks with destructor exception - boost::interprocess::scoped_ptr mem((void*)memory, *this); - - if(boost::has_trivial_destructor::value) - return; - - //Call destructors in reverse order, if one throws catch it and - //continue destroying ignoring further exceptions. - if(!boost::has_nothrow_destructor::value){ - while(count--){ - objects[count].~T(); - } - } - else{ - BOOST_TRY { - while(count--){ - objects[count].~T(); - } - } - BOOST_CATCH(...){ - //Destroy the rest of objects ignoring exceptions - while(count--){ - BOOST_TRY { objects[count].~T(); } - //Ignore exceptions - BOOST_CATCH(...) { } - BOOST_CATCH_END - } - //throws first exception - BOOST_RETHROW - } - BOOST_CATCH_END - } - } - - template - void array_construct(typename Ctor::target_t *ptr, - std::size_t num, Ctor &ctor) - { - typedef typename Ctor::target_t target_t; - //Try constructors - std::size_t counter = 0; - BOOST_TRY{ - for(; counter < num; ++counter, ++ctor){ - ctor(&ptr[counter]); - } - } - //If there is an exception call destructors and erase index node - BOOST_CATCH(...){ - if(!boost::has_trivial_destructor::value){ - for(; counter; --counter){ - BOOST_TRY { ptr[counter].~target_t(); } - //Ignore exceptions, we will throw the original - //exception to free acquired locks - BOOST_CATCH(...) {} - BOOST_CATCH_END - } - } - BOOST_RETHROW; - } - BOOST_CATCH_END - } + std::size_t name_length() const + { return m_len; } }; -/// @endcond -namespace detail{ +//!The index_data stores a pointer to a buffer and the element count needed +//!to know how many destructors must be called when calling destroy +template +struct index_data +{ + typedef VoidPointer void_ptr; + void_ptr m_ptr; + index_data(void *ptr) : m_ptr(ptr){} + + void *value() const + { return (void*)detail::get_pointer(m_ptr); } +}; template -struct restricted_segment_manager_type -{ typedef restricted_segment_manager type; }; +struct basic_segment_manager_type +{ typedef basic_segment_manager type; }; template struct index_config @@ -637,8 +244,8 @@ struct index_config typedef CharT char_type; typedef detail::index_key key_type; typedef detail::index_data mapped_type; - typedef typename restricted_segment_manager_type - ::type restricted_segment_manager; + typedef typename basic_segment_manager_type + ::type basic_segment_manager; template struct intrusive_value_type @@ -647,38 +254,107 @@ struct index_config typedef intrusive_compare_key intrusive_compare_key_type; }; +template +class iterator_value_adaptor +{ + typedef typename Iterator::value_type iterator_val_t; + typedef typename iterator_val_t::char_type char_type; + + public: + iterator_value_adaptor(const typename Iterator::value_type &val) + : m_val(&val) + {} + + const char_type *name() const + { return m_val->name(); } + + std::size_t name_length() const + { return m_val->name_length(); } + + const void *value() const + { return m_val->value(); } + + const typename Iterator::value_type *m_val; +}; + + +template +class iterator_value_adaptor +{ + typedef typename Iterator::value_type iterator_val_t; + typedef typename iterator_val_t::first_type first_type; + typedef typename iterator_val_t::second_type second_type; + typedef typename first_type::char_type char_type; + + public: + iterator_value_adaptor(const typename Iterator::value_type &val) + : m_val(&val) + {} + + const char_type *name() const + { return m_val->first.name(); } + + std::size_t name_length() const + { return m_val->first.name_length(); } + + const void *value() const + { + return reinterpret_cast + (detail::get_pointer(m_val->second.m_ptr))->value(); + } + + const typename Iterator::value_type *m_val; +}; + +template +struct iterator_transform + : std::unary_function< typename Iterator::value_type + , iterator_value_adaptor > +{ + typedef iterator_value_adaptor result_type; + + result_type operator()(const typename Iterator::value_type &arg) const + { return result_type(arg); } +}; + } //namespace detail{ -/*! - This object is placed in the beginning of memory segment and - implements the allocation (named or anonymous) of portions - of the segment. This object contains two indexes that - maintain an association between a name and a portion of the segment. - - The first index contains the mappings for normal named objects using the - char type specified in the template parameter. +/// @endcond - The second index contains the association for unique instances. The key will - be the const char * returned from type_info.name() function for the unique - type to be constructed. -*/ +//These pointers are the ones the user will use to +//indicate previous allocation types +static const detail::anonymous_instance_t * anonymous_instance = 0; +static const detail::unique_instance_t * unique_instance = 0; + +//!This object is placed in the beginning of memory segment and +//!implements the allocation (named or anonymous) of portions +//!of the segment. This object contains two indexes that +//!maintain an association between a name and a portion of the segment. +//! +//!The first index contains the mappings for normal named objects using the +//!char type specified in the template parameter. +//! +//!The second index contains the association for unique instances. The key will +//!be the const char * returned from type_info.name() function for the unique +//!type to be constructed. template class IndexType> class segment_manager - : private restricted_segment_manager + : private detail::basic_segment_manager { /// @cond //Non-copyable segment_manager(); segment_manager(const segment_manager &); segment_manager &operator=(const segment_manager &); - typedef restricted_segment_manager Base; - typedef typename Base::raw_deleter_t raw_deleter_t; + typedef detail::basic_segment_manager Base; + typedef detail::block_header block_header_t; /// @endcond public: typedef typename Base::void_pointer void_pointer; + typedef CharType char_type; enum { PayloadPerAllocation = Base::PayloadPerAllocation }; @@ -687,187 +363,181 @@ class segment_manager typedef detail::index_config index_config_named; typedef detail::index_config index_config_unique; typedef IndexType index_type; - typedef boost::mpl::bool_::value > is_intrusive_t; - typedef boost::mpl::bool_::value> is_node_index_t; + typedef bool_::value > is_intrusive_t; + typedef bool_::value> is_node_index_t; public: typedef IndexType named_index_t; typedef IndexType unique_index_t; typedef detail::char_ptr_holder char_ptr_holder_t; + typedef detail::iterator_transform + ::value> named_transform; + + typedef detail::iterator_transform + ::value> unique_transform; /// @endcond - typedef typename Base::mutex_family mutex_family; + typedef typename Base::mutex_family mutex_family; - /*!Constructor proxy object definition helper class*/ - template + + typedef boost::transform_iterator + const_named_iterator; + typedef boost::transform_iterator + const_unique_iterator; +/* + typedef typename + named_index_t::const_iterator const_named_iterator; + typedef typename + unique_index_t::const_iterator const_unique_iterator; +*/ + //!Constructor proxy object definition helper class + template struct construct_proxy { - typedef detail::named_proxy type; + typedef detail::named_proxy type; }; - /*!Find or construct proxy object definition helper class*/ - template - struct find_construct_proxy - { - typedef detail::named_proxy type; - }; - - /*!Constructor proxy object definition helper class*/ - template + //!Constructor proxy object definition helper class + template struct construct_iter_proxy { - typedef detail::named_proxy type; + typedef detail::named_proxy type; }; - /*!Find or construct proxy object definition helper class*/ - template - struct find_construct_iter_proxy - { - typedef detail::named_proxy type; - }; - - /*!Constructor. Can throw*/ + //!Constructor. Can throw segment_manager(std::size_t size) : Base(size, priv_get_reserved_bytes()) , m_header(static_cast(get_this_pointer())) { (void) anonymous_instance; (void) unique_instance; } - /*!Tries to find a previous named allocation address. Returns a memory - buffer and the object count. */ + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. template std::pair find (const CharType* name) { //The name can't be null, no anonymous object can be found by name assert(name != 0); + detail::placement_destroy table; + std::size_t size; + void *ret; + if(name == reinterpret_cast(-1)){ - return priv_generic_find (typeid(T).name(), m_header.m_unique_index, is_intrusive_t()); + ret = priv_generic_find (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t()); } else{ - return priv_generic_find (name, m_header.m_named_index, is_intrusive_t()); + ret = priv_generic_find (name, m_header.m_named_index, table, size, is_intrusive_t()); } + return std::pair(static_cast(ret), size); } template std::pair find (const detail::unique_instance_t* name) - { return priv_generic_find (name, m_header.m_unique_index, is_intrusive_t()); } + { + detail::placement_destroy table; + std::size_t size; + void *ret = priv_generic_find(name, m_header.m_unique_index, table, size, is_intrusive_t()); + return std::pair(static_cast(ret), size); + } - /*!Returns throwing "construct" proxy object*/ + //!Returns throwing "construct" proxy + //!object template - typename construct_proxy::type + typename construct_proxy::type construct(char_ptr_holder_t name) - { return typename construct_proxy::type (name, this); } + { return typename construct_proxy::type (this, name, false, true); } - /*!Returns throwing "search or construct" proxy object*/ + //!Returns throwing "search or construct" proxy + //!object template - typename find_construct_proxy::type find_or_construct(char_ptr_holder_t name) - { return typename find_construct_proxy::type(name, this); } + typename construct_proxy::type find_or_construct(char_ptr_holder_t name) + { return typename construct_proxy::type (this, name, true, true); } - /*!Returns no throwing "construct" proxy object*/ + //!Returns no throwing "construct" proxy + //!object template - typename construct_proxy::type + typename construct_proxy::type construct(char_ptr_holder_t name, std::nothrow_t) - { return typename construct_proxy::type (name, this); } + { return typename construct_proxy::type (this, name, false, false); } - /*!Returns no throwing "search or construct" proxy object*/ + //!Returns no throwing "search or construct" + //!proxy object template - typename find_construct_proxy::type + typename construct_proxy::type find_or_construct(char_ptr_holder_t name, std::nothrow_t) - { return typename find_construct_proxy::type (name, this); } + { return typename construct_proxy::type (this, name, true, false); } - /*!Returns throwing "construct from iterators" proxy object*/ + //!Returns throwing "construct from iterators" proxy object template - typename construct_iter_proxy::type + typename construct_iter_proxy::type construct_it(char_ptr_holder_t name) - { return typename construct_iter_proxy::type (name, this); } + { return construct_iter_proxy::type (this, name, false, true); } - /*!Returns throwing "search or construct from iterators" proxy object*/ + //!Returns throwing "search or construct from iterators" + //!proxy object template - typename find_construct_iter_proxy::type + typename construct_iter_proxy::type find_or_construct_it(char_ptr_holder_t name) - { return typename find_construct_iter_proxy::type(name, this); } + { return typename construct_iter_proxy::type (this, name, true, true); } - /*!Returns no throwing "construct from iterators" proxy object*/ + //!Returns no throwing "construct from iterators" + //!proxy object template - typename construct_iter_proxy::type + typename construct_iter_proxy::type construct_it(char_ptr_holder_t name, std::nothrow_t) - { return typename construct_iter_proxy::type (name, this); } + { return typename construct_iter_proxy::type (this, name, false, false); } - /*!Returns no throwing "search or construct from iterators" proxy object*/ + //!Returns no throwing "search or construct from iterators" + //!proxy object template - typename find_construct_iter_proxy::type + typename construct_iter_proxy::type find_or_construct_it(char_ptr_holder_t name, std::nothrow_t) - { return typename find_construct_iter_proxy::type (name, this); } + { return typename construct_iter_proxy::type (this, name, true, false); } - /*!Calls object function blocking recursive interprocess_mutex and guarantees that - no new named_alloc or destroy will be executed by any process while - executing the object function call*/ + //!Calls object function blocking recursive interprocess_mutex and guarantees that + //!no new named_alloc or destroy will be executed by any process while + //!executing the object function call*/ template void atomic_func(Func &f) { boost::interprocess::scoped_lock guard(m_header); f(); } - /*!Calls the destructor and makes an unique deallocate*/ + //!Calls the destructor and makes an unique + //!deallocate template bool destroy(const detail::unique_instance_t *) { - return this->priv_generic_named_destroy - (typeid(T).name(), m_header.m_unique_index, is_intrusive_t()); + detail::placement_destroy dtor; + return this->priv_generic_named_destroy + (typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t()); } template bool destroy(const CharType *name) { - return this->priv_generic_named_destroy - (name, m_header.m_named_index, is_intrusive_t()); + detail::placement_destroy dtor; + return this->priv_generic_named_destroy + (name, m_header.m_named_index, dtor, is_intrusive_t()); } template bool destroy_ptr(const T *p) { - //Allow void pointer deletion instantiation to be able to - //construct void shared_ptrs - //If we call the destroy_ptr(const void *), the function will return 0 - typedef typename boost::mpl::if_c::value, - char, T>::type data_t; - const data_t *ptr = (const data_t*)p; - - //TO-DO: Although we now that the block_header_temp is equal for both indexes - //we should find a cleaner way to do this. - detail::block_header *ctrl_data = detail::block_header::block_header_from_value(ptr); - switch(ctrl_data->allocation_type()){ - case anonymous_type: - return this->template anonymous_destroy(ptr); - break; - - case named_type: - return this->priv_generic_named_destroy - (ctrl_data, m_header.m_named_index, is_node_index_t()); - break; - - case unique_type: - return this->priv_generic_named_destroy - (ctrl_data, m_header.m_unique_index, is_node_index_t()); - break; - - default: - //This type is unknown, bad pointer passed to this function! - assert(0); - return false; - break; - } - return false; + //If T is void transform it to char + typedef typename detail::char_if_void::type data_t; + detail::placement_destroy dtor; + return priv_destroy_ptr(p, dtor); } - /*!Returns the name of an object created with construct/find_or_construct - functions. Does not throw*/ + //!Returns the name of an object created with construct/find_or_construct + //!functions. Does not throw template const CharType *get_name(const T *ptr) { //Get header - detail::block_header *ctrl_data = detail::block_header::block_header_from_value(ptr); + block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr); CharType *name = static_cast(ctrl_data->template name()); //Sanity checks @@ -877,20 +547,20 @@ class segment_manager return name; } - /*!Returns is the the name of an object created with construct/find_or_construct - functions. Does not throw*/ + //!Returns is the the name of an object created with construct/find_or_construct + //!functions. Does not throw template - InstanceType get_type(const T *ptr) + detail::instance_type get_type(const T *ptr) { //Get header - detail::block_header *ctrl_data = detail::block_header::block_header_from_value(ptr); - assert((InstanceType)ctrl_data->allocation_type() < max_allocation_type); - return (InstanceType)ctrl_data->allocation_type(); + block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr); + assert((detail::instance_type)ctrl_data->allocation_type() < detail::max_allocation_type); + return (detail::instance_type)ctrl_data->allocation_type(); } - /*!Preallocates needed index resources to optimize the - creation of "num" named objects in the managed memory segment. - Can throw boost::interprocess::bad_alloc if there is no enough memory.*/ + //!Preallocates needed index resources to optimize the + //!creation of "num" named objects in the managed memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_named_objects(std::size_t num) { //------------------------------- @@ -899,9 +569,9 @@ class segment_manager m_header.m_named_index.reserve(num); } - /*!Preallocates needed index resources to optimize the - creation of "num" unique objects in the managed memory segment. - Can throw boost::interprocess::bad_alloc if there is no enough memory.*/ + //!Preallocates needed index resources to optimize the + //!creation of "num" unique objects in the managed memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_unique_objects(std::size_t num) { //------------------------------- @@ -910,7 +580,8 @@ class segment_manager m_header.m_unique_index.reserve(num); } - /*!Returns the number of named objects stored in the segment.*/ + //!Returns the number of named objects stored in + //!the segment. std::size_t get_num_named_objects() { //------------------------------- @@ -919,7 +590,8 @@ class segment_manager return m_header.m_named_index.size(); } - /*!Returns the number of unique objects stored in the segment.*/ + //!Returns the number of unique objects stored in + //!the segment. std::size_t get_num_unique_objects() { //------------------------------- @@ -928,31 +600,38 @@ class segment_manager return m_header.m_unique_index.size(); } - /*!Returns the size of the memory segment*/ + //!Returns the size of the memory + //!segment std::size_t get_size() const { return Base::get_size(); } - /*!Obtains the minimum size needed by the segment manager*/ + //!Returns the number of free bytes of the memory + //!segment + std::size_t get_free_memory() const + { return Base::get_free_memory(); } + + //!Obtains the minimum size needed by the + //!segment manager static std::size_t get_min_size() { return Base::get_min_size(priv_get_reserved_bytes()); } - /*!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc when - it can allocate*/ + //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc + //!when it can allocate void * allocate(std::size_t nbytes) { return Base::allocate(nbytes); } - /*!Allocates nbytes bytes. This function is only used in - single-segment management. Never throws*/ + //!Allocates nbytes bytes. This function is only used in + //!single-segment management. Never throws void * allocate (std::size_t nbytes, std::nothrow_t nothrow) { return Base::allocate(nbytes, nothrow); } - /*!Allocates aligned bytes, returns 0 if there is not more memory. - Alignment must be power of 2*/ + //!Allocates aligned bytes, returns 0 if there is not more memory. + //!Alignment must be power of 2 void* allocate_aligned (std::size_t nbytes, std::size_t alignment) { return Base::allocate_aligned(nbytes, alignment); } - /*!Allocates aligned bytes, throws bad_alloc when - it can allocate. Alignment must be power of 2*/ + //!Allocates aligned bytes, throws bad_alloc when + //!it can allocate. Alignment must be power of 2 void* allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t nothrow) { return Base::allocate_aligned(nbytes, alignment, nothrow); } @@ -965,86 +644,126 @@ class segment_manager (command, limit_size, preferred_size, received_size, reuse_ptr, backwards_multiple); } - /*!Deallocates the bytes allocated with allocate/allocate_at_least() - pointed by addr*/ + //!Deallocates the bytes allocated with allocate/allocate_at_least() + //!pointed by addr void deallocate (void *addr) { Base::deallocate(addr); } - /*!Increases managed memory in extra_size bytes more. This only works - with single-segment management*/ + //!Increases managed memory in extra_size bytes more. This only works + //!with single-segment management void grow(std::size_t extra_size) { Base::grow(extra_size); } - /*!Returns the result of "all_memory_deallocated()" function - of the used memory algorithm*/ + //!Returns the result of "all_memory_deallocated()" function + //!of the used memory algorithm bool all_memory_deallocated() { return Base::all_memory_deallocated(); } - /*!Returns the result of "check_sanity()" function - of the used memory algorithm*/ + //!Returns the result of "check_sanity()" function + //!of the used memory algorithm bool check_sanity() { return Base::check_sanity(); } - //!Writes to zero free memory (memory not yet allocated) of the memory algorithm - void clear_free_memory() - { Base::clear_free_memory(); } + //!Writes to zero free memory (memory not yet allocated) of + //!the memory algorithm + void zero_free_memory() + { Base::zero_free_memory(); } - typename named_index_t::iterator named_begin() - { return m_header.m_named_index.begin(); } + const_named_iterator named_begin() const + { + return boost::make_transform_iterator + (m_header.m_named_index.begin(), named_transform()); + } - typename named_index_t::iterator named_begin() const - { return m_header.m_named_index.begin(); } + const_named_iterator named_end() const + { + return boost::make_transform_iterator + (m_header.m_named_index.end(), named_transform()); + } - typename named_index_t::iterator named_end() - { return m_header.m_named_index.end(); } + const_unique_iterator unique_begin() const + { + return boost::make_transform_iterator + (m_header.m_unique_index.begin(), unique_transform()); + } - typename named_index_t::iterator named_end() const - { return m_header.m_named_index.end(); } - - typename unique_index_t::iterator unique_begin() - { return m_header.m_unique_index.begin(); } - - typename unique_index_t::iterator unique_begin() const - { return m_header.m_unique_index.begin(); } - - typename unique_index_t::iterator unique_end() - { return m_header.m_unique_index.end(); } - - typename unique_index_t::iterator unique_end() const - { return m_header.m_unique_index.end(); } + const_unique_iterator unique_end() const + { + return boost::make_transform_iterator + (m_header.m_unique_index.end(), unique_transform()); + } /// @cond - /*!Generic named/annoymous new function. Offers all the possibilities, - such as throwing, search before creating, and the constructor is - encapsulated in an object function.*/ - template - T * generic_construct(const CharType *name, + //!Generic named/anonymous new function. Offers all the possibilities, + //!such as throwing, search before creating, and the constructor is + //!encapsulated in an object function. + template + T *generic_construct(const CharType *name, std::size_t num, bool try2find, bool dothrow, - CtorFunc &ctor) + detail::in_place_interface &table) { + return static_cast + (priv_generic_construct(name, num, try2find, dothrow, table)); + } + + private: + void *priv_generic_construct(const CharType *name, + std::size_t num, + bool try2find, + bool dothrow, + detail::in_place_interface &table) + { + void *ret; //Security overflow check - if(num > ((std::size_t)-1)/sizeof(T)){ + if(num > ((std::size_t)-1)/table.size){ if(dothrow) throw bad_alloc(); else return 0; } if(name == 0){ - return this->template anonymous_construct(num, dothrow, ctor); + ret = this->prot_anonymous_construct(num, dothrow, table); } else if(name == reinterpret_cast(-1)){ - return this->priv_generic_named_construct - (unique_type, typeid(T).name(), num, try2find, dothrow, ctor, m_header.m_unique_index, is_intrusive_t()); + ret = this->priv_generic_named_construct + (detail::unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t()); } else{ - return this->priv_generic_named_construct - (named_type, name, num, try2find, dothrow, ctor, m_header.m_named_index, is_intrusive_t()); + ret = this->priv_generic_named_construct + (detail::named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t()); } + return ret; + } + + bool priv_destroy_ptr(const void *ptr, detail::in_place_interface &dtor) + { + block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment); + switch(ctrl_data->allocation_type()){ + case detail::anonymous_type: + return this->prot_anonymous_destroy(ptr, dtor); + break; + + case detail::named_type: + return this->priv_generic_named_destroy + (ctrl_data, m_header.m_named_index, dtor, is_node_index_t()); + break; + + case detail::unique_type: + return this->priv_generic_named_destroy + (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t()); + break; + + default: + //This type is unknown, bad pointer passed to this function! + assert(0); + return false; + break; + } + return false; } - private: static std::size_t priv_get_reserved_bytes() { //Get the number of bytes until the end of (*this) @@ -1053,11 +772,13 @@ class segment_manager (detail::char_ptr_cast(static_cast((segment_manager*)0)) + sizeof(Base)); } - template - std::pair priv_generic_find + template + void *priv_generic_find (const CharT* name, IndexType > &index, - boost::mpl::true_ is_intrusive) + detail::in_place_interface &table, + std::size_t &length, + true_ is_intrusive) { (void)is_intrusive; typedef IndexType > index_type; @@ -1068,39 +789,40 @@ class segment_manager boost::interprocess::scoped_lock guard(m_header); //------------------------------- //Find name in index - intrusive_compare_key key + detail::intrusive_compare_key key (name, std::char_traits::length(name)); index_it it = index.find(key); //Initialize return values - T *ret_ptr = 0; - std::size_t ret_num = 0; + void *ret_ptr = 0; + length = 0; //If found, assign values if(it != index.end()){ //Get header - detail::block_header *ctrl_data = it->get_block_header(); + block_header_t *ctrl_data = it->get_block_header(); //Sanity check - assert((ctrl_data->m_value_bytes % sizeof(T)) == 0); + assert((ctrl_data->m_value_bytes % table.size) == 0); assert(ctrl_data->sizeof_char() == sizeof(CharT)); - ret_ptr = static_cast(ctrl_data->value()); - ret_num = ctrl_data->m_value_bytes/sizeof(T); + ret_ptr = ctrl_data->value(); + length = ctrl_data->m_value_bytes/table.size; } - return std::make_pair(ret_ptr, ret_num); + return ret_ptr; } - template - std::pair priv_generic_find + template + void *priv_generic_find (const CharT* name, IndexType > &index, - boost::mpl::false_ is_intrusive) + detail::in_place_interface &table, + std::size_t &length, + false_ is_intrusive) { (void)is_intrusive; typedef IndexType > index_type; typedef typename index_type::key_type key_type; typedef typename index_type::iterator index_it; - typedef detail::block_header block_header_t; //------------------------------- boost::interprocess::scoped_lock guard(m_header); @@ -1109,8 +831,8 @@ class segment_manager index_it it = index.find(key_type(name, std::char_traits::length(name))); //Initialize return values - T *ret_ptr = 0; - std::size_t ret_num = 0; + void *ret_ptr = 0; + length = 0; //If found, assign values if(it != index.end()){ @@ -1119,46 +841,47 @@ class segment_manager (detail::get_pointer(it->second.m_ptr)); //Sanity check - assert((ctrl_data->m_value_bytes % sizeof(T)) == 0); + assert((ctrl_data->m_value_bytes % table.size) == 0); assert(ctrl_data->sizeof_char() == sizeof(CharT)); - ret_ptr = static_cast(ctrl_data->value()); - ret_num = ctrl_data->m_value_bytes/sizeof(T); + ret_ptr = ctrl_data->value(); + length = ctrl_data->m_value_bytes/table.size; } - return std::make_pair(ret_ptr, ret_num); + return ret_ptr; } - template + template bool priv_generic_named_destroy - (detail::block_header *block_header, + (block_header_t *block_header, IndexType > &index, - boost::mpl::true_ is_node_index) + detail::in_place_interface &table, + true_ is_node_index) { (void)is_node_index; typedef typename IndexType >::iterator index_it; - typedef detail::block_header block_header_t; index_it *ihdr = block_header_t::to_first_header(block_header); - return this->priv_generic_named_destroy_impl(*ihdr, index); + return this->priv_generic_named_destroy_impl(*ihdr, index, table); } - template + template bool priv_generic_named_destroy - (detail::block_header *block_header, + (block_header_t *block_header, IndexType > &index, - boost::mpl::false_ is_node_index) + detail::in_place_interface &table, + false_ is_node_index) { (void)is_node_index; CharT *name = static_cast(block_header->template name()); - return this->priv_generic_named_destroy(name, index, is_intrusive_t()); + return this->priv_generic_named_destroy(name, index, table, is_intrusive_t()); } - template + template bool priv_generic_named_destroy(const CharT *name, IndexType > &index, - boost::mpl::true_ is_intrusive_index) + detail::in_place_interface &table, + true_ is_intrusive_index) { (void)is_intrusive_index; - typedef detail::block_header block_header_t; typedef IndexType > index_type; typedef detail::index_key index_key_t; typedef typename index_type::iterator index_it; @@ -1168,7 +891,7 @@ class segment_manager boost::interprocess::scoped_lock guard(m_header); //------------------------------- //Find name in index - intrusive_compare_key key + detail::intrusive_compare_key key (name, std::char_traits::length(name)); index_it it = index.find(key); @@ -1182,11 +905,11 @@ class segment_manager block_header_t *ctrl_data = it->get_block_header(); intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data); void *memory = iv; - T *values = static_cast(ctrl_data->value()); - std::size_t num = ctrl_data->m_value_bytes/sizeof(T); + void *values = ctrl_data->value(); + std::size_t num = ctrl_data->m_value_bytes/table.size; //Sanity check - assert((ctrl_data->m_value_bytes % sizeof(T)) == 0); + assert((ctrl_data->m_value_bytes % table.size) == 0); assert(sizeof(CharT) == ctrl_data->sizeof_char()); //Erase node from index @@ -1197,14 +920,17 @@ class segment_manager iv->~intrusive_value_type(); //Call destructors and free memory - array_destroy(memory, values, num); + std::size_t destroyed; + table.destroy_n(values, num, destroyed); + this->deallocate(memory); return true; } - template + template bool priv_generic_named_destroy(const CharT *name, IndexType > &index, - boost::mpl::false_ is_intrusive_index) + detail::in_place_interface &table, + false_ is_intrusive_index) { (void)is_intrusive_index; typedef IndexType > index_type; @@ -1224,17 +950,17 @@ class segment_manager assert(0); return false; } - return this->priv_generic_named_destroy_impl(it, index); + return this->priv_generic_named_destroy_impl(it, index, table); } - template + template bool priv_generic_named_destroy_impl (const typename IndexType >::iterator &it, - IndexType > &index) + IndexType > &index, + detail::in_place_interface &table) { typedef IndexType > index_type; typedef typename index_type::iterator index_it; - typedef detail::block_header block_header_t; //Get allocation parameters block_header_t *ctrl_data = reinterpret_cast @@ -1243,12 +969,12 @@ class segment_manager (void)stored_name; //Check if the distance between the name pointer and the memory pointer - //is correct (this can detect incorrect T type in destruction) - std::size_t num = ctrl_data->m_value_bytes/sizeof(T); - T *values = static_cast(ctrl_data->value()); + //is correct (this can detect incorrect type in destruction) + std::size_t num = ctrl_data->m_value_bytes/table.size; + void *values = ctrl_data->value(); //Sanity check - assert((ctrl_data->m_value_bytes % sizeof(T)) == 0); + assert((ctrl_data->m_value_bytes % table.size) == 0); assert((void*)stored_name == ctrl_data->template name()); assert(sizeof(CharT) == ctrl_data->sizeof_char()); @@ -1270,26 +996,27 @@ class segment_manager } //Call destructors and free memory - array_destroy(memory, values, num); + std::size_t destroyed; + table.destroy_n(values, num, destroyed); + this->deallocate(memory); return true; } - template - T * priv_generic_named_construct(std::size_t type, + template + void * priv_generic_named_construct(std::size_t type, const CharT *name, std::size_t num, bool try2find, bool dothrow, - CtorFunc &ctor, + detail::in_place_interface &table, IndexType > &index, - boost::mpl::true_ is_intrusive) + true_ is_intrusive) { (void)is_intrusive; std::size_t namelen = std::char_traits::length(name); - typedef typename detail::block_header block_header_t; - block_header_t block_info ( sizeof(T)*num - , boost::alignment_of::value + block_header_t block_info ( table.size*num + , table.alignment , type , sizeof(CharT) , namelen); @@ -1316,10 +1043,9 @@ class segment_manager typename index_type::insert_commit_data commit_data; typedef typename index_type::value_type intrusive_value_type; - typedef detail::block_header block_header_t; BOOST_TRY{ - intrusive_compare_key key(name, namelen); + detail::intrusive_compare_key key(name, namelen); insert_ret = index.insert_check(key, commit_data); } //Ignore exceptions @@ -1336,7 +1062,7 @@ class segment_manager //else return null if(!insert_ret.second){ if(try2find){ - return static_cast(it->get_block_header()->value()); + return it->get_block_header()->value(); } return 0; } @@ -1359,7 +1085,7 @@ class segment_manager //Now construct the intrusive hook plus the header intrusive_value_type * intrusive_hdr = new(buffer_ptr) intrusive_value_type(); block_header_t * hdr = new(intrusive_hdr->get_block_header())block_header_t(block_info); - T *ptr = static_cast(hdr->value()); + void *ptr = hdr->value(); //Copy name to memory segment and insert data CharT *name_ptr = static_cast(hdr->template name()); @@ -1382,38 +1108,37 @@ class segment_manager detail::value_eraser value_eraser(index, it); //Avoid constructions if constructor is trivial - if(!CtorFunc::is_trivial){ - //Build scoped ptr to avoid leaks with constructor exception - boost::interprocess::scoped_ptr mem(buffer_ptr, *this); + //Build scoped ptr to avoid leaks with constructor exception + detail::mem_algo_deallocator mem + (buffer_ptr, this->memory_algorithm()); - //Construct array, this can throw - this->template array_construct(ptr, num, ctor); + //Construct array, this can throw + detail::array_construct(ptr, num, table); - //All constructors successful, we don't want to release memory - mem.release(); - } + //All constructors successful, we don't want to release memory + mem.release(); //Release node value_eraser since construction was successful value_eraser.release(); return ptr; } - /*!Generic named new function for named functions*/ - template - T * priv_generic_named_construct(std::size_t type, + //!Generic named new function for + //!named functions + template + void * priv_generic_named_construct(std::size_t type, const CharT *name, std::size_t num, bool try2find, bool dothrow, - CtorFunc &ctor, + detail::in_place_interface &table, IndexType > &index, - boost::mpl::false_ is_intrusive) + false_ is_intrusive) { (void)is_intrusive; std::size_t namelen = std::char_traits::length(name); - typedef detail::block_header block_header_t; - block_header_t block_info ( sizeof(T)*num - , boost::alignment_of::value + block_header_t block_info ( table.size*num + , table.alignment , type , sizeof(CharT) , namelen); @@ -1460,7 +1185,7 @@ class segment_manager if(try2find){ block_header_t *hdr = static_cast (detail::get_pointer(it->second.m_ptr)); - return static_cast(hdr->value()); + return hdr->value(); } return 0; } @@ -1474,11 +1199,12 @@ class segment_manager //Allocate and construct the headers if(is_node_index_t::value){ + std::size_t total_size = block_info.total_size_with_header(); if(dothrow){ - buffer_ptr = this->allocate(block_info.total_size_with_header()); + buffer_ptr = this->allocate(total_size); } else{ - buffer_ptr = this->allocate(block_info.total_size_with_header(), std::nothrow_t()); + buffer_ptr = this->allocate(total_size, std::nothrow_t()); if(!buffer_ptr) return 0; } @@ -1498,7 +1224,7 @@ class segment_manager } hdr = new(hdr)block_header_t(block_info); - T *ptr = static_cast(hdr->value()); + void *ptr = hdr->value(); //Copy name to memory segment and insert data CharT *name_ptr = static_cast(hdr->template name()); @@ -1510,32 +1236,30 @@ class segment_manager const_cast(it->first).name(name_ptr); it->second.m_ptr = hdr; - //Avoid constructions if constructor is trivial - if(!CtorFunc::is_trivial){ - //Build scoped ptr to avoid leaks with constructor exception - boost::interprocess::scoped_ptr mem(buffer_ptr, *this); + //Build scoped ptr to avoid leaks with constructor exception + detail::mem_algo_deallocator mem + (buffer_ptr, this->memory_algorithm()); - //Construct array, this can throw - this->template array_construct(ptr, num, ctor); + //Construct array, this can throw + detail::array_construct(ptr, num, table); + + //All constructors successful, we don't want to release memory + mem.release(); - //All constructors successful, we don't want to release memory - mem.release(); - } //Release node value_eraser since construction was successful value_eraser.release(); return ptr; } private: - - /*!Returns the this pointer*/ + //!Returns the this pointer segment_manager *get_this_pointer() { return this; } typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex; - /*!This struct includes needed data and derives from - rmutex to allow EBO when using null interprocess_mutex*/ + //!This struct includes needed data and derives from + //!rmutex to allow EBO when using null interprocess_mutex struct header_t : public rmutex { @@ -1555,5 +1279,5 @@ class segment_manager #include -#endif //#ifndef BOOST_INTERPROCESS_NAMED_OBJECT_ALGO_HPP +#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP diff --git a/include/boost/interprocess/shared_memory_object.hpp b/include/boost/interprocess/shared_memory_object.hpp index b817851..25a64ad 100644 --- a/include/boost/interprocess/shared_memory_object.hpp +++ b/include/boost/interprocess/shared_memory_object.hpp @@ -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 &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 &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) diff --git a/include/boost/interprocess/smart_ptr/detail/Attic/sp_counted_base_pt.hpp b/include/boost/interprocess/smart_ptr/detail/Attic/sp_counted_base_pt.hpp deleted file mode 100644 index 5b265eb..0000000 --- a/include/boost/interprocess/smart_ptr/detail/Attic/sp_counted_base_pt.hpp +++ /dev/null @@ -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 -#include - -#include -#include - -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 - -#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED diff --git a/include/boost/interprocess/smart_ptr/detail/Attic/sp_counted_base_w32.hpp b/include/boost/interprocess/smart_ptr/detail/Attic/sp_counted_base_w32.hpp deleted file mode 100644 index b0c7ad1..0000000 --- a/include/boost/interprocess/smart_ptr/detail/Attic/sp_counted_base_w32.hpp +++ /dev/null @@ -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 -#include - -#include -#include - -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( use_count_ ); } -}; - -} // namespace detail - -} // namespace interprocess - -} // namespace boost - -#include - -#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED diff --git a/include/boost/interprocess/smart_ptr/detail/shared_count.hpp b/include/boost/interprocess/smart_ptr/detail/shared_count.hpp index 0b57605..fa0c51b 100644 --- a/include/boost/interprocess/smart_ptr/detail/shared_count.hpp +++ b/include/boost/interprocess/smart_ptr/detail/shared_count.hpp @@ -28,8 +28,7 @@ #include #include #include -#include - +#include #include // std::less namespace boost { @@ -84,7 +83,7 @@ class shared_count m_pi = alloc.allocate(1); //Anti-exception deallocator scoped_ptr > + scoped_ptr_deallocator > deallocator(m_pi, alloc); //It's more correct to use A::construct but //this needs copy constructor and we don't like it diff --git a/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp index ebbf961..2ddcad2 100644 --- a/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp +++ b/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp @@ -84,8 +84,9 @@ class sp_counted_impl_pd this_pointer this_ptr (this); //Do it now! scoped_ptr >(this_ptr, a_copy); - a_copy.destroy(this_ptr); + scoped_ptr_deallocator >(this_ptr, a_copy); + typedef typename this_allocator::value_type value_type; + detail::get_pointer(this_ptr)->~value_type(); } void release() // nothrow diff --git a/include/boost/interprocess/smart_ptr/unique_ptr.hpp b/include/boost/interprocess/smart_ptr/unique_ptr.hpp index 0bec9e4..181b6a3 100644 --- a/include/boost/interprocess/smart_ptr/unique_ptr.hpp +++ b/include/boost/interprocess/smart_ptr/unique_ptr.hpp @@ -20,10 +20,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -103,7 +104,7 @@ class unique_ptr {} unique_ptr(pointer p - ,typename boost::mpl::if_ + ,typename if_ ,D ,typename boost::add_reference::type>::type d) : ptr_(p, d) @@ -113,9 +114,15 @@ class unique_ptr : ptr_(const_cast(u).release(), u.get_deleter()) {} */ + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE unique_ptr(detail::moved_object u) : ptr_(u.get().release(), u.get().get_deleter()) {} + #else + unique_ptr(unique_ptr &&u) + : ptr_(u.release(), u.get_deleter()) + {} + #endif /* template unique_ptr(const unique_ptr& u, @@ -132,6 +139,7 @@ class unique_ptr : ptr_(const_cast&>(u).release(), u.get_deleter()) {} */ + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template unique_ptr(const detail::moved_object >& u, typename boost::enable_if_c< @@ -146,6 +154,22 @@ class unique_ptr >::type = nat()) : ptr_(const_cast&>(u.get()).release(), u.get().get_deleter()) {} + #else + template + unique_ptr(unique_ptr && u, + typename boost::enable_if_c< + boost::is_convertible::pointer, pointer>::value && + boost::is_convertible::value && + ( + !boost::is_reference::value || + boost::is_same::value + ) + , + nat + >::type = nat()) + : ptr_(const_cast&>(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 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, typename boost::add_reference::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, typename boost::add_reference::type>::type d) diff --git a/include/boost/interprocess/smart_ptr/weak_ptr.hpp b/include/boost/interprocess/smart_ptr/weak_ptr.hpp index 2e680e7..923e7c3 100644 --- a/include/boost/interprocess/smart_ptr/weak_ptr.hpp +++ b/include/boost/interprocess/smart_ptr/weak_ptr.hpp @@ -18,6 +18,7 @@ #include #include +#include namespace boost{ namespace interprocess{ diff --git a/include/boost/interprocess/sync/scoped_lock.hpp b/include/boost/interprocess/sync/scoped_lock.hpp index 98ee528..58062bd 100644 --- a/include/boost/interprocess/sync/scoped_lock.hpp +++ b/include/boost/interprocess/sync/scoped_lock.hpp @@ -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 > scop) : mp_mutex(0), m_locked(scop.get().owns()) { mp_mutex = scop.get().release(); } + #else + explicit scoped_lock(scoped_lock &&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 > 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 &&upgr) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &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 > 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 &&upgr + ,detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &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 > 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 &&upgr + ,boost::posix_time::ptime &abs_time) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &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 > 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 &&shar + ,detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + sharable_lock &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 > scop) { if(this->owns()) @@ -265,6 +336,16 @@ class scoped_lock mp_mutex = scop.get().release(); return *this; } + #else + scoped_lock &operator=(scoped_lock &&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 > other) { std::swap(mp_mutex, other.get().mp_mutex); std::swap(m_locked, other.get().m_locked); } + #else + void swap(scoped_lock &&other) + { + std::swap(mp_mutex, other.mp_mutex); + std::swap(m_locked, other.m_locked); + } + #endif + /// @cond private: mutex_type *mp_mutex; diff --git a/include/boost/interprocess/sync/sharable_lock.hpp b/include/boost/interprocess/sync/sharable_lock.hpp index d6cd365..d8f733d 100644 --- a/include/boost/interprocess/sync/sharable_lock.hpp +++ b/include/boost/interprocess/sync/sharable_lock.hpp @@ -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 > upgr) : mp_mutex(0), m_locked(upgr.get().owns()) { mp_mutex = upgr.get().release(); } + #else + explicit sharable_lock(sharable_lock &&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 > 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 &&upgr) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &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 > 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 &&scop) + : mp_mutex(0), m_locked(false) + { + scoped_lock &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 > upgr) { if(this->owns()) @@ -198,6 +231,16 @@ class sharable_lock mp_mutex = upgr.get().release(); return *this; } + #else + sharable_lock &operator=(sharable_lock &&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 > other) { std::swap(mp_mutex, other.get().mp_mutex); std::swap(m_locked, other.get().m_locked); } + #else + void swap(sharable_lock &&other) + { + std::swap(mp_mutex, other.mp_mutex); + std::swap(m_locked, other.m_locked); + } + #endif + /// @cond private: mutex_type *mp_mutex; diff --git a/include/boost/interprocess/sync/upgradable_lock.hpp b/include/boost/interprocess/sync/upgradable_lock.hpp index 1f0a66b..d37bbb6 100644 --- a/include/boost/interprocess/sync/upgradable_lock.hpp +++ b/include/boost/interprocess/sync/upgradable_lock.hpp @@ -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 > upgr) : mp_mutex(0), m_locked(upgr.get().owns()) { mp_mutex = upgr.get().release(); } + #else + explicit upgradable_lock(upgradable_lock &&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 > 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 &&scop) + : mp_mutex(0), m_locked(false) + { + scoped_lock &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 > 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 &&shar + , detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + sharable_lock &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 > upgr) { if(this->owns()) @@ -203,6 +240,16 @@ class upgradable_lock mp_mutex = upgr.get().release(); return *this; } + #else + upgradable_lock &operator=(upgradable_lock &&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 > other) { std::swap(mp_mutex, other.get().mp_mutex); std::swap(m_locked, other.get().m_locked); } + #else + void swap(upgradable_lock &&other) + { + std::swap(mp_mutex, other.mp_mutex); + std::swap(m_locked, other.m_locked); + } + #endif + /// @cond private: mutex_type *mp_mutex; diff --git a/include/boost/interprocess/windows_shared_memory.hpp b/include/boost/interprocess/windows_shared_memory.hpp index f5a66d9..158eb52 100644 --- a/include/boost/interprocess/windows_shared_memory.hpp +++ b/include/boost/interprocess/windows_shared_memory.hpp @@ -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 &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 &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); diff --git a/index.html b/index.html index f1a6b2d..222acdf 100644 --- a/index.html +++ b/index.html @@ -1,8 +1,9 @@ - + -Automatic redirection failed, please go to doc/html/interprocess.html +Automatic redirection failed, please go to +../../doc/html/interprocess.html diff --git a/proj/vc7ide/Attic/ProcessA.vcproj b/proj/vc7ide/Attic/ProcessA.vcproj deleted file mode 100644 index 18884ba..0000000 --- a/proj/vc7ide/Attic/ProcessA.vcproj +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/ProcessAFixed.vcproj b/proj/vc7ide/Attic/ProcessAFixed.vcproj deleted file mode 100644 index 4026bf9..0000000 --- a/proj/vc7ide/Attic/ProcessAFixed.vcproj +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/ProcessB.vcproj b/proj/vc7ide/Attic/ProcessB.vcproj deleted file mode 100644 index f7fa6f8..0000000 --- a/proj/vc7ide/Attic/ProcessB.vcproj +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/ProcessBFixed.vcproj b/proj/vc7ide/Attic/ProcessBFixed.vcproj deleted file mode 100644 index f6ca6ac..0000000 --- a/proj/vc7ide/Attic/ProcessBFixed.vcproj +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/allocate_ex.vcproj b/proj/vc7ide/Attic/allocate_ex.vcproj deleted file mode 100644 index c43dea2..0000000 --- a/proj/vc7ide/Attic/allocate_ex.vcproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/file_lock_test.vcproj b/proj/vc7ide/Attic/file_lock_test.vcproj deleted file mode 100644 index 3e311dc..0000000 --- a/proj/vc7ide/Attic/file_lock_test.vcproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/hash_table_ex.vcproj b/proj/vc7ide/Attic/hash_table_ex.vcproj deleted file mode 100644 index 430ecf8..0000000 --- a/proj/vc7ide/Attic/hash_table_ex.vcproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/intersegment_ptr_test.vcproj b/proj/vc7ide/Attic/intersegment_ptr_test.vcproj deleted file mode 100644 index ea0de1f..0000000 --- a/proj/vc7ide/Attic/intersegment_ptr_test.vcproj +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/named_allocate_ex.vcproj b/proj/vc7ide/Attic/named_allocate_ex.vcproj deleted file mode 100644 index 1c71de3..0000000 --- a/proj/vc7ide/Attic/named_allocate_ex.vcproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/read_write_mutex_test.vcproj b/proj/vc7ide/Attic/read_write_mutex_test.vcproj deleted file mode 100644 index 7e507b6..0000000 --- a/proj/vc7ide/Attic/read_write_mutex_test.vcproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Attic/sharable_mutex.vcproj b/proj/vc7ide/Attic/sharable_mutex.vcproj deleted file mode 100644 index b821bcf..0000000 --- a/proj/vc7ide/Attic/sharable_mutex.vcproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Interprocess.sln b/proj/vc7ide/Interprocess.sln index 30ca319..4ef0d8f 100644 --- a/proj/vc7ide/Interprocess.sln +++ b/proj/vc7ide/Interprocess.sln @@ -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 diff --git a/proj/vc7ide/doc_shared_memory.vcproj b/proj/vc7ide/doc_shared_memory.vcproj index c31a947..4ca52b7 100644 --- a/proj/vc7ide/doc_shared_memory.vcproj +++ b/proj/vc7ide/doc_shared_memory.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_shared_memory" + ProjectGUID="{58CCE183-6032-12FE-4FC7-83A79F760B61}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/interprocesslib.vcproj b/proj/vc7ide/interprocesslib.vcproj index 52b0a6d..ae82f76 100644 --- a/proj/vc7ide/interprocesslib.vcproj +++ b/proj/vc7ide/interprocesslib.vcproj @@ -331,9 +331,6 @@ - - @@ -395,9 +392,15 @@ + + + + @@ -407,21 +410,36 @@ + + + + + + + + + + @@ -431,6 +449,9 @@ + + @@ -443,6 +464,9 @@ + + @@ -461,13 +485,6 @@ - - - - + + + + diff --git a/test/allocexcept_test.cpp b/test/allocexcept_test.cpp index e04a02f..c06cc76 100644 --- a/test/allocexcept_test.cpp +++ b/test/allocexcept_test.cpp @@ -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); diff --git a/test/list_test.hpp b/test/list_test.hpp index 817e555..8b142ce 100644 --- a/test/list_test.hpp +++ b/test/list_test.hpp @@ -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; } diff --git a/test/map_test.hpp b/test/map_test.hpp index 2b98958..ab18985 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -19,6 +19,7 @@ #include "print_container.hpp" #include #include +#include template bool operator ==(std::pair &p1, std::pair &p2) diff --git a/test/memory_algorithm_test_template.hpp b/test/memory_algorithm_test_template.hpp index 1310b4d..a710577 100644 --- a/test/memory_algorithm_test_template.hpp +++ b/test/memory_algorithm_test_template.hpp @@ -49,6 +49,7 @@ template bool test_allocation_direct_deallocation(Allocator &a) { std::vector 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 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; diff --git a/test/movable_int.hpp b/test/movable_int.hpp index 298cc88..8d16596 100644 --- a/test/movable_int.hpp +++ b/test/movable_int.hpp @@ -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 &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 &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 &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 &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; } diff --git a/test/named_allocation_test_template.hpp b/test/named_allocation_test_template.hpp index 71f1bbb..7e58758 100644 --- a/test/named_allocation_test_template.hpp +++ b/test/named_allocation_test_template.hpp @@ -15,11 +15,15 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include namespace boost { namespace interprocess { namespace test { @@ -28,23 +32,36 @@ namespace boost { namespace interprocess { namespace test { template bool test_names_and_types(ManagedMemory &m) { + typedef typename ManagedMemory::char_type char_type; + typedef std::char_traits char_traits_type; std::vector buffers; const int BufferLen = 100; - char name[BufferLen]; + char_type name[BufferLen]; + + basic_bufferstream 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(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(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 +bool test_named_iterators(ManagedMemory &m) +{ + typedef typename ManagedMemory::char_type char_type; + typedef std::char_traits char_traits_type; + std::vector buffers; + const int BufferLen = 100; + char_type name[BufferLen]; + typedef std::basic_string string_type; + std::set names; + + basic_bufferstream 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(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(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 bool test_direct_named_allocation_destruction(ManagedMemory &m) { + typedef typename ManagedMemory::char_type char_type; + typedef std::char_traits char_traits_type; std::vector buffers; const int BufferLen = 100; - char name[BufferLen]; + char_type name[BufferLen]; + + basic_bufferstream 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(name, std::nothrow)(i); if(!ptr) break; @@ -102,12 +194,18 @@ bool test_direct_named_allocation_destruction(ManagedMemory &m) template bool test_named_allocation_inverse_destruction(ManagedMemory &m) { + typedef typename ManagedMemory::char_type char_type; + typedef std::char_traits char_traits_type; + std::vector buffers; const int BufferLen = 100; - char name[BufferLen]; + char_type name[BufferLen]; + + basic_bufferstream 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(name, std::nothrow)(i); if(!ptr) break; @@ -133,12 +231,18 @@ bool test_named_allocation_inverse_destruction(ManagedMemory &m) template bool test_named_allocation_mixed_destruction(ManagedMemory &m) { + typedef typename ManagedMemory::char_type char_type; + typedef std::char_traits char_traits_type; + std::vector buffers; const int BufferLen = 100; - char name[BufferLen]; + char_type name[BufferLen]; + + basic_bufferstream 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(name, std::nothrow)(i); if(!ptr) break; @@ -166,13 +270,18 @@ bool test_named_allocation_mixed_destruction(ManagedMemory &m) template bool test_inverse_named_allocation_destruction(ManagedMemory &m) { + typedef typename ManagedMemory::char_type char_type; + typedef std::char_traits char_traits_type; + std::vector buffers; const int BufferLen = 100; - char name[BufferLen]; - const unsigned int FirstNumber = (unsigned int)-1; + char_type name[BufferLen]; + + basic_bufferstream 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(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; }