From 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 20:24:20 +0200 Subject: Adding upstream version 14.2.21. Signed-off-by: Daniel Baumann --- src/boost/libs/interprocess/test/Jamfile.v2 | 40 + .../interprocess/test/adaptive_node_pool_test.cpp | 30 + .../libs/interprocess/test/adaptive_pool_test.cpp | 71 ++ src/boost/libs/interprocess/test/allocator_v1.hpp | 167 ++++ .../libs/interprocess/test/allocexcept_test.cpp | 95 ++ .../test/anonymous_shared_memory_test.cpp | 54 + .../interprocess/test/boost_interprocess_check.hpp | 27 + .../libs/interprocess/test/boost_use_windows_h.cpp | 38 + .../libs/interprocess/test/bufferstream_test.cpp | 144 +++ .../test/cached_adaptive_pool_test.cpp | 73 ++ .../test/cached_node_allocator_test.cpp | 67 ++ .../interprocess/test/check_equal_containers.hpp | 92 ++ .../libs/interprocess/test/condition_any_test.cpp | 34 + .../libs/interprocess/test/condition_test.cpp | 40 + .../interprocess/test/condition_test_template.hpp | 401 ++++++++ src/boost/libs/interprocess/test/data_test.cpp | 97 ++ src/boost/libs/interprocess/test/deque_test.cpp | 312 ++++++ .../interprocess/test/dummy_test_allocator.hpp | 149 +++ src/boost/libs/interprocess/test/emplace_test.hpp | 627 ++++++++++++ .../test/enable_shared_from_this_test.cpp | 97 ++ .../test/expand_bwd_test_allocator.hpp | 193 ++++ .../interprocess/test/expand_bwd_test_template.hpp | 269 +++++ .../libs/interprocess/test/file_lock_test.cpp | 80 ++ .../libs/interprocess/test/file_mapping_test.cpp | 164 ++++ .../test/flat_map_index_allocation_test.cpp | 25 + .../libs/interprocess/test/flat_tree_test.cpp | 202 ++++ .../libs/interprocess/test/get_process_id_name.hpp | 71 ++ .../libs/interprocess/test/heap_allocator_v1.hpp | 166 ++++ .../test/intermodule_singleton_test.cpp | 330 +++++++ .../libs/interprocess/test/intrusive_ptr_test.cpp | 546 +++++++++++ .../test/iset_index_allocation_test.cpp | 24 + .../test/iunordered_set_index_allocation_test.cpp | 25 + src/boost/libs/interprocess/test/list_test.cpp | 63 ++ src/boost/libs/interprocess/test/list_test.hpp | 281 ++++++ .../interprocess/test/managed_mapped_file_test.cpp | 239 +++++ .../test/managed_shared_memory_test.cpp | 216 ++++ .../test/managed_windows_shared_memory_test.cpp | 152 +++ .../test/managed_xsi_shared_memory_test.cpp | 174 ++++ .../test/map_index_allocation_test.cpp | 25 + src/boost/libs/interprocess/test/map_test.hpp | 593 +++++++++++ .../libs/interprocess/test/mapped_file_test.cpp | 100 ++ .../interprocess/test/memory_algorithm_test.cpp | 91 ++ .../test/memory_algorithm_test_template.hpp | 1036 ++++++++++++++++++++ .../libs/interprocess/test/message_queue_test.cpp | 376 +++++++ src/boost/libs/interprocess/test/movable_int.hpp | 293 ++++++ src/boost/libs/interprocess/test/mutex_test.cpp | 37 + .../libs/interprocess/test/mutex_test_template.hpp | 394 ++++++++ .../libs/interprocess/test/mutex_timeout_test.cpp | 30 + .../test/named_allocation_test_template.hpp | 495 ++++++++++ .../interprocess/test/named_condition_any_test.cpp | 189 ++++ .../interprocess/test/named_condition_test.cpp | 189 ++++ .../interprocess/test/named_construct_test.cpp | 196 ++++ .../interprocess/test/named_creation_template.hpp | 132 +++ .../libs/interprocess/test/named_mutex_test.cpp | 38 + .../test/named_recursive_mutex_test.cpp | 41 + .../interprocess/test/named_semaphore_test.cpp | 123 +++ .../test/named_sharable_mutex_test.cpp | 103 ++ .../test/named_upgradable_mutex_test.cpp | 103 ++ .../libs/interprocess/test/node_allocator_test.cpp | 66 ++ .../libs/interprocess/test/node_pool_test.cpp | 29 + .../libs/interprocess/test/node_pool_test.hpp | 163 +++ .../libs/interprocess/test/null_index_test.cpp | 51 + .../libs/interprocess/test/offset_ptr_test.cpp | 352 +++++++ .../libs/interprocess/test/print_container.hpp | 56 ++ .../test/private_adaptive_pool_test.cpp | 66 ++ .../test/private_node_allocator_test.cpp | 66 ++ .../interprocess/test/recursive_mutex_test.cpp | 42 + .../interprocess/test/robust_emulation_test.cpp | 22 + .../libs/interprocess/test/robust_mutex_test.hpp | 208 ++++ .../test/robust_recursive_emulation_test.cpp | 23 + .../interprocess/test/segment_manager_test.cpp | 478 +++++++++ .../libs/interprocess/test/semaphore_test.cpp | 70 ++ src/boost/libs/interprocess/test/set_test.hpp | 594 +++++++++++ .../libs/interprocess/test/sharable_mutex_test.cpp | 31 + .../test/sharable_mutex_test_template.hpp | 291 ++++++ .../test/shared_memory_mapping_test.cpp | 239 +++++ .../libs/interprocess/test/shared_memory_test.cpp | 87 ++ .../libs/interprocess/test/shared_ptr_test.cpp | 615 ++++++++++++ src/boost/libs/interprocess/test/slist_test.cpp | 63 ++ .../libs/interprocess/test/stable_vector_test.cpp | 72 ++ src/boost/libs/interprocess/test/string_test.cpp | 289 ++++++ src/boost/libs/interprocess/test/tree_test.cpp | 199 ++++ .../libs/interprocess/test/unique_ptr_test.cpp | 142 +++ .../libs/interprocess/test/unordered_test.cpp | 100 ++ .../interprocess/test/upgradable_mutex_test.cpp | 173 ++++ .../libs/interprocess/test/user_buffer_test.cpp | 259 +++++ src/boost/libs/interprocess/test/util.hpp | 95 ++ src/boost/libs/interprocess/test/vector_test.cpp | 103 ++ src/boost/libs/interprocess/test/vector_test.hpp | 254 +++++ .../libs/interprocess/test/vectorstream_test.cpp | 185 ++++ .../interprocess/test/windows_shared_dir_func.cpp | 84 ++ .../test/windows_shared_memory_mapping_test.cpp | 138 +++ .../test/windows_shared_memory_test.cpp | 80 ++ .../test/xsi_shared_memory_mapping_test.cpp | 139 +++ 94 files changed, 16383 insertions(+) create mode 100644 src/boost/libs/interprocess/test/Jamfile.v2 create mode 100644 src/boost/libs/interprocess/test/adaptive_node_pool_test.cpp create mode 100644 src/boost/libs/interprocess/test/adaptive_pool_test.cpp create mode 100644 src/boost/libs/interprocess/test/allocator_v1.hpp create mode 100644 src/boost/libs/interprocess/test/allocexcept_test.cpp create mode 100644 src/boost/libs/interprocess/test/anonymous_shared_memory_test.cpp create mode 100644 src/boost/libs/interprocess/test/boost_interprocess_check.hpp create mode 100644 src/boost/libs/interprocess/test/boost_use_windows_h.cpp create mode 100644 src/boost/libs/interprocess/test/bufferstream_test.cpp create mode 100644 src/boost/libs/interprocess/test/cached_adaptive_pool_test.cpp create mode 100644 src/boost/libs/interprocess/test/cached_node_allocator_test.cpp create mode 100644 src/boost/libs/interprocess/test/check_equal_containers.hpp create mode 100644 src/boost/libs/interprocess/test/condition_any_test.cpp create mode 100644 src/boost/libs/interprocess/test/condition_test.cpp create mode 100644 src/boost/libs/interprocess/test/condition_test_template.hpp create mode 100644 src/boost/libs/interprocess/test/data_test.cpp create mode 100644 src/boost/libs/interprocess/test/deque_test.cpp create mode 100644 src/boost/libs/interprocess/test/dummy_test_allocator.hpp create mode 100644 src/boost/libs/interprocess/test/emplace_test.hpp create mode 100644 src/boost/libs/interprocess/test/enable_shared_from_this_test.cpp create mode 100644 src/boost/libs/interprocess/test/expand_bwd_test_allocator.hpp create mode 100644 src/boost/libs/interprocess/test/expand_bwd_test_template.hpp create mode 100644 src/boost/libs/interprocess/test/file_lock_test.cpp create mode 100644 src/boost/libs/interprocess/test/file_mapping_test.cpp create mode 100644 src/boost/libs/interprocess/test/flat_map_index_allocation_test.cpp create mode 100644 src/boost/libs/interprocess/test/flat_tree_test.cpp create mode 100644 src/boost/libs/interprocess/test/get_process_id_name.hpp create mode 100644 src/boost/libs/interprocess/test/heap_allocator_v1.hpp create mode 100644 src/boost/libs/interprocess/test/intermodule_singleton_test.cpp create mode 100644 src/boost/libs/interprocess/test/intrusive_ptr_test.cpp create mode 100644 src/boost/libs/interprocess/test/iset_index_allocation_test.cpp create mode 100644 src/boost/libs/interprocess/test/iunordered_set_index_allocation_test.cpp create mode 100644 src/boost/libs/interprocess/test/list_test.cpp create mode 100644 src/boost/libs/interprocess/test/list_test.hpp create mode 100644 src/boost/libs/interprocess/test/managed_mapped_file_test.cpp create mode 100644 src/boost/libs/interprocess/test/managed_shared_memory_test.cpp create mode 100644 src/boost/libs/interprocess/test/managed_windows_shared_memory_test.cpp create mode 100644 src/boost/libs/interprocess/test/managed_xsi_shared_memory_test.cpp create mode 100644 src/boost/libs/interprocess/test/map_index_allocation_test.cpp create mode 100644 src/boost/libs/interprocess/test/map_test.hpp create mode 100644 src/boost/libs/interprocess/test/mapped_file_test.cpp create mode 100644 src/boost/libs/interprocess/test/memory_algorithm_test.cpp create mode 100644 src/boost/libs/interprocess/test/memory_algorithm_test_template.hpp create mode 100644 src/boost/libs/interprocess/test/message_queue_test.cpp create mode 100644 src/boost/libs/interprocess/test/movable_int.hpp create mode 100644 src/boost/libs/interprocess/test/mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/mutex_test_template.hpp create mode 100644 src/boost/libs/interprocess/test/mutex_timeout_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_allocation_test_template.hpp create mode 100644 src/boost/libs/interprocess/test/named_condition_any_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_condition_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_construct_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_creation_template.hpp create mode 100644 src/boost/libs/interprocess/test/named_mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_recursive_mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_semaphore_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_sharable_mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/named_upgradable_mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/node_allocator_test.cpp create mode 100644 src/boost/libs/interprocess/test/node_pool_test.cpp create mode 100644 src/boost/libs/interprocess/test/node_pool_test.hpp create mode 100644 src/boost/libs/interprocess/test/null_index_test.cpp create mode 100644 src/boost/libs/interprocess/test/offset_ptr_test.cpp create mode 100644 src/boost/libs/interprocess/test/print_container.hpp create mode 100644 src/boost/libs/interprocess/test/private_adaptive_pool_test.cpp create mode 100644 src/boost/libs/interprocess/test/private_node_allocator_test.cpp create mode 100644 src/boost/libs/interprocess/test/recursive_mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/robust_emulation_test.cpp create mode 100644 src/boost/libs/interprocess/test/robust_mutex_test.hpp create mode 100644 src/boost/libs/interprocess/test/robust_recursive_emulation_test.cpp create mode 100644 src/boost/libs/interprocess/test/segment_manager_test.cpp create mode 100644 src/boost/libs/interprocess/test/semaphore_test.cpp create mode 100644 src/boost/libs/interprocess/test/set_test.hpp create mode 100644 src/boost/libs/interprocess/test/sharable_mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/sharable_mutex_test_template.hpp create mode 100644 src/boost/libs/interprocess/test/shared_memory_mapping_test.cpp create mode 100644 src/boost/libs/interprocess/test/shared_memory_test.cpp create mode 100644 src/boost/libs/interprocess/test/shared_ptr_test.cpp create mode 100644 src/boost/libs/interprocess/test/slist_test.cpp create mode 100644 src/boost/libs/interprocess/test/stable_vector_test.cpp create mode 100644 src/boost/libs/interprocess/test/string_test.cpp create mode 100644 src/boost/libs/interprocess/test/tree_test.cpp create mode 100644 src/boost/libs/interprocess/test/unique_ptr_test.cpp create mode 100644 src/boost/libs/interprocess/test/unordered_test.cpp create mode 100644 src/boost/libs/interprocess/test/upgradable_mutex_test.cpp create mode 100644 src/boost/libs/interprocess/test/user_buffer_test.cpp create mode 100644 src/boost/libs/interprocess/test/util.hpp create mode 100644 src/boost/libs/interprocess/test/vector_test.cpp create mode 100644 src/boost/libs/interprocess/test/vector_test.hpp create mode 100644 src/boost/libs/interprocess/test/vectorstream_test.cpp create mode 100644 src/boost/libs/interprocess/test/windows_shared_dir_func.cpp create mode 100644 src/boost/libs/interprocess/test/windows_shared_memory_mapping_test.cpp create mode 100644 src/boost/libs/interprocess/test/windows_shared_memory_test.cpp create mode 100644 src/boost/libs/interprocess/test/xsi_shared_memory_mapping_test.cpp (limited to 'src/boost/libs/interprocess/test') diff --git a/src/boost/libs/interprocess/test/Jamfile.v2 b/src/boost/libs/interprocess/test/Jamfile.v2 new file mode 100644 index 00000000..a09bf8f2 --- /dev/null +++ b/src/boost/libs/interprocess/test/Jamfile.v2 @@ -0,0 +1,40 @@ +# Boost Interprocess Library Test Jamfile + +# (C) Copyright Ion Gaztanaga 2006. +# Use, modification and distribution are subject to the +# Boost Software License, Version 1.0. (See accompanying file +# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# Adapted from John Maddock's TR1 Jamfile.v2 +# Copyright John Maddock 2005. +# Use, modification and distribution are subject to the +# Boost Software License, Version 1.0. (See accompanying file +# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# this rule enumerates through all the sources and invokes +# the run rule for each source, the result is a list of all +# the run rules, which we can pass on to the test_suite rule: + +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob *.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + acc:-lrt + acc-pa_risc:-lrt + gcc,windows:"-lole32 -loleaut32 -lpsapi -ladvapi32" + hpux,gcc:"-Wl,+as,mpas" + windows,clang:"-lole32 -loleaut32 -lpsapi -ladvapi32" + linux:"-lrt" + ] ; + } + + return $(all_rules) ; +} + +test-suite interprocess_test : [ test_all r ] : multi ; diff --git a/src/boost/libs/interprocess/test/adaptive_node_pool_test.cpp b/src/boost/libs/interprocess/test/adaptive_node_pool_test.cpp new file mode 100644 index 00000000..3caae188 --- /dev/null +++ b/src/boost/libs/interprocess/test/adaptive_node_pool_test.cpp @@ -0,0 +1,30 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS +#include +#include "node_pool_test.hpp" +#include +#include + +using namespace boost::interprocess; +typedef managed_shared_memory::segment_manager segment_manager_t; + +int main () +{ + typedef ipcdetail::private_adaptive_node_pool + node_pool_t; + + if(!test::test_all_node_pool()) + return 1; + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/adaptive_pool_test.cpp b/src/boost/libs/interprocess/test/adaptive_pool_test.cpp new file mode 100644 index 00000000..59c7f979 --- /dev/null +++ b/src/boost/libs/interprocess/test/adaptive_pool_test.cpp @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS +#include +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" +#include "vector_test.hpp" + +using namespace boost::interprocess; + +//We will work with wide characters for shared memory objects +//Alias an adaptive pool that allocates ints +typedef adaptive_pool + shmem_node_allocator_t; + +typedef ipcdetail::adaptive_pool_v1 + shmem_node_allocator_v1_t; + +namespace boost { +namespace interprocess { + +//Explicit instantiations to catch compilation errors +template class adaptive_pool; +template class adaptive_pool; + +namespace ipcdetail { + +template class ipcdetail::adaptive_pool_v1; +template class ipcdetail::adaptive_pool_v1; + +}}} + +//Alias list types +typedef list MyShmList; +typedef list MyShmListV1; + +//Alias vector types +typedef vector MyShmVector; +typedef vector MyShmVectorV1; + +int main () +{ + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/allocator_v1.hpp b/src/boost/libs/interprocess/test/allocator_v1.hpp new file mode 100644 index 00000000..d68ef9f4 --- /dev/null +++ b/src/boost/libs/interprocess/test/allocator_v1.hpp @@ -0,0 +1,167 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_ALLOCATOR_V1_HPP +#define BOOST_INTERPROCESS_ALLOCATOR_V1_HPP + +#if defined (_MSC_VER) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an allocator_v1 that allocates portions of fixed size +//!memory buffer (shared memory, mapped file...) + +namespace boost { +namespace interprocess { +namespace test { + +//!An STL compatible allocator_v1 that uses a segment manager as +//!memory source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator_v1 in shared memory, memory mapped-files, etc...*/ +template +class allocator_v1 +{ + private: + typedef allocator_v1 self_t; + typedef SegmentManager segment_manager; + typedef typename segment_manager::void_pointer aux_pointer_t; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type cvoid_ptr; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type alloc_ptr_t; + + template + allocator_v1& operator=(const allocator_v1&); + + allocator_v1& operator=(const allocator_v1&); + + alloc_ptr_t mp_mngr; + + public: + typedef T value_type; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename segment_manager::size_type size_type; + typedef typename segment_manager::difference_type difference_type; + + //!Obtains an allocator_v1 of other type + template + struct rebind + { + typedef allocator_v1 other; + }; + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return ipcdetail::to_raw_pointer(mp_mngr); } +/* + //!Returns address of mutable object. Never throws + pointer address(reference value) const + { return pointer(addressof(value)); } + + //!Returns address of non mutable object. Never throws + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } +*/ + //!Constructor from the segment manager. Never throws + allocator_v1(segment_manager *segment_mngr) + : mp_mngr(segment_mngr) { } + + //!Constructor from other allocator_v1. Never throws + allocator_v1(const allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){ } + + //!Constructor from related allocator_v1. Never throws + template + allocator_v1(const allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){} + + //!Allocates memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_ptr hint = 0) + { + if(size_overflows(count)){ + throw bad_alloc(); + } + (void)hint; return pointer(static_cast(mp_mngr->allocate(count*sizeof(T)))); + } + + //!Deallocates memory previously allocated. Never throws + void deallocate(const pointer &ptr, size_type) + { mp_mngr->deallocate((void*)ipcdetail::to_raw_pointer(ptr)); } + + //!Construct object, calling constructor. + //!Throws if T(const T&) throws + void construct(const pointer &ptr, const_reference value) + { new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(value); } + + //!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(); } + + //!Swap segment manager. Does not throw. If each allocator_v1 is placed in + //!different memory segments, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { ::boost::adl_move_swap(alloc1.mp_mngr, alloc2.mp_mngr); } +}; + +//!Equality test for same type of allocator_v1 +template inline +bool operator==(const allocator_v1 &alloc1, + const allocator_v1 &alloc2) + { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } + +//!Inequality test for same type of allocator_v1 +template inline +bool operator!=(const allocator_v1 &alloc1, + const allocator_v1 &alloc2) + { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } + +} //namespace test { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_ALLOCATOR_V1_HPP + diff --git a/src/boost/libs/interprocess/test/allocexcept_test.cpp b/src/boost/libs/interprocess/test/allocexcept_test.cpp new file mode 100644 index 00000000..696b2797 --- /dev/null +++ b/src/boost/libs/interprocess/test/allocexcept_test.cpp @@ -0,0 +1,95 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include "print_container.hpp" +#include +#include "get_process_id_name.hpp" + +struct InstanceCounter +{ + InstanceCounter(){++counter;} + InstanceCounter(const InstanceCounter&){++counter;} + ~InstanceCounter(){--counter;} + static std::size_t counter; +}; + +std::size_t InstanceCounter::counter = 0; + +using namespace boost::interprocess; + + +int main () +{ + const int memsize = 16384; + const char *const shMemName = test::get_process_id_name(); + + try{ + shared_memory_object::remove(shMemName); + + //Named allocate capable shared mem allocator + managed_shared_memory segment(create_only, shMemName, memsize); + + //STL compatible allocator object, uses allocate(), deallocate() functions + typedef allocator + inst_allocator_t; + const inst_allocator_t myallocator (segment.get_segment_manager()); + + typedef vector MyVect; + + //We'll provoke an exception, let's see if exception handling works + try{ + //Fill vector until there is no more memory + MyVect myvec(myallocator); + int i; + for(i = 0; true; ++i){ + myvec.push_back(InstanceCounter()); + } + } + catch(boost::interprocess::bad_alloc &){ + if(InstanceCounter::counter != 0) + return 1; + } + + //We'll provoke an exception, let's see if exception handling works + try{ + //Fill vector at the beginning until there is no more memory + MyVect myvec(myallocator); + int i; + InstanceCounter ic; + for(i = 0; true; ++i){ + myvec.insert(myvec.begin(), i, ic); + } + } + catch(boost::interprocess::bad_alloc &){ + if(InstanceCounter::counter != 0) + return 1; + } + catch(std::length_error &){ + if(InstanceCounter::counter != 0) + return 1; + } + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/anonymous_shared_memory_test.cpp b/src/boost/libs/interprocess/test/anonymous_shared_memory_test.cpp new file mode 100644 index 00000000..cdff6e66 --- /dev/null +++ b/src/boost/libs/interprocess/test/anonymous_shared_memory_test.cpp @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + try{ + const std::size_t MemSize = 99999*2; + { + //Now check anonymous mapping + mapped_region region(anonymous_shared_memory(MemSize)); + + //Write pattern + unsigned char *pattern = static_cast(region.get_address()); + for(std::size_t i = 0 + ;i < MemSize + ;++i, ++pattern){ + *pattern = static_cast(i); + } + + //Check pattern + pattern = static_cast(region.get_address()); + for(std::size_t i = 0 + ;i < MemSize + ;++i, ++pattern){ + if(*pattern != static_cast(i)){ + return 1; + } + } + } + } + catch(std::exception &exc){ + std::cout << "Unhandled exception: " << exc.what() << std::endl; + return 1; + } + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/boost_interprocess_check.hpp b/src/boost/libs/interprocess/test/boost_interprocess_check.hpp new file mode 100644 index 00000000..675613c9 --- /dev/null +++ b/src/boost/libs/interprocess/test/boost_interprocess_check.hpp @@ -0,0 +1,27 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TEST_CHECK_HEADER +#define BOOST_INTERPROCESS_TEST_CHECK_HEADER + +#include +#include +#include + +namespace boost { namespace interprocess { namespace test { + +#define BOOST_INTERPROCESS_CHECK( P ) \ + if(!(P)) do{ assert(P); std::cout << "Failed: " << #P << " file: " << __FILE__ << " line : " << __LINE__ << std::endl; throw boost::interprocess::interprocess_exception(#P);}while(0) + +}}} //namespace boost { namespace interprocess { namespace test { + +#include + +#endif //BOOST_INTERPROCESS_TEST_CHECK_HEADER diff --git a/src/boost/libs/interprocess/test/boost_use_windows_h.cpp b/src/boost/libs/interprocess/test/boost_use_windows_h.cpp new file mode 100644 index 00000000..2fb1a612 --- /dev/null +++ b/src/boost/libs/interprocess/test/boost_use_windows_h.cpp @@ -0,0 +1,38 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. 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. +// +////////////////////////////////////////////////////////////////////////////// +#define _WIN32_WINNT 0x0501 +#define BOOST_USE_WINDOWS_H + +#include +#include + +#ifdef BOOST_INTERPROCESS_WINDOWS + +#include + +using namespace boost::interprocess; + +int main () +{ + windows_shared_memory dummy; + static_cast(dummy); + return 0; +} + +#else + +int main() +{ + return 0; +} + +#endif + +#include diff --git a/src/boost/libs/interprocess/test/bufferstream_test.cpp b/src/boost/libs/interprocess/test/bufferstream_test.cpp new file mode 100644 index 00000000..6b6cb24c --- /dev/null +++ b/src/boost/libs/interprocess/test/bufferstream_test.cpp @@ -0,0 +1,144 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +namespace boost{ +namespace interprocess{ + +//Force instantiations to catch compile-time errors +template class basic_bufferbuf; +template class basic_bufferstream; +template class basic_ibufferstream; +template class basic_obufferstream; + +}} + +using namespace boost::interprocess; + +static int bufferstream_test() +{ + //Static big enough buffer + { + const int BufSize = 10001; + //This will be zero-initialized + static char buffer [BufSize]; + bufferstream bufstream; + if(bufstream.tellg() != std::streampos(0)){ + return 1; + } + if(bufstream.tellp() != std::streampos(0)){ + return 1; + } + std::stringstream std_stringstream; + std::string str1, str2, str3("testline:"); + int number1, number2; + + //Make sure we have null in the last byte + bufstream.buffer(buffer, BufSize-1); + for(int i = 0; i < 100; ++i){ + bufstream << "testline: " << i << std::endl; + std_stringstream << "testline: " << i << std::endl; + } + + if(std::strcmp(buffer, std_stringstream.str().c_str()) != 0){ + return 1; + } + + //We shouldn't have reached the end of the buffer writing + if(bufstream.bad()){ + assert(0); + return 1; + } + + bufstream.buffer(buffer, BufSize-1); + for(int i = 0; i < 100; ++i){ + bufstream >> str1 >> number1; + std_stringstream >> str2 >> number2; + if((str1 != str2) || (str1 != str3)){ + assert(0); return 1; + } + if((number1 != number2) || (number1 != i)){ + assert(0); return 1; + } + } + //We shouldn't have reached the end of the buffer reading + if(bufstream.eof()){ + assert(0); + return 1; + } + } + + //Static small buffer. Check if buffer + //overflow protection works. + { + const int BufSize = 101; + //This will be zero-initialized + static char buffer [BufSize]; + bufferstream bufstream; + std::stringstream std_stringstream; + std::string str1; + int number1; + + //Make sure we have null in the last byte + bufstream.buffer(buffer, BufSize-1); + for(int i = 0; i < 100; ++i){ + bufstream << "testline: " << i << std::endl; + std_stringstream << "testline: " << i << std::endl; + } + + //Contents should be different + if(std::strcmp(buffer, std_stringstream.str().c_str()) == 0){ + return 1; + } + //The stream shouldn't be in good health + if(bufstream.good()){ + assert(0); + return 1; + } + //The bad flag should be active. This indicates overflow attempt + if(!bufstream.bad()){ + assert(0); + return 1; + } + + //Now let's test read overflow + bufstream.clear(); + bufstream.buffer(buffer, BufSize-1); + for(int i = 0; i < 100; ++i){ + bufstream >> str1 >> number1; + } + //The stream shouldn't be in good health + if(bufstream.good()){ + assert(0); + return 1; + } + //The eof flag indicates we have reached the end of the + //buffer while reading + if(!bufstream.eof()){ + assert(0); + return 1; + } + } + return 0; +} + +int main () +{ + if(bufferstream_test()){ + return 1; + } + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/cached_adaptive_pool_test.cpp b/src/boost/libs/interprocess/test/cached_adaptive_pool_test.cpp new file mode 100644 index 00000000..ee5b86c2 --- /dev/null +++ b/src/boost/libs/interprocess/test/cached_adaptive_pool_test.cpp @@ -0,0 +1,73 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS +#include +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" +#include "vector_test.hpp" + +using namespace boost::interprocess; + +//We will work with wide characters for shared memory objects +//Alias an cached adaptive pool that allocates ints +typedef cached_adaptive_pool + + cached_node_allocator_t; + +typedef ipcdetail::cached_adaptive_pool_v1 + + cached_node_allocator_v1_t; + +namespace boost { +namespace interprocess { + +//Explicit instantiations to catch compilation errors +template class cached_adaptive_pool; +template class cached_adaptive_pool; + +namespace ipcdetail { + +template class ipcdetail::cached_adaptive_pool_v1; +template class ipcdetail::cached_adaptive_pool_v1; + +}}} + +//Alias list types +typedef list MyShmList; +typedef list MyShmListV1; + +//Alias vector types +typedef vector MyShmVector; +typedef vector MyShmVectorV1; + +int main () +{ + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::vector_test()) + return 1; + + if(test::vector_test()) + return 1; + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/cached_node_allocator_test.cpp b/src/boost/libs/interprocess/test/cached_node_allocator_test.cpp new file mode 100644 index 00000000..8ffa0f0b --- /dev/null +++ b/src/boost/libs/interprocess/test/cached_node_allocator_test.cpp @@ -0,0 +1,67 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" +#include "vector_test.hpp" + +using namespace boost::interprocess; + +//Alias an integer node allocator type +typedef cached_node_allocator + + cached_node_allocator_t; +typedef ipcdetail::cached_node_allocator_v1 + + cached_node_allocator_v1_t; + +namespace boost { +namespace interprocess { + +//Explicit instantiations to catch compilation errors +template class cached_node_allocator; +template class cached_node_allocator; + +namespace ipcdetail { + +template class ipcdetail::cached_node_allocator_v1; +template class ipcdetail::cached_node_allocator_v1; + +}}} + +//Alias list types +typedef list MyShmList; +typedef list MyShmListV1; + +//Alias vector types +typedef vector MyShmVector; +typedef vector MyShmVectorV1; + +int main () +{ + if(test::list_test()) + return 1; + if(test::list_test()) + return 1; + if(test::vector_test()) + return 1; + if(test::vector_test()) + return 1; + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/check_equal_containers.hpp b/src/boost/libs/interprocess/test/check_equal_containers.hpp new file mode 100644 index 00000000..423a84cd --- /dev/null +++ b/src/boost/libs/interprocess/test/check_equal_containers.hpp @@ -0,0 +1,92 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TEST_CHECK_EQUAL_CONTAINERS_HPP +#define BOOST_INTERPROCESS_TEST_CHECK_EQUAL_CONTAINERS_HPP + +#include +// container/detail +#include +#include + +namespace boost{ +namespace interprocess{ +namespace test{ + +template< class T1, class T2> +bool CheckEqual( const T1 &t1, const T2 &t2 + , typename boost::container::dtl::enable_if_c + ::value && + !boost::container::dtl::is_pair::value + >::type* = 0) +{ return t1 == t2; } + +template< class Pair1, class Pair2> +bool CheckEqual( const Pair1 &pair1, const Pair2 &pair2 + , typename boost::container::dtl::enable_if_c + ::value && + boost::container::dtl::is_pair::value + >::type* = 0) +{ + return CheckEqual(pair1.first, pair2.first) && CheckEqual(pair1.second, pair2.second); +} + + +//Function to check if both containers are equal +template +bool CheckEqualContainers(MyShmCont *shmcont, MyStdCont *stdcont) +{ + if(shmcont->size() != stdcont->size()) + return false; + + typename MyShmCont::iterator itshm(shmcont->begin()), itshmend(shmcont->end()); + typename MyStdCont::iterator itstd(stdcont->begin()); + typename MyStdCont::size_type dist = + typename MyStdCont::size_type(boost::container::iterator_distance(itshm, itshmend)); + if(dist != shmcont->size()){ + return false; + } + std::size_t i = 0; + for(; itshm != itshmend; ++itshm, ++itstd, ++i){ + if(!CheckEqual(*itstd, *itshm)) + return false; + } + return true; +} + +template +bool CheckEqualPairContainers(MyShmCont *shmcont, MyStdCont *stdcont) +{ + if(shmcont->size() != stdcont->size()) + return false; + + typedef typename MyShmCont::key_type key_type; + typedef typename MyShmCont::mapped_type mapped_type; + + typename MyShmCont::iterator itshm(shmcont->begin()), itshmend(shmcont->end()); + typename MyStdCont::iterator itstd(stdcont->begin()); + for(; itshm != itshmend; ++itshm, ++itstd){ + if(itshm->first != key_type(itstd->first)) + return false; + + if(itshm->second != mapped_type(itstd->second)) + return false; + } + return true; +} +} //namespace test{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_TEST_CHECK_EQUAL_CONTAINERS_HPP diff --git a/src/boost/libs/interprocess/test/condition_any_test.cpp b/src/boost/libs/interprocess/test/condition_any_test.cpp new file mode 100644 index 00000000..8349fed3 --- /dev/null +++ b/src/boost/libs/interprocess/test/condition_any_test.cpp @@ -0,0 +1,34 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include "condition_test_template.hpp" + +using namespace boost::interprocess; + +int main () +{ + if(!test::do_test_condition()) + return 1; + if(!test::do_test_condition()) + return 1; + if(!test::do_test_condition()) + return 1; + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/condition_test.cpp b/src/boost/libs/interprocess/test/condition_test.cpp new file mode 100644 index 00000000..089c0a6f --- /dev/null +++ b/src/boost/libs/interprocess/test/condition_test.cpp @@ -0,0 +1,40 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "condition_test_template.hpp" + +#if defined(BOOST_INTERPROCESS_WINDOWS) +#include +#include +#include +#include +#endif + +using namespace boost::interprocess; + +int main () +{ + #if defined(BOOST_INTERPROCESS_WINDOWS) + if(!test::do_test_condition()) + return 1; + if(!test::do_test_condition()) + return 1; + #endif + if(!test::do_test_condition()) + return 1; + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/condition_test_template.hpp b/src/boost/libs/interprocess/test/condition_test_template.hpp new file mode 100644 index 00000000..03e80ba4 --- /dev/null +++ b/src/boost/libs/interprocess/test/condition_test_template.hpp @@ -0,0 +1,401 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP +#define BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP + +#include +#include +#include +#include "boost_interprocess_check.hpp" +#include +#include +#include + +namespace boost{ +namespace interprocess{ +namespace test { + +boost::posix_time::ptime ptime_delay(int secs) +{ + return microsec_clock::universal_time() + + boost::posix_time::time_duration(0, 0, secs); +} + +template +class binder +{ +public: + binder(const F& f, const T& p) + : func(f), param(p) { } + void operator()() const { func(param); } + +private: + F func; + T param; +}; + +template +binder bind_function(F func, T param) +{ + return binder(func, param); +} + +template +struct condition_test_data +{ + condition_test_data() : notified(0), awoken(0) { } + + ~condition_test_data() + {} + + Mutex mutex; + Condition condition; + int notified; + int awoken; +}; + +template +void condition_test_thread(condition_test_data* data) +{ + boost::interprocess::scoped_lock + lock(data->mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + while (!(data->notified > 0)) + data->condition.wait(lock); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + data->awoken++; +} + +struct cond_predicate +{ + cond_predicate(int& var, int val) : _var(var), _val(val) { } + + bool operator()() { return _var == _val; } + + int& _var; + int _val; +}; + +template +void condition_test_waits(condition_test_data* data) +{ + boost::interprocess::scoped_lock + lock(data->mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + + // Test wait. + while (data->notified != 1) + data->condition.wait(lock); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data->notified == 1); + data->awoken++; + data->condition.notify_one(); + + // Test predicate wait. + data->condition.wait(lock, cond_predicate(data->notified, 2)); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data->notified == 2); + data->awoken++; + data->condition.notify_one(); + + // Test timed_wait. + while (data->notified != 3) + data->condition.timed_wait(lock, ptime_delay(5)); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data->notified == 3); + data->awoken++; + data->condition.notify_one(); + + // Test predicate timed_wait. + cond_predicate pred(data->notified, 4); + bool ret = data->condition.timed_wait(lock, ptime_delay(5), pred); + BOOST_INTERPROCESS_CHECK(ret);(void)ret; + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(pred()); + BOOST_INTERPROCESS_CHECK(data->notified == 4); + data->awoken++; + data->condition.notify_one(); +} + +template +void do_test_condition_notify_one() +{ + condition_test_data data; + + boost::interprocess::ipcdetail::OS_thread_t thread; + boost::interprocess::ipcdetail::thread_launch(thread, bind_function(&condition_test_thread, &data)); + //Make sure thread is blocked + boost::interprocess::ipcdetail::thread_sleep(1000); + { + boost::interprocess::scoped_lock + lock(data.mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + data.notified++; + data.condition.notify_one(); + } + + boost::interprocess::ipcdetail::thread_join(thread); + BOOST_INTERPROCESS_CHECK(data.awoken == 1); +} + +template +void do_test_condition_notify_all() +{ + const int NUMTHREADS = 3; + + boost::interprocess::ipcdetail::OS_thread_t thgroup[NUMTHREADS]; + condition_test_data data; + + for(int i = 0; i< NUMTHREADS; ++i){ + boost::interprocess::ipcdetail::thread_launch(thgroup[i], bind_function(&condition_test_thread, &data)); + } + + //Make sure all threads are blocked + boost::interprocess::ipcdetail::thread_sleep(1000); + { + boost::interprocess::scoped_lock + lock(data.mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + data.notified++; + } + data.condition.notify_all(); + + for(int i = 0; i< NUMTHREADS; ++i){ + boost::interprocess::ipcdetail::thread_join(thgroup[i]); + } + BOOST_INTERPROCESS_CHECK(data.awoken == NUMTHREADS); +} + +template +void do_test_condition_waits() +{ + condition_test_data data; + boost::interprocess::ipcdetail::OS_thread_t thread; + boost::interprocess::ipcdetail::thread_launch(thread, bind_function(&condition_test_waits, &data)); + + { + boost::interprocess::scoped_lock + lock(data.mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + + boost::interprocess::ipcdetail::thread_sleep(1000); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 1) + data.condition.wait(lock); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 1); + + boost::interprocess::ipcdetail::thread_sleep(1000); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 2) + data.condition.wait(lock); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 2); + + boost::interprocess::ipcdetail::thread_sleep(1000); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 3) + data.condition.wait(lock); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 3); + + boost::interprocess::ipcdetail::thread_sleep(1000); + data.notified++; + data.condition.notify_one(); + while (data.awoken != 4) + data.condition.wait(lock); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 4); + } + + boost::interprocess::ipcdetail::thread_join(thread); + BOOST_INTERPROCESS_CHECK(data.awoken == 4); +} +/* +//Message queue simulation test +template +inline Condition &cond_empty() +{ + static Condition cond_empty; + return cond_empty; +} + +template +inline Condition &cond_full() +{ + static Condition cond_full; + return cond_full; +} + + +template +inline Mutex &mutex() +{ + static Mutex mut; + return mut; +} +*/ +static volatile int count = 0; +static volatile int waiting_readers = 0; +static volatile int waiting_writer = 0; +const int queue_size = 3; +const int thread_factor = 10; +const int NumThreads = thread_factor*queue_size; + +//Function that removes items from queue +template +struct condition_func +{ + condition_func(Condition &cond_full, Condition &cond_empty, Mutex &mutex) + : cond_full_(cond_full), cond_empty_(cond_empty), mutex_(mutex) + {} + + void operator()() + { + boost::interprocess::scoped_locklock(mutex_); + while(count == 0){ + ++waiting_readers; + cond_empty_.wait(lock); + --waiting_readers; + } + --count; + if(waiting_writer) + cond_full_.notify_one(); + } + Condition &cond_full_; + Condition &cond_empty_; + Mutex &mutex_; +}; + +//Queue functions +template +void do_test_condition_queue_notify_one(void) +{ + //Force mutex and condition creation + Condition cond_empty; + Condition cond_full; + Mutex mutex; + + //Create threads that will decrease count + { + //Initialize counters + count = 0; + waiting_readers = 0; + waiting_writer = 0; + + boost::interprocess::ipcdetail::OS_thread_t thgroup[NumThreads]; + for(int i = 0; i< NumThreads; ++i){ + condition_func func(cond_full, cond_empty, mutex); + boost::interprocess::ipcdetail::thread_launch(thgroup[i], func); + } + + //Add 20 elements one by one in the queue simulation + //The sender will block if it fills the queue + for(int i = 0; i < NumThreads; ++i){ + boost::interprocess::scoped_lock lock(mutex); + while(count == queue_size){ + ++waiting_writer; + cond_full.wait(lock); + --waiting_writer; + } + count++; + + if(waiting_readers) + cond_empty.notify_one(); + } + for(int i = 0; i< NumThreads; ++i){ + boost::interprocess::ipcdetail::thread_join(thgroup[i]); + } + BOOST_INTERPROCESS_CHECK(count == 0); + BOOST_INTERPROCESS_CHECK(waiting_readers == 0); + BOOST_INTERPROCESS_CHECK(waiting_writer == 0); + } +} + +//Queue functions +template +void do_test_condition_queue_notify_all(void) +{ + //Force mutex and condition creation + Condition cond_empty; + Condition cond_full; + Mutex mutex; + + //Create threads that will decrease count + { + //Initialize counters + count = 0; + waiting_readers = 0; + waiting_writer = 0; + + boost::interprocess::ipcdetail::OS_thread_t thgroup[NumThreads]; + for(int i = 0; i< NumThreads; ++i){ + condition_func func(cond_full, cond_empty, mutex); + boost::interprocess::ipcdetail::thread_launch(thgroup[i], func); + } + + //Fill queue to the max size and notify all several times + for(int i = 0; i < NumThreads; ++i){ + boost::interprocess::scoped_locklock(mutex); + while(count == queue_size){ + ++waiting_writer; + cond_full.wait(lock); + --waiting_writer; + } + count++; + + if(waiting_readers) + cond_empty.notify_all(); + } + for(int i = 0; i< NumThreads; ++i){ + boost::interprocess::ipcdetail::thread_join(thgroup[i]); + } + BOOST_INTERPROCESS_CHECK(count == 0); + BOOST_INTERPROCESS_CHECK(waiting_readers == 0); + BOOST_INTERPROCESS_CHECK(waiting_writer == 0); + } +} + +template +bool do_test_condition() +{ + std::cout << "do_test_condition_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; + do_test_condition_notify_one(); + std::cout << "do_test_condition_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; + do_test_condition_notify_all(); + std::cout << "do_test_condition_waits<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; + do_test_condition_waits(); + std::cout << "do_test_condition_queue_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; + do_test_condition_queue_notify_one(); + std::cout << "do_test_condition_queue_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; + do_test_condition_queue_notify_all(); + return true; +} + +} //namespace test +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP diff --git a/src/boost/libs/interprocess/test/data_test.cpp b/src/boost/libs/interprocess/test/data_test.cpp new file mode 100644 index 00000000..450031b2 --- /dev/null +++ b/src/boost/libs/interprocess/test/data_test.cpp @@ -0,0 +1,97 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include "print_container.hpp" +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +int main () +{ + const int memsize = 65536; + std::string process_name; + test::get_process_id_name(process_name); + const char *const shMemName = process_name.c_str(); + + try{ + shared_memory_object::remove(shMemName); + + //Create shared memory + managed_shared_memory segment(create_only, shMemName, memsize); + + //STL compatible allocator object, uses allocate(), deallocate() functions + typedef allocator + shmem_allocator_int_t; + + const shmem_allocator_int_t myallocator (segment.get_segment_manager()); + + const int max = 100; + void *array[max]; + + const char *allocName = "testAllocation"; + + typedef boost::interprocess::vector MyVect; + + //---- ALLOC, NAMED_ALLOC, NAMED_NEW TEST ----// + { + int i; + //Let's allocate some memory + for(i = 0; i < max; ++i){ + array[i] = segment.allocate(i+1); + } + + //Deallocate allocated memory + for(i = 0; i < max; ++i){ + segment.deallocate(array[i]); + } + + bool res; + + MyVect *shmem_vect; + + //Construct and find + shmem_vect = segment.construct (allocName) (myallocator); + res = (shmem_vect == segment.find(allocName).first); + if(!res) + return 1; + //Destroy and check it is not present + segment.destroy (allocName); + res = (0 == segment.find(allocName).first); + if(!res) + return 1; + + //Construct, dump to a file + shmem_vect = segment.construct (allocName) (myallocator); + + if(shmem_vect != segment.find(allocName).first) + return 1; + //Destroy and check it is not present + segment.destroy (allocName); + res = (0 == segment.find(allocName).first); + if(!res) + return 1; + } + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/deque_test.cpp b/src/boost/libs/interprocess/test/deque_test.cpp new file mode 100644 index 00000000..4b3ee3cd --- /dev/null +++ b/src/boost/libs/interprocess/test/deque_test.cpp @@ -0,0 +1,312 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "print_container.hpp" +#include "check_equal_containers.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include +#include "allocator_v1.hpp" +#include +#include +#include +#include +#include +#include "get_process_id_name.hpp" +#include "emplace_test.hpp" + +/////////////////////////////////////////////////////////////////// +// // +// This example repeats the same operations with std::deque and // +// shmem_deque using the node allocator // +// and compares the values of both containers // +// // +/////////////////////////////////////////////////////////////////// + +using namespace boost::interprocess; + +//Function to check if both sets are equal +template +bool copyable_only(V1 *, V2 *, ipcdetail::false_type) +{ + return true; +} + +//Function to check if both sets are equal +template +bool copyable_only(V1 *shmdeque, V2 *stddeque, ipcdetail::true_type) +{ + typedef typename V1::value_type IntType; + std::size_t size = shmdeque->size(); + stddeque->insert(stddeque->end(), 50, 1); + shmdeque->insert(shmdeque->end(), 50, IntType(1)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + { + IntType move_me(1); + stddeque->insert(stddeque->begin()+size/2, 50, 1); + shmdeque->insert(shmdeque->begin()+size/2, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + { + IntType move_me(2); + shmdeque->assign(shmdeque->size()/2, boost::move(move_me)); + stddeque->assign(stddeque->size()/2, 2); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + { + IntType move_me(1); + stddeque->clear(); + shmdeque->clear(); + stddeque->insert(stddeque->begin(), 50, 1); + shmdeque->insert(shmdeque->begin(), 50, boost::move(move_me)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + stddeque->insert(stddeque->begin()+20, 50, 1); + shmdeque->insert(shmdeque->begin()+20, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + stddeque->insert(stddeque->begin()+20, 20, 1); + shmdeque->insert(shmdeque->begin()+20, 20, boost::move(move_me)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + { + IntType move_me(1); + stddeque->clear(); + shmdeque->clear(); + stddeque->insert(stddeque->end(), 50, 1); + shmdeque->insert(shmdeque->end(), 50, boost::move(move_me)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + stddeque->insert(stddeque->end()-20, 50, 1); + shmdeque->insert(shmdeque->end()-20, 50, boost::move(move_me)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + stddeque->insert(stddeque->end()-20, 20, 1); + shmdeque->insert(shmdeque->end()-20, 20, boost::move(move_me)); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + + return true; +} + + +template class AllocatorType > +bool do_test() +{ + //Customize managed_shared_memory class + typedef basic_managed_shared_memory + , + rbtree_best_fit, + //flat_map_index + iset_index + > my_managed_shared_memory; + + //Alias AllocatorType type + typedef AllocatorType + shmem_allocator_t; + + //Alias deque types + typedef deque MyShmDeque; + typedef std::deque MyStdDeque; + const int Memsize = 65536; + const char *const shMemName = test::get_process_id_name(); + const int max = 100; + + /*try*/{ + shared_memory_object::remove(shMemName); + + //Create shared memory + my_managed_shared_memory segment(create_only, shMemName, Memsize); + + segment.reserve_named_objects(100); + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyShmDeque *shmdeque = segment.template construct("MyShmDeque") + (segment.get_segment_manager()); + + MyStdDeque *stddeque = new MyStdDeque; + + /*try*/{ + //Compare several shared memory deque operations with std::deque + for(int i = 0; i < max*50; ++i){ + IntType move_me(i); + shmdeque->insert(shmdeque->end(), boost::move(move_me)); + stddeque->insert(stddeque->end(), i); + shmdeque->insert(shmdeque->end(), IntType(i)); + stddeque->insert(stddeque->end(), int(i)); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + shmdeque->clear(); + stddeque->clear(); + + for(int i = 0; i < max*50; ++i){ + IntType move_me(i); + shmdeque->push_back(boost::move(move_me)); + stddeque->push_back(i); + shmdeque->push_back(IntType(i)); + stddeque->push_back(i); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + shmdeque->clear(); + stddeque->clear(); + + for(int i = 0; i < max*50; ++i){ + IntType move_me(i); + shmdeque->push_front(boost::move(move_me)); + stddeque->push_front(i); + shmdeque->push_front(IntType(i)); + stddeque->push_front(int(i)); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + typename MyShmDeque::iterator it; + typename MyShmDeque::const_iterator cit = it; + (void)cit; + + shmdeque->erase(shmdeque->begin()++); + stddeque->erase(stddeque->begin()++); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + shmdeque->erase(shmdeque->begin()); + stddeque->erase(stddeque->begin()); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + { + //Initialize values + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me (-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + + shmdeque->insert(shmdeque->end() + ,::boost::make_move_iterator(&aux_vect[0]) + ,::boost::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->end(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + for(int i = 0, j = static_cast(shmdeque->size()); i < j; ++i){ + shmdeque->erase(shmdeque->begin()); + stddeque->erase(stddeque->begin()); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + shmdeque->insert(shmdeque->begin() + ,::boost::make_move_iterator(&aux_vect[0]) + ,::boost::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->begin(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + + if(!copyable_only(shmdeque, stddeque + ,ipcdetail::bool_::value>())){ + return false; + } + + shmdeque->erase(shmdeque->begin()); + stddeque->erase(stddeque->begin()); + + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + for(int i = 0; i < max; ++i){ + IntType move_me(i); + shmdeque->insert(shmdeque->begin(), boost::move(move_me)); + stddeque->insert(stddeque->begin(), i); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + //Test insertion from list + { + std::list l(50, int(1)); + shmdeque->insert(shmdeque->begin(), l.begin(), l.end()); + stddeque->insert(stddeque->begin(), l.begin(), l.end()); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + shmdeque->assign(l.begin(), l.end()); + stddeque->assign(l.begin(), l.end()); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + } + + shmdeque->resize(100); + stddeque->resize(100); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + + shmdeque->resize(200); + stddeque->resize(200); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + + segment.template destroy("MyShmDeque"); + delete stddeque; + segment.shrink_to_fit_indexes(); + + if(!segment.all_memory_deallocated()) + return false; + }/* + catch(std::exception &ex){ + std::cout << ex.what() << std::endl; + return false; + }*/ + + std::cout << std::endl << "Test OK!" << std::endl; + }/* + catch(...){ + shared_memory_object::remove(shMemName); + throw; + }*/ + shared_memory_object::remove(shMemName); + return true; +} + +int main () +{ + if(!do_test()) + return 1; + + if(!do_test()) + return 1; + + if(!do_test()) + return 1; + + if(!do_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); + + if(!boost::interprocess::test::test_emplace + < deque, Options>()) + return 1; + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/dummy_test_allocator.hpp b/src/boost/libs/interprocess/test/dummy_test_allocator.hpp new file mode 100644 index 00000000..42e5403e --- /dev/null +++ b/src/boost/libs/interprocess/test/dummy_test_allocator.hpp @@ -0,0 +1,149 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DUMMY_TEST_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_DUMMY_TEST_ALLOCATOR_HPP + +#if defined (_MSC_VER) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an allocator to test expand capabilities + +namespace boost { +namespace interprocess { +namespace test { + +//This allocator just allows two allocations. The first one will return +//mp_buffer + m_offset configured in the constructor. The second one +//will return mp_buffer. +template +class dummy_test_allocator +{ + private: + typedef dummy_test_allocator self_t; + typedef void * aux_pointer_t; + typedef const void * cvoid_ptr; + + template + dummy_test_allocator& operator=(const dummy_test_allocator&); + + dummy_test_allocator& operator=(const dummy_test_allocator&); + + public: + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + +// typedef boost::interprocess::version_type version; + + template + struct rebind + { typedef dummy_test_allocator other; }; + + //!Default constructor. Never throws + dummy_test_allocator() + {} + + //!Constructor from other dummy_test_allocator. Never throws + dummy_test_allocator(const dummy_test_allocator &) + {} + + //!Constructor from related dummy_test_allocator. Never throws + template + dummy_test_allocator(const dummy_test_allocator &) + {} + + pointer address(reference value) + { return pointer(addressof(value)); } + + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } + + pointer allocate(size_type, cvoid_ptr = 0) + { return 0; } + + void deallocate(const pointer &, size_type) + { } + + template + void construct(pointer, const Convertible &) + {} + + void destroy(pointer) + {} + + size_type max_size() const + { return 0; } + + friend void swap(self_t &, self_t &) + {} + + //Experimental version 2 dummy_test_allocator functions + + pointer allocation_command(boost::interprocess::allocation_type, + size_type, size_type &, pointer &) + { return pointer(); } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. + size_type size(const pointer &) const + { return 0; } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { return pointer(); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &) + {} +}; + +//!Equality test for same type of dummy_test_allocator +template inline +bool operator==(const dummy_test_allocator &, + const dummy_test_allocator &) +{ return false; } + +//!Inequality test for same type of dummy_test_allocator +template inline +bool operator!=(const dummy_test_allocator &, + const dummy_test_allocator &) +{ return true; } + +} //namespace test { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DUMMY_TEST_ALLOCATOR_HPP + diff --git a/src/boost/libs/interprocess/test/emplace_test.hpp b/src/boost/libs/interprocess/test/emplace_test.hpp new file mode 100644 index 00000000..71cb2882 --- /dev/null +++ b/src/boost/libs/interprocess/test/emplace_test.hpp @@ -0,0 +1,627 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_TEST_EMPLACE_TEST_HPP +#define BOOST_INTERPROCESS_TEST_EMPLACE_TEST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include //make_unsigned, alignment_of + +namespace boost{ +namespace interprocess{ +namespace test{ + +class EmplaceInt +{ + private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(EmplaceInt) + + public: + EmplaceInt() + : a_(0), b_(0), c_(0), d_(0), e_(0) + {} + EmplaceInt(int a, int b = 0, int c = 0, int d = 0, int e = 0) + : a_(a), b_(b), c_(c), d_(d), e_(e) + {} + + EmplaceInt(BOOST_RV_REF(EmplaceInt) o) + : a_(o.a_), b_(o.b_), c_(o.c_), d_(o.d_), e_(o.e_) + {} + + EmplaceInt& operator=(BOOST_RV_REF(EmplaceInt) o) + { + this->a_ = o.a_; + this->b_ = o.b_; + this->c_ = o.c_; + this->d_ = o.d_; + this->e_ = o.e_; + return *this; + } + + friend bool operator==(const EmplaceInt &l, const EmplaceInt &r) + { + return l.a_ == r.a_ && + l.b_ == r.b_ && + l.c_ == r.c_ && + l.d_ == r.d_ && + l.e_ == r.e_; + } + + friend bool operator<(const EmplaceInt &l, const EmplaceInt &r) + { return l.sum() < r.sum(); } + + friend bool operator>(const EmplaceInt &l, const EmplaceInt &r) + { return l.sum() > r.sum(); } + + friend bool operator!=(const EmplaceInt &l, const EmplaceInt &r) + { return !(l == r); } + + friend std::ostream &operator <<(std::ostream &os, const EmplaceInt &v) + { + os << "EmplaceInt: " << v.a_ << ' ' << v.b_ << ' ' << v.c_ << ' ' << v.d_ << ' ' << v.e_; + return os; + } + + //private: + int sum() const + { return this->a_ + this->b_ + this->c_ + this->d_ + this->e_; } + + int a_, b_, c_, d_, e_; + int padding[6]; +}; + + +} //namespace test { + +namespace test { + +enum EmplaceOptions{ + EMPLACE_BACK = 1 << 0, + EMPLACE_FRONT = 1 << 1, + EMPLACE_BEFORE = 1 << 2, + EMPLACE_AFTER = 1 << 3, + EMPLACE_ASSOC = 1 << 4, + EMPLACE_HINT = 1 << 5, + EMPLACE_ASSOC_PAIR = 1 << 6, + EMPLACE_HINT_PAIR = 1 << 7 +}; + +template +bool test_expected_container(const Container &ec, const EmplaceInt *Expected, unsigned int only_first_n) +{ + typedef typename Container::const_iterator const_iterator; + const_iterator itb(ec.begin()), ite(ec.end()); + unsigned int cur = 0; + if(only_first_n > ec.size()){ + return false; + } + for(; itb != ite && only_first_n--; ++itb, ++cur){ + const EmplaceInt & cr = *itb; + if(cr != Expected[cur]){ + return false; + } + } + return true; +} + +template +bool test_expected_container(const Container &ec, const std::pair *Expected, unsigned int only_first_n) +{ + typedef typename Container::const_iterator const_iterator; + const_iterator itb(ec.begin()), ite(ec.end()); + unsigned int cur = 0; + if(only_first_n > ec.size()){ + return false; + } + for(; itb != ite && only_first_n--; ++itb, ++cur){ + if(itb->first != Expected[cur].first){ + std::cout << "Error in first: " << itb->first << ' ' << Expected[cur].first << std::endl; + return false; + + } + else if(itb->second != Expected[cur].second){ + std::cout << "Error in second: " << itb->second << ' ' << Expected[cur].second << std::endl; + return false; + } + } + return true; +} + +static EmplaceInt expected [10]; + +typedef std::pair EmplaceIntPair; +static boost::container::dtl::aligned_storage::type pair_storage; + +static EmplaceIntPair* initialize_emplace_int_pair() +{ + EmplaceIntPair* ret = reinterpret_cast(&pair_storage); + for(unsigned int i = 0; i != 10; ++i){ + new(&ret->first)EmplaceInt(); + new(&ret->second)EmplaceInt(); + } + return ret; +} + +static EmplaceIntPair * expected_pair = initialize_emplace_int_pair(); + + +template +bool test_emplace_back(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_back." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + Container c; + c.emplace_back(); + if(!test_expected_container(c, &expected[0], 1)) + return false; + c.emplace_back(1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace_back(1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + c.emplace_back(1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + c.emplace_back(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + c.emplace_back(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + + return true; +} + +template +bool test_emplace_back(ipcdetail::false_) +{ return true; } + +template +bool test_emplace_front(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_front." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(1, 2, 3, 4, 5); + new(&expected [1]) EmplaceInt(1, 2, 3, 4); + new(&expected [2]) EmplaceInt(1, 2, 3); + new(&expected [3]) EmplaceInt(1, 2); + new(&expected [4]) EmplaceInt(1); + new(&expected [5]) EmplaceInt(); + Container c; + c.emplace_front(); + if(!test_expected_container(c, &expected[0] + 5, 1)) + return false; + c.emplace_front(1); + if(!test_expected_container(c, &expected[0] + 4, 2)) + return false; + c.emplace_front(1, 2); + if(!test_expected_container(c, &expected[0] + 3, 3)) + return false; + c.emplace_front(1, 2, 3); + if(!test_expected_container(c, &expected[0] + 2, 4)) + return false; + c.emplace_front(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0] + 1, 5)) + return false; + c.emplace_front(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0] + 0, 6)) + return false; + } + return true; +} + +template +bool test_emplace_front(ipcdetail::false_) +{ return true; } + +template +bool test_emplace_before(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_before." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(); + Container c; + c.emplace(c.cend(), 1); + c.emplace(c.cbegin()); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace(c.cend()); + if(!test_expected_container(c, &expected[0], 3)) + return false; + } + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + //emplace_front-like + Container c; + c.emplace(c.cbegin(), 1, 2, 3, 4, 5); + c.emplace(c.cbegin(), 1, 2, 3, 4); + c.emplace(c.cbegin(), 1, 2, 3); + c.emplace(c.cbegin(), 1, 2); + c.emplace(c.cbegin(), 1); + c.emplace(c.cbegin()); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_back-like + typename Container::const_iterator i = c.emplace(c.cend()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + i = c.emplace(++i, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + i = c.emplace(++i, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + i = c.emplace(++i, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + i = c.emplace(++i, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + i = c.emplace(++i, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace in the middle + c.emplace(c.cbegin()); + i = c.emplace(c.cend(), 1, 2, 3, 4, 5); + i = c.emplace(i, 1, 2, 3, 4); + i = c.emplace(i, 1, 2, 3); + i = c.emplace(i, 1, 2); + i = c.emplace(i, 1); + + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_before(ipcdetail::false_) +{ return true; } + +template +bool test_emplace_after(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_after." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(); + Container c; + typename Container::const_iterator i = c.emplace_after(c.cbefore_begin(), 1); + c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace_after(i); + if(!test_expected_container(c, &expected[0], 3)) + return false; + } + { + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + //emplace_front-like + Container c; + c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4, 5); + c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4); + c.emplace_after(c.cbefore_begin(), 1, 2, 3); + c.emplace_after(c.cbefore_begin(), 1, 2); + c.emplace_after(c.cbefore_begin(), 1); + c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_back-like + typename Container::const_iterator i = c.emplace_after(c.cbefore_begin()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + i = c.emplace_after(i, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + i = c.emplace_after(i, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + i = c.emplace_after(i, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + i = c.emplace_after(i, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + i = c.emplace_after(i, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + c.clear(); + //emplace_after in the middle + i = c.emplace_after(c.cbefore_begin()); + c.emplace_after(i, 1, 2, 3, 4, 5); + c.emplace_after(i, 1, 2, 3, 4); + c.emplace_after(i, 1, 2, 3); + c.emplace_after(i, 1, 2); + c.emplace_after(i, 1); + + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_after(ipcdetail::false_) +{ return true; } + +template +bool test_emplace_assoc(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_assoc." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + { + Container c; + c.emplace(); + if(!test_expected_container(c, &expected[0], 1)) + return false; + c.emplace(1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + c.emplace(1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + c.emplace(1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + c.emplace(1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + c.emplace(1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + return true; +} + +template +bool test_emplace_assoc(ipcdetail::false_) +{ return true; } + +template +bool test_emplace_hint(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_hint." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected [0]) EmplaceInt(); + new(&expected [1]) EmplaceInt(1); + new(&expected [2]) EmplaceInt(1, 2); + new(&expected [3]) EmplaceInt(1, 2, 3); + new(&expected [4]) EmplaceInt(1, 2, 3, 4); + new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5); + + { + Container c; + typename Container::const_iterator it; + it = c.emplace_hint(c.begin()); + if(!test_expected_container(c, &expected[0], 1)) + return false; + it = c.emplace_hint(it, 1); + if(!test_expected_container(c, &expected[0], 2)) + return false; + it = c.emplace_hint(it, 1, 2); + if(!test_expected_container(c, &expected[0], 3)) + return false; + it = c.emplace_hint(it, 1, 2, 3); + if(!test_expected_container(c, &expected[0], 4)) + return false; + it = c.emplace_hint(it, 1, 2, 3, 4); + if(!test_expected_container(c, &expected[0], 5)) + return false; + it = c.emplace_hint(it, 1, 2, 3, 4, 5); + if(!test_expected_container(c, &expected[0], 6)) + return false; + } + + return true; +} + +template +bool test_emplace_hint(ipcdetail::false_) +{ return true; } + +template +bool test_emplace_assoc_pair(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_assoc_pair." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected_pair[0].first) EmplaceInt(); + new(&expected_pair[0].second) EmplaceInt(); + new(&expected_pair[1].first) EmplaceInt(1); + new(&expected_pair[1].second) EmplaceInt(); + new(&expected_pair[2].first) EmplaceInt(2); + new(&expected_pair[2].second) EmplaceInt(2); +// new(&expected_pair[3].first) EmplaceInt(3); +// new(&expected_pair[3].second) EmplaceInt(2, 3); +// new(&expected_pair[4].first) EmplaceInt(4); +// new(&expected_pair[4].second) EmplaceInt(2, 3, 4); +// new(&expected_pair[5].first) EmplaceInt(5); +// new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5); + { //piecewise construct missing + /* + Container c; + c.emplace(); + if(!test_expected_container(c, &expected_pair[0], 1)){ + std::cout << "Error after c.emplace();\n"; + return false; + } + c.emplace(1); + if(!test_expected_container(c, &expected_pair[0], 2)){ + std::cout << "Error after c.emplace(1);\n"; + return false; + } + c.emplace(2, 2); + if(!test_expected_container(c, &expected_pair[0], 3)){ + std::cout << "Error after c.emplace(2, 2);\n"; + return false; + } + c.emplace(3, 2, 3); + if(!test_expected_container(c, &expected_pair[0], 4)){ + std::cout << "Error after c.emplace(3, 2, 3);\n"; + return false; + } + c.emplace(4, 2, 3, 4); + if(!test_expected_container(c, &expected_pair[0], 5)){ + std::cout << "Error after c.emplace(4, 2, 3, 4);\n"; + return false; + } + c.emplace(5, 2, 3, 4, 5); + if(!test_expected_container(c, &expected_pair[0], 6)){ + std::cout << "Error after c.emplace(5, 2, 3, 4, 5);\n"; + return false; + }*/ + } + return true; +} + +template +bool test_emplace_assoc_pair(ipcdetail::false_) +{ return true; } + +template +bool test_emplace_hint_pair(ipcdetail::true_) +{ + std::cout << "Starting test_emplace_hint_pair." << std::endl << " Class: " + << typeid(Container).name() << std::endl; + + new(&expected_pair[0].first) EmplaceInt(); + new(&expected_pair[0].second) EmplaceInt(); + new(&expected_pair[1].first) EmplaceInt(1); + new(&expected_pair[1].second) EmplaceInt(); + new(&expected_pair[2].first) EmplaceInt(2); + new(&expected_pair[2].second) EmplaceInt(2);/* + new(&expected_pair[3].first) EmplaceInt(3); + new(&expected_pair[3].second) EmplaceInt(2, 3); + new(&expected_pair[4].first) EmplaceInt(4); + new(&expected_pair[4].second) EmplaceInt(2, 3, 4); + new(&expected_pair[5].first) EmplaceInt(5); + new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5);*/ + {/* + Container c; + typename Container::const_iterator it; + it = c.emplace_hint(c.begin()); + if(!test_expected_container(c, &expected_pair[0], 1)){ + std::cout << "Error after c.emplace(1);\n"; + return false; + } + it = c.emplace_hint(it, 1); + if(!test_expected_container(c, &expected_pair[0], 2)){ + std::cout << "Error after c.emplace(it, 1);\n"; + return false; + } + it = c.emplace_hint(it, 2, 2); + if(!test_expected_container(c, &expected_pair[0], 3)){ + std::cout << "Error after c.emplace(it, 2, 2);\n"; + return false; + } + it = c.emplace_hint(it, 3, 2, 3); + if(!test_expected_container(c, &expected_pair[0], 4)){ + std::cout << "Error after c.emplace(it, 3, 2, 3);\n"; + return false; + } + it = c.emplace_hint(it, 4, 2, 3, 4); + if(!test_expected_container(c, &expected_pair[0], 5)){ + std::cout << "Error after c.emplace(it, 4, 2, 3, 4);\n"; + return false; + } + it = c.emplace_hint(it, 5, 2, 3, 4, 5); + if(!test_expected_container(c, &expected_pair[0], 6)){ + std::cout << "Error after c.emplace(it, 5, 2, 3, 4, 5);\n"; + return false; + }*/ + } + return true; +} + +template +bool test_emplace_hint_pair(ipcdetail::false_) +{ return true; } + +template +struct emplace_active +{ + static const bool value = (0 != (O & Mask)); + typedef ipcdetail::bool_ type; + operator type() const{ return type(); } +}; + +template +bool test_emplace() +{ + if(!test_emplace_back(emplace_active())) + return false; + if(!test_emplace_front(emplace_active())) + return false; + if(!test_emplace_before(emplace_active())) + return false; + if(!test_emplace_after(emplace_active())) + return false; + if(!test_emplace_assoc(emplace_active())) + return false; + if(!test_emplace_hint(emplace_active())) + return false; + if(!test_emplace_assoc_pair(emplace_active())) + return false; + if(!test_emplace_hint_pair(emplace_active())) + return false; + return true; +} + +} //namespace test{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_TEST_EMPLACE_TEST_HPP diff --git a/src/boost/libs/interprocess/test/enable_shared_from_this_test.cpp b/src/boost/libs/interprocess/test/enable_shared_from_this_test.cpp new file mode 100644 index 00000000..342e0a7e --- /dev/null +++ b/src/boost/libs/interprocess/test/enable_shared_from_this_test.cpp @@ -0,0 +1,97 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2002, 2003 Peter Dimov +// +// This file is the adaptation of shared_from_this_test.cpp from smart_ptr library +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +#include +#include +#include "get_process_id_name.hpp" + +// + +using namespace boost::interprocess; + +typedef allocator + v_allocator_t; + +struct X; + +typedef deleter x_deleter_t; + +struct X : + public enable_shared_from_this +{ +}; + +typedef shared_ptr v_shared_ptr; + + +template +void test_enable_shared_this(ManagedMemory &managed_mem) +{ + v_shared_ptr p(make_managed_shared_ptr + (managed_mem.template construct(anonymous_instance)(), managed_mem)); + + v_shared_ptr q = p->shared_from_this(); + BOOST_TEST(p == q); + BOOST_TEST(!(p < q) && !(q < p)); + + X v2(*p); + + try + { + //This should throw bad_weak_ptr + v_shared_ptr r = v2.shared_from_this(); + BOOST_ERROR("v2.shared_from_this() failed to throw"); + } + catch(boost::interprocess::bad_weak_ptr const &) + { + //This is the expected path + } + catch(...){ + BOOST_ERROR("v2.shared_from_this() threw an unexpected exception"); + } + + try + { + //This should not throw bad_weak_ptr + *p = X(); + v_shared_ptr r = p->shared_from_this(); + BOOST_TEST(p == r); + BOOST_TEST(!(p < r) && !(r < p)); + } + catch(boost::interprocess::bad_weak_ptr const &) + { + BOOST_ERROR("p->shared_from_this() threw bad_weak_ptr after *p = X()"); + } + catch(...) + { + BOOST_ERROR("p->shared_from_this() threw an unexpected exception after *p = X()"); + } +} + + +int main() +{ + std::string process_name; + test::get_process_id_name(process_name); + shared_memory_object::remove(process_name.c_str()); + managed_shared_memory shmem(create_only, process_name.c_str(), 65536); + test_enable_shared_this(shmem); + shared_memory_object::remove(process_name.c_str()); + return boost::report_errors(); +} + +#include diff --git a/src/boost/libs/interprocess/test/expand_bwd_test_allocator.hpp b/src/boost/libs/interprocess/test/expand_bwd_test_allocator.hpp new file mode 100644 index 00000000..7124c574 --- /dev/null +++ b/src/boost/libs/interprocess/test/expand_bwd_test_allocator.hpp @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_EXPAND_BWD_TEST_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_EXPAND_BWD_TEST_ALLOCATOR_HPP + +#if defined (_MSC_VER) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an allocator to test expand capabilities + +namespace boost { +namespace interprocess { +namespace test { + +//This allocator just allows two allocations. The first one will return +//mp_buffer + m_offset configured in the constructor. The second one +//will return mp_buffer. +template +class expand_bwd_test_allocator +{ + private: + typedef expand_bwd_test_allocator self_t; + typedef void * aux_pointer_t; + typedef const void * cvoid_ptr; + + template + expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&); + + expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&); + + public: + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef boost::interprocess::version_type version; + + //Dummy multiallocation chain + struct multiallocation_chain{}; + + template + struct rebind + { typedef expand_bwd_test_allocator other; }; + + //!Constructor from the segment manager. Never throws + expand_bwd_test_allocator(T *buf, size_type sz, difference_type offset) + : mp_buffer(buf), m_size(sz) + , m_offset(offset), m_allocations(0){ } + + //!Constructor from other expand_bwd_test_allocator. Never throws + expand_bwd_test_allocator(const expand_bwd_test_allocator &other) + : mp_buffer(other.mp_buffer), m_size(other.m_size) + , m_offset(other.m_offset), m_allocations(0){ } + + //!Constructor from related expand_bwd_test_allocator. Never throws + template + expand_bwd_test_allocator(const expand_bwd_test_allocator &other) + : mp_buffer(other.mp_buffer), m_size(other.m_size) + , m_offset(other.m_offset), m_allocations(0){ } + + pointer address(reference value) + { return pointer(addressof(value)); } + + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } + + pointer allocate(size_type , cvoid_ptr hint = 0) + { (void)hint; return 0; } + + void deallocate(const pointer &, size_type) + {} + + template + void construct(pointer ptr, const Convertible &value) + { new((void*)ptr) value_type(value); } + + void destroy(pointer ptr) + { (*ptr).~value_type(); } + + size_type max_size() const + { return m_size; } + + friend void swap(self_t &alloc1, self_t &alloc2) + { + ::boost::adl_move_swap(alloc1.mp_buffer, alloc2.mp_buffer); + ::boost::adl_move_swap(alloc1.m_size, alloc2.m_size); + ::boost::adl_move_swap(alloc1.m_offset, alloc2.m_offset); + } + + //Experimental version 2 expand_bwd_test_allocator functions + + pointer allocation_command(boost::interprocess::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) + { + (void)reuse; (void)command; + //This allocator only expands backwards! + assert(m_allocations == 0 || (command & boost::interprocess::expand_bwd)); + prefer_in_recvd_out_size = limit_size; + + if(m_allocations == 0){ + if((m_offset + limit_size) > m_size){ + assert(0); + } + ++m_allocations; + return mp_buffer + m_offset; + } + else if(m_allocations == 1){ + if(limit_size > m_size){ + assert(0); + } + ++m_allocations; + return mp_buffer; + } + else{ + assert(0); + throw std::bad_alloc(); + } + } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. + size_type size(const pointer &p) const + { (void)p; return m_size; } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { return this->allocate(1); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { return this->deallocate(p, 1); } + + pointer mp_buffer; + size_type m_size; + difference_type m_offset; + char m_allocations; +}; + +//!Equality test for same type of expand_bwd_test_allocator +template inline +bool operator==(const expand_bwd_test_allocator &, + const expand_bwd_test_allocator &) +{ return false; } + +//!Inequality test for same type of expand_bwd_test_allocator +template inline +bool operator!=(const expand_bwd_test_allocator &, + const expand_bwd_test_allocator &) +{ return true; } + +} //namespace test { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_EXPAND_BWD_TEST_ALLOCATOR_HPP + diff --git a/src/boost/libs/interprocess/test/expand_bwd_test_template.hpp b/src/boost/libs/interprocess/test/expand_bwd_test_template.hpp new file mode 100644 index 00000000..91d1146b --- /dev/null +++ b/src/boost/libs/interprocess/test/expand_bwd_test_template.hpp @@ -0,0 +1,269 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER +#define BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER + +#include +#include "expand_bwd_test_allocator.hpp" +#include +#include //std::equal +#include +#include + +namespace boost { namespace interprocess { namespace test { + +template +struct value_holder +{ + value_holder(T val) : m_value(val){} + value_holder(): m_value(0){} + ~value_holder(){ m_value = 0; } + bool operator == (const value_holder &other) const + { return m_value == other.m_value; } + bool operator != (const value_holder &other) const + { return m_value != other.m_value; } + + T m_value; +}; + +template +struct triple_value_holder +{ + triple_value_holder(T val) + : m_value1(val) + , m_value2(val) + , m_value3(val) + {} + + triple_value_holder() + : m_value1(0) + , m_value2(0) + , m_value3(0) + {} + + ~triple_value_holder() + { m_value1 = m_value2 = m_value3 = 0; } + + bool operator == (const triple_value_holder &other) const + { + return m_value1 == other.m_value1 + && m_value2 == other.m_value2 + && m_value3 == other.m_value3; + } + + bool operator != (const triple_value_holder &other) const + { + return m_value1 != other.m_value1 + || m_value2 != other.m_value2 + || m_value3 != other.m_value3; + } + + T m_value1; + T m_value2; + T m_value3; +}; + +typedef value_holder int_holder; +typedef triple_value_holder triple_int_holder; + + + +//Function to check if both sets are equal +template +bool CheckEqualVector(const Vector1 &vector1, const Vector2 &vector2) +{ + if(vector1.size() != vector2.size()) + return false; + return std::equal(vector1.begin(), vector1.end(), vector2.begin()); +} + +template +bool CheckUninitializedIsZero(const Vector & v) +{ + typedef typename Vector::value_type value_type; + typename Vector::size_type sz = v.size(); + typename Vector::size_type extra = v.capacity() - v.size(); + value_type comp(0); + + const value_type *holder = &v[0] + sz; + + while(extra--){ + if(*holder++ != comp) + return false; + } + return true; +} + + +//This function tests all the possible combinations when +//inserting data in a vector and expanding backwards +template +bool test_insert_with_expand_bwd() +{ + typedef typename VectorWithExpandBwdAllocator::value_type value_type; + typedef typename boost::interprocess::ipcdetail::remove_volatile::type non_volatile_value_type; + typedef std::vector Vect; + const int MemorySize = 1000; + + //Distance old and new buffer + const int Offset[] = + { 350, 250, 150, 150, + 150, 50, 50, 50 }; + //Insert position + const int Position[] = + { 100, 100, 100, 100, + 100, 100, 100, 100 }; + //Initial vector size + const int InitialSize[] = + { 200, 200, 200, 200, + 200, 200, 200, 200 }; + //Size of the data to insert + const int InsertSize[] = + { 100, 100, 100, 200, + 300, 25, 100, 200 }; + //Number of tests + const int Iterations = sizeof(InsertSize)/sizeof(int); + + for(int iteration = 0; iteration < Iterations; ++iteration) + { + value_type *memory = new value_type[MemorySize]; + try { + std::vector initial_data; + initial_data.resize(InitialSize[iteration]); + for(int i = 0; i < InitialSize[iteration]; ++i){ + initial_data[i] = i; + } + + Vect data_to_insert; + data_to_insert.resize(InsertSize[iteration]); + for(int i = 0; i < InsertSize[iteration]; ++i){ + data_to_insert[i] = -i; + } + + expand_bwd_test_allocator alloc + (&memory[0], MemorySize, Offset[iteration]); + VectorWithExpandBwdAllocator vector(alloc); + vector.insert( vector.begin() + , initial_data.begin(), initial_data.end()); + vector.insert( vector.begin() + Position[iteration] + , data_to_insert.begin(), data_to_insert.end()); + initial_data.insert(initial_data.begin() + Position[iteration] + , data_to_insert.begin(), data_to_insert.end()); + //Now check that values are equal + if(!CheckEqualVector(vector, initial_data)){ + std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl + << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl + << " Iteration: " << iteration << std::endl; + return false; + } + } + catch(...){ + delete [](const_cast(memory)); + throw; + } + delete [](const_cast(memory)); + } + + return true; +} + +//This function tests all the possible combinations when +//inserting data in a vector and expanding backwards +template +bool test_assign_with_expand_bwd() +{ + typedef typename VectorWithExpandBwdAllocator::value_type value_type; + typedef typename boost::interprocess::ipcdetail::remove_volatile::type non_volatile_value_type; + const int MemorySize = 200; + + const int Offset[] = { 50, 50, 50}; + const int InitialSize[] = { 25, 25, 25}; + const int InsertSize[] = { 15, 35, 55}; + const int Iterations = sizeof(InsertSize)/sizeof(int); + + for(int iteration = 0; iteration initial_data; + initial_data.resize(InitialSize[iteration]); + for(int i = 0; i < InitialSize[iteration]; ++i){ + initial_data[i] = i; + } + + //Create data to insert + std::vector data_to_insert; + data_to_insert.resize(InsertSize[iteration]); + for(int i = 0; i < InsertSize[iteration]; ++i){ + data_to_insert[i] = -i; + } + + //Insert initial data to the vector to test + expand_bwd_test_allocator alloc + (&memory[0], MemorySize, Offset[iteration]); + VectorWithExpandBwdAllocator vector(alloc); + vector.insert( vector.begin() + , initial_data.begin(), initial_data.end()); + + //Insert data + vector.insert(vector.cbegin(), data_to_insert.begin(), data_to_insert.end()); + initial_data.insert(initial_data.begin(), data_to_insert.begin(), data_to_insert.end()); + + //Now check that values are equal + if(!CheckEqualVector(vector, initial_data)){ + std::cout << "test_insert_with_expand_bwd::CheckEqualVector failed." << std::endl + << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl + << " Iteration: " << iteration << std::endl; + return false; + } + } + catch(...){ + delete [](const_cast::type*>(memory)); + throw; + } + delete [](const_cast::type*>(memory)); + } + + return true; +} + +//This function calls all tests +template +bool test_all_expand_bwd() +{ + std::cout << "Starting test_insert_with_expand_bwd." << std::endl << " Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + + if(!test_insert_with_expand_bwd()){ + std::cout << "test_allocation_direct_deallocation failed. Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + return false; + } + + std::cout << "Starting test_assign_with_expand_bwd." << std::endl << " Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + + if(!test_assign_with_expand_bwd()){ + std::cout << "test_allocation_direct_deallocation failed. Class: " + << typeid(VectorWithExpandBwdAllocator).name() << std::endl; + return false; + } + + return true; +} + +}}} //namespace boost { namespace interprocess { namespace test { + +#include + +#endif //BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER + diff --git a/src/boost/libs/interprocess/test/file_lock_test.cpp b/src/boost/libs/interprocess/test/file_lock_test.cpp new file mode 100644 index 00000000..6dcfd926 --- /dev/null +++ b/src/boost/libs/interprocess/test/file_lock_test.cpp @@ -0,0 +1,80 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include "mutex_test_template.hpp" +#include "sharable_mutex_test_template.hpp" +#include "get_process_id_name.hpp" +#include +#include //std::remove + +using namespace boost::interprocess; + +inline std::string get_filename() +{ + std::string ret (ipcdetail::get_temporary_path()); + ret += "/"; + ret += test::get_process_id_name(); + return ret; +} + +//This wrapper is necessary to have a default constructor +//in generic mutex_test_template functions +class file_lock_lock_test_wrapper + : public boost::interprocess::file_lock +{ + public: + file_lock_lock_test_wrapper() + : boost::interprocess::file_lock(get_filename().c_str()) + {} +}; + +int main () +{ + //Destroy and create file + { + std::remove(get_filename().c_str()); + std::ofstream file(get_filename().c_str()); + if(!file){ + return 1; + } + file_lock flock(get_filename().c_str()); + { + scoped_lock sl(flock); + } + { + scoped_lock sl(flock, try_to_lock); + } + { + scoped_lock sl(flock, test::delay(1)); + } + } + { + //Now test move semantics + file_lock mapping(get_filename().c_str()); + file_lock move_ctor(boost::move(mapping)); + file_lock move_assign; + move_assign = boost::move(move_ctor); + mapping.swap(move_assign); + } + + //test::test_all_lock(); + //test::test_all_mutex(); + //test::test_all_sharable_mutex(); + std::remove(get_filename().c_str()); + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/file_mapping_test.cpp b/src/boost/libs/interprocess/test/file_mapping_test.cpp new file mode 100644 index 00000000..c3ce1614 --- /dev/null +++ b/src/boost/libs/interprocess/test/file_mapping_test.cpp @@ -0,0 +1,164 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include //std::streamoff +#include //std::ofstream, std::ifstream +#include +#include +#include +#include +#include //std::exception +#include //std::size_t +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +inline std::string get_filename() +{ + std::string ret (ipcdetail::get_temporary_path()); + ret += "/"; + ret += test::get_process_id_name(); + return ret; +} + +file_mapping get_file_mapping() +{ + file_mapping f; + return file_mapping(boost::move(f)); +} + +int main () +{ + try{ + const std::size_t FileSize = 99999*2; + { + //Create file with given size + std::ofstream file(get_filename().c_str(), std::ios::binary | std::ios::trunc); + file.seekp(static_cast(FileSize-1)); + file.write("", 1); + } + + { + //Create a file mapping + file_mapping mapping(get_filename().c_str(), read_write); + //Create two mapped regions, one half of the file each + mapped_region region (mapping + ,read_write + ,0 + ,FileSize/2 + ); + + mapped_region region2(mapping + ,read_write + ,FileSize/2 + ,FileSize - FileSize/2 + ); + + //Fill two regions with a pattern + unsigned char *filler = static_cast(region.get_address()); + for(std::size_t i = 0 + ;i < FileSize/2 + ;++i){ + *filler++ = static_cast(i); + } + + filler = static_cast(region2.get_address()); + for(std::size_t i = FileSize/2 + ;i < FileSize + ;++i){ + *filler++ = static_cast(i); + } + if(!region.flush(0, 0, false)){ + return 1; + } + + if(!region2.flush(0, 0, true)){ + return 1; + } + } + + //See if the pattern is correct in the file + { + //Open the file + std::ifstream file(get_filename().c_str(), std::ios::binary); + + //Create a memory buffer + boost::container::vector memory(FileSize/2 +1); + + //Fill buffer + file.read(static_cast(static_cast(memory.data())) + , FileSize/2); + + unsigned char *checker = memory.data(); + //Check pattern + for(std::size_t i = 0 + ;i < FileSize/2 + ;++i){ + if(*checker++ != static_cast(i)){ + return 1; + } + } + + //Fill buffer + file.read(static_cast(static_cast(memory.data())) + , FileSize - FileSize/2); + + checker = memory.data(); + //Check pattern + for(std::size_t i = FileSize/2 + ;i < FileSize + ;++i){ + if(*checker++ != static_cast(i)){ + return 1; + } + } + } + + //Now check the pattern mapping a single read only mapped_region + { + //Create a file mapping + file_mapping mapping(get_filename().c_str(), read_only); + + //Create a single regions, mapping all the file + mapped_region region (mapping + ,read_only + ); + + //Check pattern + unsigned char *pattern = static_cast(region.get_address()); + for(std::size_t i = 0 + ;i < FileSize + ;++i, ++pattern){ + if(*pattern != static_cast(i)){ + return 1; + } + } + } + { + //Now test move semantics + file_mapping mapping(get_filename().c_str(), read_only); + file_mapping move_ctor(boost::move(mapping)); + file_mapping move_assign; + move_assign = boost::move(move_ctor); + mapping.swap(move_assign); + file_mapping ret(get_file_mapping()); + } + } + catch(std::exception &exc){ + file_mapping::remove(get_filename().c_str()); + std::cout << "Unhandled exception: " << exc.what() << std::endl; + throw; + } + file_mapping::remove(get_filename().c_str()); + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/flat_map_index_allocation_test.cpp b/src/boost/libs/interprocess/test/flat_map_index_allocation_test.cpp new file mode 100644 index 00000000..41476ab3 --- /dev/null +++ b/src/boost/libs/interprocess/test/flat_map_index_allocation_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/flat_tree_test.cpp b/src/boost/libs/interprocess/test/flat_tree_test.cpp new file mode 100644 index 00000000..bd4af0f7 --- /dev/null +++ b/src/boost/libs/interprocess/test/flat_tree_test.cpp @@ -0,0 +1,202 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "set_test.hpp" +#include "map_test.hpp" +#include "emplace_test.hpp" + +///////////////////////////////////////////////////////////////// +// +// This example repeats the same operations with std::set and +// shmem_set using the node allocator +// and compares the values of both containers +// +///////////////////////////////////////////////////////////////// + +using namespace boost::interprocess; + +//Customize managed_shared_memory class +typedef basic_managed_shared_memory + , + rbtree_best_fit, + iset_index + > my_managed_shared_memory; + +//Alias allocator type +typedef allocator + shmem_allocator_t; +typedef allocator + shmem_movable_allocator_t; +typedef allocator, my_managed_shared_memory::segment_manager> + shmem_pair_allocator_t; +typedef allocator, my_managed_shared_memory::segment_manager> + shmem_movable_pair_allocator_t; + +typedef allocator + shmem_move_copy_allocator_t; + +typedef allocator + shmem_copy_allocator_t; + +typedef allocator, my_managed_shared_memory::segment_manager> + shmem_move_copy_pair_allocator_t; + +//Alias set types +typedef std::set MyStdSet; +typedef std::multiset MyStdMultiSet; +typedef std::map MyStdMap; +typedef std::multimap MyStdMultiMap; + +typedef flat_set, shmem_allocator_t> MyShmSet; +typedef flat_multiset, shmem_allocator_t> MyShmMultiSet; +typedef flat_map, shmem_pair_allocator_t> MyShmMap; +typedef flat_multimap, shmem_pair_allocator_t> MyShmMultiMap; + +typedef flat_set + ,shmem_movable_allocator_t> MyMovableShmSet; +typedef flat_multiset + ,shmem_movable_allocator_t> MyMovableShmMultiSet; +typedef flat_map + ,shmem_movable_pair_allocator_t> MyMovableShmMap; +typedef flat_multimap + ,shmem_movable_pair_allocator_t> MyMovableShmMultiMap; + +typedef flat_set + ,shmem_move_copy_allocator_t> MyMoveCopyShmSet; +typedef flat_multiset + ,shmem_move_copy_allocator_t> MyMoveCopyShmMultiSet; + +typedef flat_set + ,shmem_copy_allocator_t> MyCopyShmSet; +typedef flat_multiset + ,shmem_copy_allocator_t> MyCopyShmMultiSet; + +typedef flat_map + ,shmem_move_copy_pair_allocator_t> MyMoveCopyShmMap; +typedef flat_multimap + ,shmem_move_copy_pair_allocator_t> MyMoveCopyShmMultiMap; + +int main() +{ + using namespace boost::interprocess::test; + + if (0 != set_test()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test_copyable()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != set_test()){ + std::cout << "Error in set_test" << std::endl; + return 1; + } + + if (0 != map_test()){ + std::cout << "Error in map_test" << std::endl; + return 1; + } + + if (0 != map_test_copyable()){ + std::cout << "Error in map_test" << std::endl; + return 1; + } + +// if (0 != map_test()){ +// return 1; +// } + + if (0 != map_test()){ + std::cout << "Error in map_test" << std::endl; + return 1; + } + + //#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 3) + const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC); + const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR); + + if(!boost::interprocess::test::test_emplace, MapOptions>()) + return 1; + if(!boost::interprocess::test::test_emplace, MapOptions>()) + return 1; + if(!boost::interprocess::test::test_emplace, SetOptions>()) + return 1; + if(!boost::interprocess::test::test_emplace, SetOptions>()) + return 1; + //#endif //!defined(__GNUC__) + return 0; + +} + +#include diff --git a/src/boost/libs/interprocess/test/get_process_id_name.hpp b/src/boost/libs/interprocess/test/get_process_id_name.hpp new file mode 100644 index 00000000..f79384ab --- /dev/null +++ b/src/boost/libs/interprocess/test/get_process_id_name.hpp @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_GET_PROCESS_ID_NAME_HPP +#define BOOST_INTERPROCESS_GET_PROCESS_ID_NAME_HPP + +#include +#include //std::string +#include //std::stringstream +#include + +namespace boost{ +namespace interprocess{ +namespace test{ + +inline void get_process_id_name(std::string &str) +{ + std::stringstream sstr; + sstr << "process_" << boost::interprocess::ipcdetail::get_current_process_id() << std::ends; + str = sstr.str().c_str(); +} + +inline void get_process_id_ptr_name(std::string &str, const void *ptr) +{ + std::stringstream sstr; + sstr << "process_" << boost::interprocess::ipcdetail::get_current_process_id() << "_" << ptr << std::ends; + str = sstr.str().c_str(); +} + +inline const char *get_process_id_name() +{ + static std::string str; + get_process_id_name(str); + return str.c_str(); +} + +inline const char *get_process_id_ptr_name(void *ptr) +{ + static std::string str; + get_process_id_ptr_name(str, ptr); + return str.c_str(); +} + +inline const char *add_to_process_id_name(const char *name) +{ + static std::string str; + get_process_id_name(str); + str += name; + return str.c_str(); +} + +inline const char *add_to_process_id_ptr_name(const char *name, void *ptr) +{ + static std::string str; + get_process_id_ptr_name(str, ptr); + str += name; + return str.c_str(); +} + +} //namespace test{ +} //namespace interprocess{ +} //namespace boost{ + +#endif //#ifndef BOOST_INTERPROCESS_GET_PROCESS_ID_NAME_HPP diff --git a/src/boost/libs/interprocess/test/heap_allocator_v1.hpp b/src/boost/libs/interprocess/test/heap_allocator_v1.hpp new file mode 100644 index 00000000..278d52e0 --- /dev/null +++ b/src/boost/libs/interprocess/test/heap_allocator_v1.hpp @@ -0,0 +1,166 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_HEAP_ALLOCATOR_V1_HPP +#define BOOST_INTERPROCESS_HEAP_ALLOCATOR_V1_HPP + +#if defined (_MSC_VER) +# pragma once +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes an heap_allocator_v1 that allocates portions of fixed size +//!memory buffer (shared memory, mapped file...) + +namespace boost { +namespace interprocess { +namespace test { + +//!An STL compatible heap_allocator_v1 that uses a segment manager as +//!memory source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the heap_allocator_v1 in shared memory, memory mapped-files, etc...*/ +template +class heap_allocator_v1 +{ + private: + typedef heap_allocator_v1 self_t; + typedef SegmentManager segment_manager; + typedef typename segment_manager::void_pointer aux_pointer_t; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type cvoid_ptr; + + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type alloc_ptr_t; + + template + heap_allocator_v1& operator=(const heap_allocator_v1&); + + heap_allocator_v1& operator=(const heap_allocator_v1&); + + alloc_ptr_t mp_mngr; + + public: + typedef T value_type; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type pointer; + typedef typename boost::intrusive:: + pointer_traits::template + rebind_pointer::type const_pointer; + typedef typename ipcdetail::add_reference + ::type reference; + typedef typename ipcdetail::add_reference + ::type const_reference; + typedef typename SegmentManager::size_type size_type; + typedef typename SegmentManager::difference_type difference_type; + + //!Obtains an heap_allocator_v1 of other type + template + struct rebind + { + typedef heap_allocator_v1 other; + }; + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return ipcdetail::to_raw_pointer(mp_mngr); } + + //!Returns address of mutable object. Never throws + pointer address(reference value) const + { return pointer(addressof(value)); } + + //!Returns address of non mutable object. Never throws + const_pointer address(const_reference value) const + { return const_pointer(addressof(value)); } + + //!Constructor from the segment manager. Never throws + heap_allocator_v1(segment_manager *segment_mngr) + : mp_mngr(segment_mngr) { } + + //!Constructor from other heap_allocator_v1. Never throws + heap_allocator_v1(const heap_allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){ } + + //!Constructor from related heap_allocator_v1. Never throws + template + heap_allocator_v1(const heap_allocator_v1 &other) + : mp_mngr(other.get_segment_manager()){} + + //!Allocates memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_ptr hint = 0) + { + (void)hint; + char *raw_mem = ::new char[sizeof(value_type)*count]; + return boost::intrusive::pointer_traits::pointer_to(reinterpret_cast(*raw_mem)); + } + + //!Deallocates memory previously allocated. Never throws + void deallocate(const pointer &ptr, size_type) + { + char *ptr_raw = (char*)ipcdetail::to_raw_pointer(ptr); + ::delete[] ptr_raw; + } + + //!Construct object, calling constructor. + //!Throws if T(const T&) throws + void construct(const pointer &ptr, const_reference value) + { new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(value); } + + //!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(); } + + //!Swap segment manager. Does not throw. If each heap_allocator_v1 is placed in + //!different memory segments, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { ::boost::adl_move_swap(alloc1.mp_mngr, alloc2.mp_mngr); } +}; + +//!Equality test for same type of heap_allocator_v1 +template inline +bool operator==(const heap_allocator_v1 &alloc1, + const heap_allocator_v1 &alloc2) + { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } + +//!Inequality test for same type of heap_allocator_v1 +template inline +bool operator!=(const heap_allocator_v1 &alloc1, + const heap_allocator_v1 &alloc2) + { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } + +} //namespace test { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_HEAP_ALLOCATOR_V1_HPP + diff --git a/src/boost/libs/interprocess/test/intermodule_singleton_test.cpp b/src/boost/libs/interprocess/test/intermodule_singleton_test.cpp new file mode 100644 index 00000000..915a9fe8 --- /dev/null +++ b/src/boost/libs/interprocess/test/intermodule_singleton_test.cpp @@ -0,0 +1,330 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include //for std::abort + +using namespace boost::interprocess; + +class MyClass +{ + public: + MyClass() + { + std::cout << "MyClass()\n" << std::endl; + } + + void shout() const + { + std::cout << "Shout\n" << std::endl; + } + + ~MyClass() + { + std::cout << "~MyClass()\n" << std::endl; + } +}; + +class MyDerivedClass + : public MyClass +{}; + +class MyThrowingClass +{ + public: + MyThrowingClass() + { + throw int(0); + } +}; + + +template < template class IntermoduleType > +int intermodule_singleton_test() +{ + bool exception_thrown = false; + bool exception_2_thrown = false; + + try{ + IntermoduleType::get(); + } + catch(int &){ + exception_thrown = true; + //Second try + try{ + IntermoduleType::get(); + } + catch(interprocess_exception &){ + exception_2_thrown = true; + } + } + + if(!exception_thrown || !exception_2_thrown){ + return 1; + } + + MyClass & mc = IntermoduleType::get(); + mc.shout(); + IntermoduleType::get().shout(); + IntermoduleType::get().shout(); + + //Second try + exception_2_thrown = false; + try{ + IntermoduleType::get(); + } + catch(interprocess_exception &){ + exception_2_thrown = true; + } + if(!exception_2_thrown){ + return 1; + } + + return 0; +} + +//A class simulating a logger +//We'll register constructor/destructor counts +//to test the singleton was correctly resurrected +//by LogUser singleton. +template +class Logger +{ + public: + Logger() + { + ++constructed_times; + std::cout << "Logger(),tag:" << typeid(Tag).name() << "(construct #" << constructed_times << ")\n" << std::endl; + } + + void log_it() + {} + + ~Logger() + { + ++destroyed_times; + std::cout << "~Logger(),tag:" << typeid(Tag).name() << "(destroy #" << destroyed_times << ")\n" << std::endl; + } + + static unsigned int constructed_times; + static unsigned int destroyed_times; +}; + +template +unsigned int Logger::constructed_times; + +template +unsigned int Logger::destroyed_times; + +//A class simulating a logger user. +//The destructor uses the logger so that +//the logger is resurrected if it was +//already destroyed +template +class LogUser +{ + public: + LogUser() + { + std::cout << "LogUser(),tag:" << typeid(LogSingleton).name() << "\n" << std::endl; + } + + void function_using_log() + { LogSingleton::get().log_it(); } + + ~LogUser() + { + std::cout << "~LogUser(),tag:" << typeid(LogSingleton).name() << "\n" << std::endl; + LogSingleton::get().log_it(); + } +}; + +//A class that tests the correct +//phoenix singleton behaviour. +//Logger should be resurrected by LogUser +template +class LogPhoenixTester +{ + public: + LogPhoenixTester() + { + std::cout << "LogPhoenixTester(), tag: " << typeid(Tag).name() << "\n" << std::endl; + } + + void dummy() + {} + + ~LogPhoenixTester() + { + //Test Phoenix singleton was correctly executed: + //created and destroyed two times + //This test will be executed after main ends + std::cout << "~LogPhoenixTester(), tag: " << typeid(Tag).name() << "\n" << std::endl; + if(Logger::constructed_times != Logger::destroyed_times || + Logger::constructed_times != 2) + { + std::stringstream sstr; + sstr << "LogPhoenixTester failed for tag "; + sstr << typeid(Tag).name(); + sstr << "\n"; + if(Logger::constructed_times != 2){ + sstr << "Logger::constructed_times != 2\n"; + sstr << "("; + sstr << Logger::constructed_times << ")\n"; + } + else{ + sstr << "Logger::constructed_times != Logger::destroyed_times\n"; + sstr << "(" << Logger::constructed_times << " vs. " << Logger::destroyed_times << ")\n"; + } + std::cout << "~LogPhoenixTester(), error: " << sstr.str() << std::endl; + std::abort(); + } + } +}; + +//A class simulating a logger user. +//The destructor uses the logger so that +//the logger is resurrected if it was +//already destroyed +template +class LogDeadReferenceUser +{ + public: + LogDeadReferenceUser() + { + std::cout << "LogDeadReferenceUser(), LogSingleton: " << typeid(LogSingleton).name() << "\n" << std::endl; + } + + void function_using_log() + { LogSingleton::get().log_it(); } + + ~LogDeadReferenceUser() + { + std::cout << "~LogDeadReferenceUser(), LogSingleton: " << typeid(LogSingleton).name() << "\n" << std::endl; + //Make sure the exception is thrown as we are + //trying to use a dead non-phoenix singleton + try{ + LogSingleton::get().log_it(); + std::string s("LogDeadReferenceUser failed for LogSingleton "); + s += typeid(LogSingleton).name(); + std::cout << "~LogDeadReferenceUser(), error: " << s << std::endl; + std::abort(); + } + catch(interprocess_exception &){ + //Correct behaviour + } + } +}; + +template < template class IntermoduleType > +int phoenix_singleton_test() +{ + typedef int DummyType; + typedef IntermoduleType Tag; + typedef Logger LoggerType; + typedef IntermoduleType LoggerSingleton; + typedef LogUser LogUserType; + typedef IntermoduleType LogUserSingleton; + typedef IntermoduleType, true, true> LogPhoenixTesterSingleton; + + //Instantiate Phoenix tester singleton so that it will be destroyed the last + LogPhoenixTesterSingleton::get().dummy(); + + //Now instantitate a log user singleton + LogUserType &log_user = LogUserSingleton::get(); + + //Then force LoggerSingleton instantiation + //calling a function that will use it. + //After main ends, LoggerSingleton will be destroyed + //before LogUserSingleton due to LIFO + //singleton semantics + log_user.function_using_log(); + + //Next, LogUserSingleton destructor will resurrect + //LoggerSingleton. + //After that LoggerSingleton will be destroyed and + //lastly LogPhoenixTester will be destroyed checking + //LoggerSingleton was correctly destroyed. + return 0; +} + +template < template class IntermoduleType > +int dead_reference_singleton_test() +{ + typedef int DummyType; + typedef IntermoduleType Tag; + typedef Logger LoggerType; + typedef IntermoduleType LoggerSingleton; + typedef LogDeadReferenceUser LogDeadReferenceUserType; + typedef IntermoduleType LogDeadReferenceUserSingleton; + + //Now instantitate a log user singleton + LogDeadReferenceUserType &log_user = LogDeadReferenceUserSingleton::get(); + + //Then force LoggerSingleton instantiation + //calling a function that will use it. + //After main ends, LoggerSingleton will be destroyed + //before LogDeadReferenceUserType due to LIFO + //singleton semantics + log_user.function_using_log(); + + //Next, LogDeadReferenceUserType destructor will try to use + //LoggerSingleton and an exception will be raised an catched. + return 0; +} + +//reduce name length +template +class port_singleton + : public ipcdetail::portable_intermodule_singleton +{}; + +#ifdef BOOST_INTERPROCESS_WINDOWS +template +class win_singleton + : public ipcdetail::windows_intermodule_singleton< C, LazyInit, Phoenix> +{}; +#endif + +int main () +{ + if(0 != intermodule_singleton_test()){ + return 1; + } + + #ifdef BOOST_INTERPROCESS_WINDOWS + if(0 != intermodule_singleton_test()){ + return 1; + } + #endif + + //Only few platforms support this + #ifdef BOOST_INTERPROCESS_ATEXIT_CALLABLE_FROM_ATEXIT + //Phoenix singletons are tested after main ends, + //LogPhoenixTester does the work + phoenix_singleton_test(); + #ifdef BOOST_INTERPROCESS_WINDOWS + phoenix_singleton_test(); + #endif + #endif + + //Dead reference singletons are tested after main ends, + //LogDeadReferenceUser does the work + dead_reference_singleton_test(); + #ifdef BOOST_INTERPROCESS_WINDOWS + dead_reference_singleton_test(); + #endif + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/intrusive_ptr_test.cpp b/src/boost/libs/interprocess/test/intrusive_ptr_test.cpp new file mode 100644 index 00000000..f3e48125 --- /dev/null +++ b/src/boost/libs/interprocess/test/intrusive_ptr_test.cpp @@ -0,0 +1,546 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Peter Dimov 2002-2005. +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +typedef boost::interprocess::offset_ptr VP; + +namespace { + int addref_release_calls = 0; +} + +namespace N +{ + +class base +{ + private: + + int use_count_; + + base(base const &); + base & operator=(base const &); + + protected: + + base(): use_count_(0) + { + } + + virtual ~base() + { + } + + public: + + long use_count() const + { + return use_count_; + } + + void add_ref() + { + ++addref_release_calls; + ++use_count_; + } + + void release() + { + ++addref_release_calls; + if(--use_count_ == 0) delete this; + } +}; + +inline void intrusive_ptr_add_ref(N::base *p) +{ p->add_ref(); } + +inline void intrusive_ptr_release(N::base *p) +{ p->release(); } + +} // namespace N + +struct X: public virtual N::base +{ +}; + +struct Y: public X +{ +}; + +// + +namespace n_element_type +{ + +void f(X &) +{ +} + +void test() +{ + typedef boost::interprocess::intrusive_ptr::element_type T; + T t; + f(t); +} + +} // namespace n_element_type + +namespace n_constructors +{ + +void default_constructor() +{ + boost::interprocess::intrusive_ptr px; + BOOST_TEST(px.get() == 0); +} + +void pointer_constructor() +{ + { + boost::interprocess::intrusive_ptr px(0); + BOOST_TEST(px.get() == 0); + } + + { + boost::interprocess::intrusive_ptr px(0, false); + BOOST_TEST(px.get() == 0); + } + + { + boost::interprocess::offset_ptr p = new X; + BOOST_TEST(p->use_count() == 0); + + boost::interprocess::intrusive_ptr px(p); + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 1); + } + + { + boost::interprocess::offset_ptr p = new X; + BOOST_TEST(p->use_count() == 0); + + intrusive_ptr_add_ref(p.get()); + BOOST_TEST(p->use_count() == 1); + + boost::interprocess::intrusive_ptr px(p, false); + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 1); + } +} + +void copy_constructor() +{ + { + boost::interprocess::intrusive_ptr px; + boost::interprocess::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::interprocess::intrusive_ptr py; + boost::interprocess::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::interprocess::intrusive_ptr px(0); + boost::interprocess::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::interprocess::intrusive_ptr py(0); + boost::interprocess::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::interprocess::intrusive_ptr px(0, false); + boost::interprocess::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::interprocess::intrusive_ptr py(0, false); + boost::interprocess::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } + + { + boost::interprocess::intrusive_ptr px(new X); + boost::interprocess::intrusive_ptr px2(px); + BOOST_TEST(px2.get() == px.get()); + } + + { + boost::interprocess::intrusive_ptr py(new Y); + boost::interprocess::intrusive_ptr px(py); + BOOST_TEST(px.get() == py.get()); + } +} + +void move_constructor() +{ + { + int prev_addref_release_calls = addref_release_calls; + X* x = new X(); + boost::interprocess::intrusive_ptr px(x); + BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1); + + //static_assert(std::is_nothrow_move_constructible< boost::interprocess::intrusive_ptr >::value, "test instrusive_ptr is nothrow move constructible"); + + boost::interprocess::intrusive_ptr px2(boost::move(px)); + BOOST_TEST(px2.get() == x); + BOOST_TEST(!px.get()); + BOOST_TEST(px2->use_count() == 1); + BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1); + } +} + +void test() +{ + default_constructor(); + pointer_constructor(); + copy_constructor(); + move_constructor(); +} + +} // namespace n_constructors + +namespace n_destructor +{ + +void test() +{ + boost::interprocess::intrusive_ptr px(new X); + BOOST_TEST(px->use_count() == 1); + + { + boost::interprocess::intrusive_ptr px2(px); + BOOST_TEST(px->use_count() == 2); + } + + BOOST_TEST(px->use_count() == 1); +} + +} // namespace n_destructor + +namespace n_assignment +{ + +void copy_assignment() +{ +} + +void move_assignment() +{ + { + int prev_addref_release_calls = addref_release_calls; + X* x = new X(); + boost::interprocess::intrusive_ptr px(x); + BOOST_TEST(px->use_count() == 1); + BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1); + + //static_assert(std::is_nothrow_move_assignable< boost::interprocess::intrusive_ptr >::value, "test if nothrow move assignable "); + + boost::interprocess::intrusive_ptr px2; + px2 = boost::move(px); + BOOST_TEST(px2.get() == x); + BOOST_TEST(!px.get()); + BOOST_TEST(px2->use_count() == 1); + BOOST_TEST(addref_release_calls == prev_addref_release_calls + 1); + } +} + +void conversion_assignment() +{ +} + +void pointer_assignment() +{ +} + +void test() +{ + copy_assignment(); + conversion_assignment(); + pointer_assignment(); + move_assignment(); +} + +} // namespace n_assignment + +namespace n_access +{ + +void test() +{ + { + boost::interprocess::intrusive_ptr px; + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + } + + { + boost::interprocess::intrusive_ptr px(0); + BOOST_TEST(px? false: true); + BOOST_TEST(!px); + } + + { + boost::interprocess::intrusive_ptr px + (boost::interprocess::offset_ptr(new X)); + BOOST_TEST(px? true: false); + BOOST_TEST(!!px); + BOOST_TEST(&*px == boost::interprocess::ipcdetail::to_raw_pointer(px.get())); + BOOST_TEST(px.operator ->() == px.get()); + } +} + +} // namespace n_access + +namespace n_swap +{ + +void test() +{ + { + boost::interprocess::intrusive_ptr px; + boost::interprocess::intrusive_ptr px2; + + px.swap(px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + + ::boost::adl_move_swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == 0); + } + + { + boost::interprocess::offset_ptr p = new X; + boost::interprocess::intrusive_ptr px; + boost::interprocess::intrusive_ptr px2(p); + boost::interprocess::intrusive_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p); + BOOST_TEST(px->use_count() == 2); + BOOST_TEST(px2.get() == 0); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3->use_count() == 2); + + ::boost::adl_move_swap(px, px2); + + BOOST_TEST(px.get() == 0); + BOOST_TEST(px2.get() == p); + BOOST_TEST(px2->use_count() == 2); + BOOST_TEST(px3.get() == p); + BOOST_TEST(px3->use_count() == 2); + } + + { + boost::interprocess::offset_ptr p1 = new X; + boost::interprocess::offset_ptr p2 = new X; + boost::interprocess::intrusive_ptr px(p1); + boost::interprocess::intrusive_ptr px2(p2); + boost::interprocess::intrusive_ptr px3(px2); + + px.swap(px2); + + BOOST_TEST(px.get() == p2); + BOOST_TEST(px->use_count() == 2); + BOOST_TEST(px2.get() == p1); + BOOST_TEST(px2->use_count() == 1); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3->use_count() == 2); + + ::boost::adl_move_swap(px, px2); + + BOOST_TEST(px.get() == p1); + BOOST_TEST(px->use_count() == 1); + BOOST_TEST(px2.get() == p2); + BOOST_TEST(px2->use_count() == 2); + BOOST_TEST(px3.get() == p2); + BOOST_TEST(px3->use_count() == 2); + } +} + +} // namespace n_swap + +namespace n_comparison +{ + +template +void test2(boost::interprocess::intrusive_ptr const & p, + boost::interprocess::intrusive_ptr const & q) +{ + BOOST_TEST((p == q) == (p.get() == q.get())); + BOOST_TEST((p != q) == (p.get() != q.get())); +} + +template +void test3(boost::interprocess::intrusive_ptr const & p, + boost::interprocess::intrusive_ptr const & q) +{ + BOOST_TEST((p == q) == (p.get() == q.get())); + BOOST_TEST((p.get() == q) == (p.get() == q.get())); + BOOST_TEST((p == q.get()) == (p.get() == q.get())); + BOOST_TEST((p != q) == (p.get() != q.get())); + BOOST_TEST((p.get() != q) == (p.get() != q.get())); + BOOST_TEST((p != q.get()) == (p.get() != q.get())); + + // 'less' moved here as a g++ 2.9x parse error workaround + std::less > less; + BOOST_TEST((p < q) == less(p.get(), q.get())); +} + +void test() +{ + { + boost::interprocess::intrusive_ptr px; + test3(px, px); + + boost::interprocess::intrusive_ptr px2; + test3(px, px2); + + boost::interprocess::intrusive_ptr px3(px); + test3(px3, px3); + test3(px, px3); + } + + { + boost::interprocess::intrusive_ptr px; + + boost::interprocess::intrusive_ptr px2(new X); + test3(px, px2); + test3(px2, px2); + + boost::interprocess::intrusive_ptr px3(new X); + test3(px2, px3); + + boost::interprocess::intrusive_ptr px4(px2); + test3(px2, px4); + test3(px4, px4); + } + + { + boost::interprocess::intrusive_ptr px(new X); + + boost::interprocess::intrusive_ptr py(new Y); + test2(px, py); + + boost::interprocess::intrusive_ptr px2(py); + test2(px2, py); + test3(px, px2); + test3(px2, px2); + } +} + +} // namespace n_comparison + +namespace n_static_cast +{ + +void test() +{ +} + +} // namespace n_static_cast + +namespace n_dynamic_cast +{ + +void test() +{ +} + +} // namespace n_dynamic_cast + +namespace n_transitive +{ + +struct X: public N::base +{ + boost::interprocess::intrusive_ptr next; +}; + +void test() +{ + boost::interprocess::intrusive_ptr p(new X); + p->next = boost::interprocess::intrusive_ptr(new X); + BOOST_TEST(!p->next->next); + p = p->next; + BOOST_TEST(!p->next); +} + +} // namespace n_transitive + +namespace n_report_1 +{ + +class foo: public N::base +{ + public: + + foo(): m_self(this) + { + } + + void suicide() + { + m_self = 0; + } + + private: + + boost::interprocess::intrusive_ptr m_self; +}; + +void test() +{ + boost::interprocess::offset_ptr foo_ptr = new foo; + foo_ptr->suicide(); +} + +} // namespace n_report_1 + +int main() +{ + n_element_type::test(); + n_constructors::test(); + n_destructor::test(); + n_assignment::test(); + n_access::test(); + n_swap::test(); + n_comparison::test(); + n_static_cast::test(); + n_dynamic_cast::test(); + + n_transitive::test(); + n_report_1::test(); + + return boost::report_errors(); +} + +#include diff --git a/src/boost/libs/interprocess/test/iset_index_allocation_test.cpp b/src/boost/libs/interprocess/test/iset_index_allocation_test.cpp new file mode 100644 index 00000000..42d03ff8 --- /dev/null +++ b/src/boost/libs/interprocess/test/iset_index_allocation_test.cpp @@ -0,0 +1,24 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/iunordered_set_index_allocation_test.cpp b/src/boost/libs/interprocess/test/iunordered_set_index_allocation_test.cpp new file mode 100644 index 00000000..5e8e966d --- /dev/null +++ b/src/boost/libs/interprocess/test/iunordered_set_index_allocation_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/list_test.cpp b/src/boost/libs/interprocess/test/list_test.cpp new file mode 100644 index 00000000..4ecf55a4 --- /dev/null +++ b/src/boost/libs/interprocess/test/list_test.cpp @@ -0,0 +1,63 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "dummy_test_allocator.hpp" +#include "list_test.hpp" +#include "movable_int.hpp" +#include "emplace_test.hpp" + +using namespace boost::interprocess; + +typedef allocator ShmemAllocator; +typedef list MyList; + +//typedef allocator ShmemVolatileAllocator; +//typedef list MyVolatileList; + +typedef allocator ShmemMoveAllocator; +typedef list MyMoveList; + +typedef allocator ShmemCopyMoveAllocator; +typedef list MyCopyMoveList; + +typedef allocator ShmemCopyAllocator; +typedef list MyCopyList; + +int main () +{ + if(test::list_test()) + return 1; + +// if(test::list_test()) +// return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + if(test::list_test()) + return 1; + + const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE); + + if(!boost::interprocess::test::test_emplace, Options>()) + return 1; + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/list_test.hpp b/src/boost/libs/interprocess/test/list_test.hpp new file mode 100644 index 00000000..a7c40633 --- /dev/null +++ b/src/boost/libs/interprocess/test/list_test.hpp @@ -0,0 +1,281 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +//////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TEST_LIST_TEST_HEADER +#define BOOST_INTERPROCESS_TEST_LIST_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include +#include +#include +#include +#include "print_container.hpp" +#include +#include +#include "get_process_id_name.hpp" + +namespace boost{ +namespace interprocess{ +namespace test{ + +template +struct push_data_function +{ + template + static int execute(int max, MyShmList *shmlist, MyStdList *stdlist) + { + typedef typename MyShmList::value_type IntType; + for(int i = 0; i < max; ++i){ + IntType move_me(i); + shmlist->push_back(boost::move(move_me)); + stdlist->push_back(i); + shmlist->push_back(IntType(i)); + stdlist->push_back(int(i)); + } + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + return 0; + } +}; + +template<> +struct push_data_function +{ + template + static int execute(int max, MyShmList *shmlist, MyStdList *stdlist) + { + typedef typename MyShmList::value_type IntType; + for(int i = 0; i < max; ++i){ + IntType move_me(i); + shmlist->push_front(boost::move(move_me)); + stdlist->push_front(i); + shmlist->push_front(IntType(i)); + stdlist->push_front(int(i)); + } + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + return 0; + } +}; + +template +struct pop_back_function +{ + template + static int execute(MyShmList *shmlist, MyStdList *stdlist) + { + shmlist->pop_back(); + stdlist->pop_back(); + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + return 0; + } +}; + +template<> +struct pop_back_function +{ + template + static int execute(MyShmList *shmlist, MyStdList *stdlist) + { + (void)shmlist; (void)stdlist; + return 0; + } +}; + +template +int list_test (bool copied_allocators_equal = true) +{ + typedef std::list MyStdList; + typedef typename MyShmList::value_type IntType; + const int memsize = 65536; + const char *const shMemName = test::get_process_id_name(); + const int max = 100; + typedef push_data_function push_data_t; + + try{ + //Named new capable shared mem allocator + //Create shared memory + shared_memory_object::remove(shMemName); + ManagedSharedMemory segment(create_only, shMemName, memsize); + + segment.reserve_named_objects(100); + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyShmList *shmlist = segment.template construct("MyList") + (segment.get_segment_manager()); + + + MyStdList *stdlist = new MyStdList; + + if(push_data_t::execute(max/2, shmlist, stdlist)){ + return 1; + } + + shmlist->erase(shmlist->begin()++); + stdlist->erase(stdlist->begin()++); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + + if(pop_back_function::execute(shmlist, stdlist)){ + return 1; + } + + shmlist->pop_front(); + stdlist->pop_front(); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + shmlist->assign(::boost::make_move_iterator(&aux_vect[0]) + ,::boost::make_move_iterator(&aux_vect[50])); + stdlist->assign(&aux_vect2[0], &aux_vect2[50]); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + } + + if(copied_allocators_equal){ + shmlist->sort(); + stdlist->sort(); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + } + + shmlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + + shmlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + shmlist->insert(shmlist->begin() + ,::boost::make_move_iterator(&aux_vect[0]) + ,::boost::make_move_iterator(&aux_vect[50])); + stdlist->insert(stdlist->begin(), &aux_vect2[0], &aux_vect2[50]); + } + + shmlist->unique(); + stdlist->unique(); + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + + if(copied_allocators_equal){ + shmlist->sort(std::greater()); + stdlist->sort(std::greater()); + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + } + + shmlist->resize(25); + stdlist->resize(25); + shmlist->resize(50); + stdlist->resize(50); + shmlist->resize(0); + stdlist->resize(0); + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + + if(push_data_t::execute(max/2, shmlist, stdlist)){ + return 1; + } + { + MyShmList othershmlist(shmlist->get_allocator()); + MyStdList otherstdlist; + + int listsize = (int)shmlist->size(); + + if(push_data_t::execute(listsize/2, shmlist, stdlist)){ + return 1; + } + + if(copied_allocators_equal){ + shmlist->splice(shmlist->begin(), othershmlist); + stdlist->splice(stdlist->begin(), otherstdlist); + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + } + + listsize = (int)shmlist->size(); + + if(push_data_t::execute(listsize/2, shmlist, stdlist)){ + return 1; + } + + if(push_data_t::execute(listsize/2, &othershmlist, &otherstdlist)){ + return 1; + } + + if(copied_allocators_equal){ + shmlist->sort(std::greater()); + stdlist->sort(std::greater()); + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + + othershmlist.sort(std::greater()); + otherstdlist.sort(std::greater()); + if(!CheckEqualContainers(&othershmlist, &otherstdlist)) + return 1; + + shmlist->merge(othershmlist, std::greater()); + stdlist->merge(otherstdlist, std::greater()); + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + } + + for(int i = 0; i < max; ++i){ + shmlist->insert(shmlist->begin(), IntType(i)); + stdlist->insert(stdlist->begin(), int(i)); + } + if(!CheckEqualContainers(shmlist, stdlist)) + return 1; + } + + segment.template destroy("MyList"); + delete stdlist; + segment.shrink_to_fit_indexes(); + + if(!segment.all_memory_deallocated()) + return 1; + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); + return 0; +} + +} //namespace test{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif diff --git a/src/boost/libs/interprocess/test/managed_mapped_file_test.cpp b/src/boost/libs/interprocess/test/managed_mapped_file_test.cpp new file mode 100644 index 00000000..8185e56c --- /dev/null +++ b/src/boost/libs/interprocess/test/managed_mapped_file_test.cpp @@ -0,0 +1,239 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#if defined(BOOST_INTERPROCESS_MAPPED_FILES) + +#include +#include +#include +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +inline std::string get_filename() +{ + std::string ret (ipcdetail::get_temporary_path()); + ret += "/"; + ret += test::get_process_id_name(); + return ret; +} + +int main () +{ + const int FileSize = 65536*10; + std::string filename(get_filename()); + const char *FileName = filename.c_str(); + + //STL compatible allocator object for memory-mapped file + typedef allocator + allocator_int_t; + //A vector that uses that allocator + typedef boost::interprocess::vector MyVect; + + { + //Remove the file it is already created + file_mapping::remove(FileName); + + const int max = 100; + void *array[max]; + //Named allocate capable shared memory allocator + managed_mapped_file mfile(create_only, FileName, FileSize); + + int i; + //Let's allocate some memory + for(i = 0; i < max; ++i){ + array[i] = mfile.allocate(i+1); + } + + //Deallocate allocated memory + for(i = 0; i < max; ++i){ + mfile.deallocate(array[i]); + } + } + + { + //Remove the file it is already created + file_mapping::remove(FileName); + + //Named allocate capable memory mapped file managed memory class + managed_mapped_file mfile(create_only, FileName, FileSize); + + //Construct the STL-like allocator with the segment manager + const allocator_int_t myallocator (mfile.get_segment_manager()); + + //Construct vector + MyVect *mfile_vect = mfile.construct ("MyVector") (myallocator); + + //Test that vector can be found via name + if(mfile_vect != mfile.find("MyVector").first) + return -1; + + //Destroy and check it is not present + mfile.destroy ("MyVector"); + if(0 != mfile.find("MyVector").first) + return -1; + + //Construct a vector in the memory-mapped file + mfile_vect = mfile.construct ("MyVector") (myallocator); + + //Flush cached data from memory-mapped file to disk + mfile.flush(); + } + { + //Map preexisting file again in memory + managed_mapped_file mfile(open_only, FileName); + + //Check vector is still there + MyVect *mfile_vect = mfile.find("MyVector").first; + if(!mfile_vect) + return -1; + } + + { + { + //Map preexisting file again in copy-on-write + managed_mapped_file mfile(open_copy_on_write, FileName); + + //Check vector is still there + MyVect *mfile_vect = mfile.find("MyVector").first; + if(!mfile_vect) + return -1; + + //Erase vector + mfile.destroy_ptr(mfile_vect); + + //Make sure vector is erased + mfile_vect = mfile.find("MyVector").first; + if(mfile_vect) + return -1; + } + //Now check vector is still in the file + { + //Map preexisting file again in copy-on-write + managed_mapped_file mfile(open_copy_on_write, FileName); + + //Check vector is still there + MyVect *mfile_vect = mfile.find("MyVector").first; + if(!mfile_vect) + return -1; + } + } + { + //Map preexisting file again in copy-on-write + managed_mapped_file mfile(open_read_only, FileName); + + //Check vector is still there + MyVect *mfile_vect = mfile.find("MyVector").first; + if(!mfile_vect) + return -1; + } + { + managed_mapped_file::size_type old_free_memory; + { + //Map preexisting file again in memory + managed_mapped_file mfile(open_only, FileName); + old_free_memory = mfile.get_free_memory(); + } + + //Now grow the file + managed_mapped_file::grow(FileName, FileSize); + + //Map preexisting file again in memory + managed_mapped_file mfile(open_only, FileName); + + //Check vector is still there + MyVect *mfile_vect = mfile.find("MyVector").first; + if(!mfile_vect) + return -1; + + if(mfile.get_size() != (FileSize*2)) + return -1; + if(mfile.get_free_memory() <= old_free_memory) + return -1; + } + { + managed_mapped_file::size_type old_free_memory, next_free_memory, + old_file_size, next_file_size, final_file_size; + { + //Map preexisting file again in memory + managed_mapped_file mfile(open_only, FileName); + old_free_memory = mfile.get_free_memory(); + old_file_size = mfile.get_size(); + } + + //Now shrink the file + managed_mapped_file::shrink_to_fit(FileName); + + { + //Map preexisting file again in memory + managed_mapped_file mfile(open_only, FileName); + next_file_size = mfile.get_size(); + + //Check vector is still there + MyVect *mfile_vect = mfile.find("MyVector").first; + if(!mfile_vect) + return -1; + + next_free_memory = mfile.get_free_memory(); + if(next_free_memory >= old_free_memory) + return -1; + if(old_file_size <= next_file_size) + return -1; + } + + //Now destroy the vector + { + //Map preexisting file again in memory + managed_mapped_file mfile(open_only, FileName); + + //Destroy and check it is not present + mfile.destroy("MyVector"); + if(0 != mfile.find("MyVector").first) + return -1; + } + + //Now shrink the file + managed_mapped_file::shrink_to_fit(FileName); + { + //Map preexisting file again in memory + managed_mapped_file mfile(open_only, FileName); + final_file_size = mfile.get_size(); + if(next_file_size <= final_file_size) + return -1; + } + { + //Now test move semantics + managed_mapped_file original(open_only, FileName); + managed_mapped_file move_ctor(boost::move(original)); + managed_mapped_file move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + } + + file_mapping::remove(FileName); + return 0; +} + +#else //#if defined(BOOST_INTERPROCESS_MAPPED_FILES) + +int main() +{ + return 0; +} + +#endif//#if defined(BOOST_INTERPROCESS_MAPPED_FILES) + +#include diff --git a/src/boost/libs/interprocess/test/managed_shared_memory_test.cpp b/src/boost/libs/interprocess/test/managed_shared_memory_test.cpp new file mode 100644 index 00000000..df850822 --- /dev/null +++ b/src/boost/libs/interprocess/test/managed_shared_memory_test.cpp @@ -0,0 +1,216 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +int main () +{ + const int ShmemSize = 65536; + const char *const ShmemName = test::get_process_id_name(); + + //STL compatible allocator object for memory-mapped shmem + typedef allocator + allocator_int_t; + //A vector that uses that allocator + typedef boost::interprocess::vector MyVect; + + { + //Remove the shmem it is already created + shared_memory_object::remove(ShmemName); + + const int max = 100; + void *array[max]; + //Named allocate capable shared memory allocator + managed_shared_memory shmem(create_only, ShmemName, ShmemSize); + + int i; + //Let's allocate some memory + for(i = 0; i < max; ++i){ + array[i] = shmem.allocate(i+1); + } + + //Deallocate allocated memory + for(i = 0; i < max; ++i){ + shmem.deallocate(array[i]); + } + } + + { + //Remove the shmem it is already created + shared_memory_object::remove(ShmemName); + + //Named allocate capable memory mapped shmem managed memory class + managed_shared_memory shmem(create_only, ShmemName, ShmemSize); + + //Construct the STL-like allocator with the segment manager + const allocator_int_t myallocator (shmem.get_segment_manager()); + + //Construct vector + MyVect *shmem_vect = shmem.construct ("MyVector") (myallocator); + + //Test that vector can be found via name + if(shmem_vect != shmem.find("MyVector").first) + return -1; + + //Destroy and check it is not present + shmem.destroy ("MyVector"); + if(0 != shmem.find("MyVector").first) + return -1; + + //Construct a vector in the memory-mapped shmem + shmem_vect = shmem.construct ("MyVector") (myallocator); + } + { + //Map preexisting shmem again in memory + managed_shared_memory shmem(open_only, ShmemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + } + { + { + //Map preexisting shmem again in copy-on-write + managed_shared_memory shmem(open_copy_on_write, ShmemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + + //Erase vector + shmem.destroy_ptr(shmem_vect); + + //Make sure vector is erased + shmem_vect = shmem.find("MyVector").first; + if(shmem_vect) + return -1; + } + //Now check vector is still in the shmem + { + //Map preexisting shmem again in copy-on-write + managed_shared_memory shmem(open_copy_on_write, ShmemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + } + } + { + //Map preexisting shmem again in copy-on-write + managed_shared_memory shmem(open_read_only, ShmemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + } + #ifndef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW + { + managed_shared_memory::size_type old_free_memory; + { + //Map preexisting shmem again in memory + managed_shared_memory shmem(open_only, ShmemName); + old_free_memory = shmem.get_free_memory(); + } + + //Now grow the shmem + managed_shared_memory::grow(ShmemName, ShmemSize); + + //Map preexisting shmem again in memory + managed_shared_memory shmem(open_only, ShmemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + + if(shmem.get_size() != (ShmemSize*2)) + return -1; + if(shmem.get_free_memory() <= old_free_memory) + return -1; + } + { + managed_shared_memory::size_type old_free_memory, next_free_memory, + old_shmem_size, next_shmem_size, final_shmem_size; + { + //Map preexisting shmem again in memory + managed_shared_memory shmem(open_only, ShmemName); + old_free_memory = shmem.get_free_memory(); + old_shmem_size = shmem.get_size(); + } + + //Now shrink the shmem + managed_shared_memory::shrink_to_fit(ShmemName); + + { + //Map preexisting shmem again in memory + managed_shared_memory shmem(open_only, ShmemName); + next_shmem_size = shmem.get_size(); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + + next_free_memory = shmem.get_free_memory(); + if(next_free_memory >= old_free_memory) + return -1; + if(old_shmem_size <= next_shmem_size) + return -1; + } + + //Now destroy the vector + { + //Map preexisting shmem again in memory + managed_shared_memory shmem(open_only, ShmemName); + + //Destroy and check it is not present + shmem.destroy("MyVector"); + if(0 != shmem.find("MyVector").first) + return -1; + } + + //Now shrink the shmem + managed_shared_memory::shrink_to_fit(ShmemName); + { + //Map preexisting shmem again in memory + managed_shared_memory shmem(open_only, ShmemName); + final_shmem_size = shmem.get_size(); + if(next_shmem_size <= final_shmem_size) + return -1; + } + } + #endif //ifndef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW + + { + //Now test move semantics + managed_shared_memory original(open_only, ShmemName); + managed_shared_memory move_ctor(boost::move(original)); + managed_shared_memory move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + + shared_memory_object::remove(ShmemName); + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/managed_windows_shared_memory_test.cpp b/src/boost/libs/interprocess/test/managed_windows_shared_memory_test.cpp new file mode 100644 index 00000000..aa01119e --- /dev/null +++ b/src/boost/libs/interprocess/test/managed_windows_shared_memory_test.cpp @@ -0,0 +1,152 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#ifdef BOOST_INTERPROCESS_WINDOWS + +#include +#include +#include +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +int main () +{ + const int MemSize = 65536; + const char *const MemName = test::get_process_id_name(); + + //STL compatible allocator object for shared memory + typedef allocator + allocator_int_t; + //A vector that uses that allocator + typedef boost::interprocess::vector MyVect; + + { + const int max = 100; + void *array[max]; + //Named allocate capable shared memory allocator + managed_windows_shared_memory w_shm(create_only, MemName, MemSize); + + int i; + //Let's allocate some memory + for(i = 0; i < max; ++i){ + array[i] = w_shm.allocate(i+1); + } + + //Deallocate allocated memory + for(i = 0; i < max; ++i){ + w_shm.deallocate(array[i]); + } + } + + { + //Named allocate capable shared memory managed memory class + managed_windows_shared_memory w_shm(create_only, MemName, MemSize); + + //Construct the STL-like allocator with the segment manager + const allocator_int_t myallocator (w_shm.get_segment_manager()); + + //Construct vector + MyVect *w_shm_vect = w_shm.construct ("MyVector") (myallocator); + + //Test that vector can be found via name + if(w_shm_vect != w_shm.find("MyVector").first) + return -1; + + //Destroy and check it is not present + w_shm.destroy ("MyVector"); + if(0 != w_shm.find("MyVector").first) + return -1; + + //Construct a vector in the shared memory + w_shm_vect = w_shm.construct ("MyVector") (myallocator); + + { + //Map preexisting segment again in memory + managed_windows_shared_memory w_shm_new(open_only, MemName); + + //Check vector is still there + w_shm_vect = w_shm_new.find("MyVector").first; + if(!w_shm_vect) + return -1; + + if(w_shm_new.get_size() != w_shm.get_size()) + return 1; + + { + { + //Map preexisting shmem again in copy-on-write + managed_windows_shared_memory shmem(open_copy_on_write, MemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + + //Erase vector + shmem.destroy_ptr(shmem_vect); + + //Make sure vector is erased + shmem_vect = shmem.find("MyVector").first; + if(shmem_vect) + return -1; + } + //Now check vector is still in the s + { + //Map preexisting shmem again in copy-on-write + managed_windows_shared_memory shmem(open_copy_on_write, MemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + } + } + { + //Map preexisting shmem again in copy-on-write + managed_windows_shared_memory shmem(open_read_only, MemName); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + } + + //Destroy and check it is not present + w_shm_new.destroy_ptr(w_shm_vect); + if(0 != w_shm_new.find("MyVector").first) + return 1; + + //Now test move semantics + managed_windows_shared_memory original(open_only, MemName); + managed_windows_shared_memory move_ctor(boost::move(original)); + managed_windows_shared_memory move_assign; + move_assign = boost::move(move_ctor); + } + } + + return 0; +} + +#else + +int main() +{ + return 0; +} + +#endif + +#include diff --git a/src/boost/libs/interprocess/test/managed_xsi_shared_memory_test.cpp b/src/boost/libs/interprocess/test/managed_xsi_shared_memory_test.cpp new file mode 100644 index 00000000..14925964 --- /dev/null +++ b/src/boost/libs/interprocess/test/managed_xsi_shared_memory_test.cpp @@ -0,0 +1,174 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) + +#include +#include +#include +#include +#include +#include +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +void remove_shared_memory(const xsi_key &key) +{ + try{ + xsi_shared_memory xsi(open_only, key); + xsi_shared_memory::remove(xsi.get_shmid()); + } + catch(interprocess_exception &e){ + if(e.get_error_code() != not_found_error) + throw; + } +} + +class xsi_shared_memory_remover +{ + public: + xsi_shared_memory_remover(xsi_shared_memory &xsi_shm) + : xsi_shm_(xsi_shm) + {} + + ~xsi_shared_memory_remover() + { xsi_shared_memory::remove(xsi_shm_.get_shmid()); } + private: + xsi_shared_memory & xsi_shm_; +}; + +inline std::string get_filename() +{ + std::string ret (ipcdetail::get_temporary_path()); + ret += "/"; + ret += test::get_process_id_name(); + return ret; +} + +int main () +{ + const int ShmemSize = 65536; + std::string filename = get_filename(); + const char *const ShmemName = filename.c_str(); + + file_mapping::remove(ShmemName); + { ipcdetail::file_wrapper(create_only, ShmemName, read_write); } + xsi_key key(ShmemName, 1); + file_mapping::remove(ShmemName); + int shmid; + + //STL compatible allocator object for memory-mapped shmem + typedef allocator + allocator_int_t; + //A vector that uses that allocator + typedef boost::interprocess::vector MyVect; + + { + //Remove the shmem it is already created + remove_shared_memory(key); + + const int max = 100; + void *array[max]; + //Named allocate capable shared memory allocator + managed_xsi_shared_memory shmem(create_only, key, ShmemSize); + shmid = shmem.get_shmid(); + int i; + //Let's allocate some memory + for(i = 0; i < max; ++i){ + array[i] = shmem.allocate(i+1); + } + + //Deallocate allocated memory + for(i = 0; i < max; ++i){ + shmem.deallocate(array[i]); + } + } + + { + //Remove the shmem it is already created + xsi_shared_memory::remove(shmid); + + //Named allocate capable memory mapped shmem managed memory class + managed_xsi_shared_memory shmem(create_only, key, ShmemSize); + shmid = shmem.get_shmid(); + + //Construct the STL-like allocator with the segment manager + const allocator_int_t myallocator (shmem.get_segment_manager()); + + //Construct vector + MyVect *shmem_vect = shmem.construct ("MyVector") (myallocator); + + //Test that vector can be found via name + if(shmem_vect != shmem.find("MyVector").first) + return -1; + + //Destroy and check it is not present + shmem.destroy ("MyVector"); + if(0 != shmem.find("MyVector").first) + return -1; + + //Construct a vector in the memory-mapped shmem + shmem_vect = shmem.construct ("MyVector") (myallocator); + } + { + //Map preexisting shmem again in memory + managed_xsi_shared_memory shmem(open_only, key); + shmid = shmem.get_shmid(); + + //Check vector is still there + MyVect *shmem_vect = shmem.find("MyVector").first; + if(!shmem_vect) + return -1; + } + + + { + //Now destroy the vector + { + //Map preexisting shmem again in memory + managed_xsi_shared_memory shmem(open_only, key); + shmid = shmem.get_shmid(); + + //Destroy and check it is not present + shmem.destroy("MyVector"); + if(0 != shmem.find("MyVector").first) + return -1; + } + + { + //Now test move semantics + managed_xsi_shared_memory original(open_only, key); + managed_xsi_shared_memory move_ctor(boost::move(original)); + managed_xsi_shared_memory move_assign; + move_assign = boost::move(move_ctor); + move_assign.swap(original); + } + } + + xsi_shared_memory::remove(shmid); + return 0; +} + +#else + +int main() +{ + return 0; +} + +#endif //#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS + +#include diff --git a/src/boost/libs/interprocess/test/map_index_allocation_test.cpp b/src/boost/libs/interprocess/test/map_index_allocation_test.cpp new file mode 100644 index 00000000..27078f45 --- /dev/null +++ b/src/boost/libs/interprocess/test/map_index_allocation_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/map_test.hpp b/src/boost/libs/interprocess/test/map_test.hpp new file mode 100644 index 00000000..0a20a787 --- /dev/null +++ b/src/boost/libs/interprocess/test/map_test.hpp @@ -0,0 +1,593 @@ +//////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +//////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER +#define BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER + +#include +#include "check_equal_containers.hpp" +#include + +// interprocess +#include +// interprocess/detail +#include +// intrusive/detail +#include +#include +// std +#include + +#include "print_container.hpp" +#include "get_process_id_name.hpp" + +template +bool operator ==(std::pair &p1, std::pair &p2) +{ + return p1.first == p2.first && p1.second == p2.second; +} + +namespace boost{ +namespace interprocess{ +namespace test{ + +template +int map_test () +{ + typedef typename MyShmMap::key_type IntType; + typedef boost::interprocess::pair IntPairType; + typedef typename MyStdMap::value_type StdPairType; + const int memsize = 65536; + const char *const shMemName = test::get_process_id_name(); + const int max = 100; + + try{ + //Create shared memory + shared_memory_object::remove(shMemName); + ManagedSharedMemory segment(create_only, shMemName, memsize); + + segment.reserve_named_objects(100); + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyShmMap *shmmap = + segment.template construct("MyShmMap") + (std::less(), segment.get_segment_manager()); + + MyStdMap *stdmap = new MyStdMap; + + MyShmMultiMap *shmmultimap = + segment.template construct("MyShmMultiMap") + (std::less(), segment.get_segment_manager()); + + MyStdMultiMap *stdmultimap = new MyStdMultiMap; + + //Test construction from a range + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + typedef typename MyStdMap::value_type StdValueType; + typedef typename MyStdMap::key_type StdKeyType; + typedef typename MyStdMap::mapped_type StdMappedType; + StdValueType aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + MyShmMap *shmmap2 = + segment.template construct("MyShmMap2") + ( ::boost::make_move_iterator(&aux_vect[0]) + , ::boost::make_move_iterator(aux_vect + 50) + , std::less(), segment.get_segment_manager()); + + MyStdMap *stdmap2 = new MyStdMap(aux_vect2, aux_vect2 + 50); + + MyShmMultiMap *shmmultimap2 = + segment.template construct("MyShmMultiMap2") + ( ::boost::make_move_iterator(&aux_vect3[0]) + , ::boost::make_move_iterator(aux_vect3 + 50) + , std::less(), segment.get_segment_manager()); + + MyStdMultiMap *stdmultimap2 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(shmmap2, stdmap2)) return 1; + if(!CheckEqualContainers(shmmultimap2, stdmultimap2)) return 1; + + //ordered range insertion + //This is really nasty, but we have no other simple choice + for(int i = 0; i < 50; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i)); + } + + for(int i = 0; i < 50; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + MyShmMap *shmmap3 = + segment.template construct("MyShmMap3") + ( ordered_unique_range + , ::boost::make_move_iterator(&aux_vect[0]) + , ::boost::make_move_iterator(aux_vect + 50) + , std::less(), segment.get_segment_manager()); + + MyStdMap *stdmap3 = new MyStdMap(aux_vect2, aux_vect2 + 50); + + MyShmMultiMap *shmmultimap3 = + segment.template construct("MyShmMultiMap3") + ( ordered_range + , ::boost::make_move_iterator(&aux_vect3[0]) + , ::boost::make_move_iterator(aux_vect3 + 50) + , std::less(), segment.get_segment_manager()); + + MyStdMultiMap *stdmultimap3 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50); + + if(!CheckEqualContainers(shmmap3, stdmap3)){ + std::cout << "Error in construct(MyShmMap3)" << std::endl; + return 1; + } + if(!CheckEqualContainers(shmmultimap3, stdmultimap3)){ + std::cout << "Error in construct(MyShmMultiMap3)" << std::endl; + return 1; + } + + segment.destroy_ptr(shmmap2); + segment.destroy_ptr(shmmultimap2); + delete stdmap2; + delete stdmultimap2; + segment.destroy_ptr(shmmap3); + segment.destroy_ptr(shmmultimap3); + delete stdmap3; + delete stdmultimap3; + } + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < max; ++i){ + shmmap->insert(boost::move(aux_vect[i])); + stdmap->insert(StdPairType(i, i)); + shmmultimap->insert(boost::move(aux_vect3[i])); + stdmultimap->insert(StdPairType(i, i)); + } + + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + + typename MyShmMap::iterator it; + typename MyShmMap::const_iterator cit = it; + (void)cit; + + shmmap->erase(shmmap->begin()++); + stdmap->erase(stdmap->begin()++); + shmmultimap->erase(shmmultimap->begin()++); + stdmultimap->erase(stdmultimap->begin()++); + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + + shmmap->erase(shmmap->begin()); + stdmap->erase(stdmap->begin()); + shmmultimap->erase(shmmultimap->begin()); + stdmultimap->erase(stdmultimap->begin()); + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + + //Swapping test + std::less lessfunc; + MyShmMap tmpshmemap2 (lessfunc, segment.get_segment_manager()); + MyStdMap tmpstdmap2; + MyShmMultiMap tmpshmemultimap2(lessfunc, segment.get_segment_manager()); + MyStdMultiMap tmpstdmultimap2; + shmmap->swap(tmpshmemap2); + stdmap->swap(tmpstdmap2); + shmmultimap->swap(tmpshmemultimap2); + stdmultimap->swap(tmpstdmultimap2); + shmmap->swap(tmpshmemap2); + stdmap->swap(tmpstdmap2); + shmmultimap->swap(tmpshmemultimap2); + stdmultimap->swap(tmpstdmultimap2); + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + } + //Insertion from other container + //Initialize values + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + shmmap->insert(::boost::make_move_iterator(&aux_vect[0]), ::boost::make_move_iterator(aux_vect + 50)); + shmmultimap->insert(::boost::make_move_iterator(&aux_vect3[0]), ::boost::make_move_iterator(aux_vect3 + 50)); + for(std::size_t i = 0; i != 50; ++i){ + StdPairType stdpairtype(-1, -1); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + } + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + + for(int i = 0, j = static_cast(shmmap->size()); i < j; ++i){ + shmmap->erase(IntType(i)); + stdmap->erase(i); + shmmultimap->erase(IntType(i)); + stdmultimap->erase(i); + } + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + } + { + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect4[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + IntPairType aux_vect5[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(-1); + IntType i2(-1); + new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + shmmap->insert(::boost::make_move_iterator(&aux_vect[0]), ::boost::make_move_iterator(aux_vect + 50)); + shmmap->insert(::boost::make_move_iterator(&aux_vect3[0]), ::boost::make_move_iterator(aux_vect3 + 50)); + shmmultimap->insert(::boost::make_move_iterator(&aux_vect4[0]), ::boost::make_move_iterator(aux_vect4 + 50)); + shmmultimap->insert(::boost::make_move_iterator(&aux_vect5[0]), ::boost::make_move_iterator(aux_vect5 + 50)); + + for(std::size_t i = 0; i != 50; ++i){ + StdPairType stdpairtype(-1, -1); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + stdmap->insert(stdpairtype); + stdmultimap->insert(stdpairtype); + } + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + + shmmap->erase(shmmap->begin()->first); + stdmap->erase(stdmap->begin()->first); + shmmultimap->erase(shmmultimap->begin()->first); + stdmultimap->erase(stdmultimap->begin()->first); + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + } + + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + IntPairType aux_vect3[max]; + for(int i = 0; i < max; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for(int i = 0; i < max; ++i){ + shmmap->insert(boost::move(aux_vect[i])); + stdmap->insert(StdPairType(i, i)); + shmmultimap->insert(boost::move(aux_vect3[i])); + stdmultimap->insert(StdPairType(i, i)); + } + + if(!CheckEqualPairContainers(shmmap, stdmap)) return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1; + + for(int i = 0; i < max; ++i){ + IntPairType intpair; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + shmmap->insert(shmmap->begin(), boost::move(intpair)); + stdmap->insert(stdmap->begin(), StdPairType(i, i)); + //PrintContainers(shmmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + shmmultimap->insert(shmmultimap->begin(), boost::move(intpair)); + stdmultimap->insert(stdmultimap->begin(), StdPairType(i, i)); + //PrintContainers(shmmultimap, stdmultimap); + if(!CheckEqualPairContainers(shmmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + shmmap->insert(shmmap->end(), boost::move(intpair)); + stdmap->insert(stdmap->end(), StdPairType(i, i)); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + shmmultimap->insert(shmmultimap->end(), boost::move(intpair)); + stdmultimap->insert(stdmultimap->end(), StdPairType(i, i)); + if(!CheckEqualPairContainers(shmmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + shmmap->insert(shmmap->lower_bound(IntType(i)), boost::move(intpair)); + stdmap->insert(stdmap->lower_bound(i), StdPairType(i, i)); + //PrintContainers(shmmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + shmmultimap->insert(shmmultimap->lower_bound(boost::move(i1)), boost::move(intpair)); + stdmultimap->insert(stdmultimap->lower_bound(i), StdPairType(i, i)); + } + + //PrintContainers(shmmultimap, stdmultimap); + if(!CheckEqualPairContainers(shmmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) + return 1; + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + shmmap->insert(shmmap->upper_bound(boost::move(i1)), boost::move(intpair)); + stdmap->insert(stdmap->upper_bound(i), StdPairType(i, i)); + } + //PrintContainers(shmmap, stdmap); + { + IntType i1(i); + IntType i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + { + IntType i1(i); + shmmultimap->insert(shmmultimap->upper_bound(boost::move(i1)), boost::move(intpair)); + stdmultimap->insert(stdmultimap->upper_bound(i), StdPairType(i, i)); + } + //PrintContainers(shmmultimap, stdmultimap); + if(!CheckEqualPairContainers(shmmap, stdmap)) + return 1; + if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) + return 1; + } + + //Compare count with std containers + for(int i = 0; i < max; ++i){ + if(shmmap->count(IntType(i)) != stdmap->count(i)){ + return -1; + } + + if(shmmultimap->count(IntType(i)) != stdmultimap->count(i)){ + return -1; + } + } + + //Now do count exercise + shmmap->erase(shmmap->begin(), shmmap->end()); + shmmultimap->erase(shmmultimap->begin(), shmmultimap->end()); + shmmap->clear(); + shmmultimap->clear(); + + for(int j = 0; j < 3; ++j) + for(int i = 0; i < 100; ++i){ + IntPairType intpair; + { + IntType i1(i), i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + shmmap->insert(boost::move(intpair)); + { + IntType i1(i), i2(i); + new(&intpair)IntPairType(boost::move(i1), boost::move(i2)); + } + shmmultimap->insert(boost::move(intpair)); + if(shmmap->count(IntType(i)) != typename MyShmMultiMap::size_type(1)) + return 1; + if(shmmultimap->count(IntType(i)) != typename MyShmMultiMap::size_type(j+1)) + return 1; + } + } + + segment.template destroy("MyShmMap"); + delete stdmap; + segment.destroy_ptr(shmmultimap); + delete stdmultimap; + + segment.shrink_to_fit_indexes(); + + if(!segment.all_memory_deallocated()) + return 1; + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); + return 0; +} + +template +int map_test_copyable () +{ + typedef typename MyShmMap::key_type IntType; + typedef boost::interprocess::pair IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + const int memsize = 65536; + const char *const shMemName = test::get_process_id_name(); + const int max = 100; + + try{ + //Create shared memory + shared_memory_object::remove(shMemName); + ManagedSharedMemory segment(create_only, shMemName, memsize); + + segment.reserve_named_objects(100); + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyShmMap *shmmap = + segment.template construct("MyShmMap") + (std::less(), segment.get_segment_manager()); + + MyStdMap *stdmap = new MyStdMap; + + MyShmMultiMap *shmmultimap = + segment.template construct("MyShmMultiMap") + (std::less(), segment.get_segment_manager()); + + MyStdMultiMap *stdmultimap = new MyStdMultiMap; + + int i; + for(i = 0; i < max; ++i){ + { + IntType i1(i), i2(i); + IntPairType intpair1(boost::move(i1), boost::move(i2)); + shmmap->insert(boost::move(intpair1)); + stdmap->insert(StdPairType(i, i)); + } + { + IntType i1(i), i2(i); + IntPairType intpair2(boost::move(i1), boost::move(i2)); + shmmultimap->insert(boost::move(intpair2)); + stdmultimap->insert(StdPairType(i, i)); + } + } + if(!CheckEqualContainers(shmmap, stdmap)) return 1; + if(!CheckEqualContainers(shmmultimap, stdmultimap)) return 1; + + { + //Now, test copy constructor + MyShmMap shmmapcopy(*shmmap); + MyStdMap stdmapcopy(*stdmap); + MyShmMultiMap shmmmapcopy(*shmmultimap); + MyStdMultiMap stdmmapcopy(*stdmultimap); + + if(!CheckEqualContainers(&shmmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&shmmmapcopy, &stdmmapcopy)) + return 1; + + //And now assignment + shmmapcopy = *shmmap; + stdmapcopy = *stdmap; + shmmmapcopy = *shmmultimap; + stdmmapcopy = *stdmultimap; + + if(!CheckEqualContainers(&shmmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&shmmmapcopy, &stdmmapcopy)) + return 1; + delete stdmap; + delete stdmultimap; + segment.destroy_ptr(shmmap); + segment.destroy_ptr(shmmultimap); + } + segment.shrink_to_fit_indexes(); + + if(!segment.all_memory_deallocated()) + return 1; + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); + return 0; +} + +} //namespace test{ +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER diff --git a/src/boost/libs/interprocess/test/mapped_file_test.cpp b/src/boost/libs/interprocess/test/mapped_file_test.cpp new file mode 100644 index 00000000..9d19977a --- /dev/null +++ b/src/boost/libs/interprocess/test/mapped_file_test.cpp @@ -0,0 +1,100 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_INTERPROCESS_MAPPED_FILES) + +#include +#include +#include +#include +#include +#include +#include "named_creation_template.hpp" +#include +#include +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +static const std::size_t FileSize = 1000; +inline std::string get_filename() +{ + std::string ret (ipcdetail::get_temporary_path()); + ret += "/"; + ret += test::get_process_id_name(); + return ret; +} + +struct file_destroyer +{ + ~file_destroyer() + { + //The last destructor will destroy the file + file_mapping::remove(get_filename().c_str()); + } +}; + +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +class mapped_file_creation_test_wrapper + : public file_destroyer + , public boost::interprocess::ipcdetail::managed_open_or_create_impl + +{ + typedef boost::interprocess::ipcdetail::managed_open_or_create_impl + mapped_file; + public: + mapped_file_creation_test_wrapper(boost::interprocess::create_only_t) + : mapped_file(boost::interprocess::create_only, get_filename().c_str(), FileSize, read_write, 0, permissions()) + {} + + mapped_file_creation_test_wrapper(boost::interprocess::open_only_t) + : mapped_file(boost::interprocess::open_only, get_filename().c_str(), read_write, 0) + {} + + mapped_file_creation_test_wrapper(boost::interprocess::open_or_create_t) + : mapped_file(boost::interprocess::open_or_create, get_filename().c_str(), FileSize, read_write, 0, permissions()) + {} +}; + +int main () +{ + typedef boost::interprocess::ipcdetail::managed_open_or_create_impl + mapped_file; + file_mapping::remove(get_filename().c_str()); + test::test_named_creation(); + + //Create and get name, size and address + { + mapped_file file1(create_only, get_filename().c_str(), FileSize, read_write, 0, permissions()); + + //Overwrite all memory + std::memset(file1.get_user_address(), 0, file1.get_user_size()); + + //Now test move semantics + mapped_file move_ctor(boost::move(file1)); + mapped_file move_assign; + move_assign = boost::move(move_ctor); + } +// file_mapping::remove(get_filename().c_str()); + return 0; +} + +#include + +#else //#if !defined(BOOST_INTERPROCESS_MAPPED_FILES) + +int main() +{ + return 0; +} + +#endif//#if !defined(BOOST_INTERPROCESS_MAPPED_FILES) diff --git a/src/boost/libs/interprocess/test/memory_algorithm_test.cpp b/src/boost/libs/interprocess/test/memory_algorithm_test.cpp new file mode 100644 index 00000000..9210640a --- /dev/null +++ b/src/boost/libs/interprocess/test/memory_algorithm_test.cpp @@ -0,0 +1,91 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include //make_unsigned, alignment_of +#include "memory_algorithm_test_template.hpp" +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +const int Memsize = 16384; +const char *const shMemName = test::get_process_id_name(); + +int test_simple_seq_fit() +{ + //A shared memory with simple sequential fit algorithm + typedef basic_managed_shared_memory + + ,null_index + > my_managed_shared_memory; + + //Create shared memory + shared_memory_object::remove(shMemName); + my_managed_shared_memory segment(create_only, shMemName, Memsize); + + //Now take the segment manager and launch memory test + if(!test::test_all_allocation(*segment.get_segment_manager())){ + return 1; + } + return 0; +} + +template +int test_rbtree_best_fit() +{ + //A shared memory with red-black tree best fit algorithm + typedef basic_managed_shared_memory + , Alignment> + ,null_index + > my_managed_shared_memory; + + //Create shared memory + shared_memory_object::remove(shMemName); + my_managed_shared_memory segment(create_only, shMemName, Memsize); + + //Now take the segment manager and launch memory test + if(!test::test_all_allocation(*segment.get_segment_manager())){ + return 1; + } + return 0; +} + +int main () +{ + const std::size_t void_ptr_align = ::boost::container::dtl::alignment_of >::value; + + if(test_simple_seq_fit()){ + return 1; + } + if(test_rbtree_best_fit()){ + return 1; + } + if(test_rbtree_best_fit<2*void_ptr_align>()){ + return 1; + } + if(test_rbtree_best_fit<4*void_ptr_align>()){ + return 1; + } + + shared_memory_object::remove(shMemName); + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/memory_algorithm_test_template.hpp b/src/boost/libs/interprocess/test/memory_algorithm_test_template.hpp new file mode 100644 index 00000000..10e880e7 --- /dev/null +++ b/src/boost/libs/interprocess/test/memory_algorithm_test_template.hpp @@ -0,0 +1,1036 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER +#define BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER + +#include + +#include + +#include +#include +#include //std::nothrow +#include //std::memset + +namespace boost { namespace interprocess { namespace test { + +enum deallocation_type { DirectDeallocation, InverseDeallocation, MixedDeallocation, EndDeallocationType }; + +//This test allocates until there is no more memory +//and after that deallocates all in the inverse order +template +bool test_allocation(Allocator &a) +{ + for( deallocation_type t = DirectDeallocation + ; t != EndDeallocationType + ; t = (deallocation_type)((int)t + 1)){ + std::vector buffers; + typename Allocator::size_type free_memory = a.get_free_memory(); + + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + buffers.push_back(ptr); + } + + switch(t){ + case DirectDeallocation: + { + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + a.deallocate(buffers[j]); + } + } + break; + case InverseDeallocation: + { + for(int j = (int)buffers.size() + ;j-- + ;){ + a.deallocate(buffers[j]); + } + } + break; + case MixedDeallocation: + { + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + } + break; + default: + break; + } + bool ok = free_memory == a.get_free_memory() && + a.all_memory_deallocated() && a.check_sanity(); + if(!ok) return ok; + } + return true; +} + +//This test allocates until there is no more memory +//and after that tries to shrink all the buffers to the +//half of the original size +template +bool test_allocation_shrink(Allocator &a) +{ + std::vector buffers; + + //Allocate buffers with extra memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i*2, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + buffers.push_back(ptr); + } + + //Now shrink to half + for(int i = 0, max = (int)buffers.size() + ;i < max + ; ++i){ + typename Allocator::size_type received_size; + char *reuse = static_cast(buffers[i]); + if(a.template allocation_command + ( boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, i*2 + , received_size = i, reuse)){ + if(received_size > std::size_t(i*2)){ + return false; + } + if(received_size < std::size_t(i)){ + return false; + } + std::memset(buffers[i], 0, a.size(buffers[i])); + } + } + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates until there is no more memory +//and after that tries to expand all the buffers to +//avoid the wasted internal fragmentation +template +bool test_allocation_expand(Allocator &a) +{ + std::vector buffers; + + //Allocate buffers with extra memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + buffers.push_back(ptr); + } + + //Now try to expand to the double of the size + for(int i = 0, max = (int)buffers.size() + ;i < max + ;++i){ + typename Allocator::size_type received_size; + std::size_t min_size = i+1; + std::size_t preferred_size = i*2; + preferred_size = min_size > preferred_size ? min_size : preferred_size; + + char *reuse = static_cast(buffers[i]); + while(a.template allocation_command + ( boost::interprocess::expand_fwd | boost::interprocess::nothrow_allocation, min_size + , received_size = preferred_size, reuse)){ + //Check received size is bigger than minimum + if(received_size < min_size){ + return false; + } + //Now, try to expand further + min_size = received_size+1; + preferred_size = min_size*2; + } + } + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates until there is no more memory +//and after that tries to expand all the buffers to +//avoid the wasted internal fragmentation +template +bool test_allocation_shrink_and_expand(Allocator &a) +{ + std::vector buffers; + std::vector received_sizes; + std::vector size_reduced; + + //Allocate buffers wand store received sizes + for(int i = 0; true; ++i){ + typename Allocator::size_type received_size; + char *reuse = 0; + void *ptr = a.template allocation_command + ( boost::interprocess::allocate_new | boost::interprocess::nothrow_allocation, i, received_size = i*2, reuse); + if(!ptr){ + ptr = a.template allocation_command + ( boost::interprocess::allocate_new | boost::interprocess::nothrow_allocation, 1, received_size = i*2, reuse); + if(!ptr) + break; + } + buffers.push_back(ptr); + received_sizes.push_back(received_size); + } + + //Now shrink to half + for(int i = 0, max = (int)buffers.size() + ; i < max + ; ++i){ + typename Allocator::size_type received_size; + char *reuse = static_cast(buffers[i]); + if(a.template allocation_command + ( boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_sizes[i] + , received_size = i, reuse)){ + if(received_size > std::size_t(received_sizes[i])){ + return false; + } + if(received_size < std::size_t(i)){ + return false; + } + size_reduced.push_back(received_size != received_sizes[i]); + } + } + + //Now try to expand to the original size + for(int i = 0, max = (int)buffers.size() + ;i < max + ;++i){ + typename Allocator::size_type received_size; + std::size_t request_size = received_sizes[i]; + char *reuse = static_cast(buffers[i]); + if(a.template allocation_command + ( boost::interprocess::expand_fwd | boost::interprocess::nothrow_allocation, request_size + , received_size = request_size, reuse)){ + if(received_size != received_sizes[i]){ + return false; + } + } + else{ + return false; + } + } + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates until there is no more memory +//and after that deallocates the odd buffers to +//make room for expansions. The expansion will probably +//success since the deallocation left room for that. +template +bool test_allocation_deallocation_expand(Allocator &a) +{ + std::vector buffers; + + //Allocate buffers with extra memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + buffers.push_back(ptr); + } + + //Now deallocate the half of the blocks + //so expand maybe can merge new free blocks + for(int i = 0, max = (int)buffers.size() + ;i < max + ;++i){ + if(i%2){ + a.deallocate(buffers[i]); + buffers[i] = 0; + } + } + + //Now try to expand to the double of the size + for(int i = 0, max = (int)buffers.size() + ;i < max + ;++i){ + // + if(buffers[i]){ + typename Allocator::size_type received_size; + std::size_t min_size = i+1; + std::size_t preferred_size = i*2; + preferred_size = min_size > preferred_size ? min_size : preferred_size; + + char *reuse = static_cast(buffers[i]); + while(a.template allocation_command + ( boost::interprocess::expand_fwd | boost::interprocess::nothrow_allocation, min_size + , received_size = preferred_size, reuse)){ + //Check received size is bigger than minimum + if(received_size < min_size){ + return false; + } + //Now, try to expand further + min_size = received_size+1; + preferred_size = min_size*2; + } + } + } + + //Now erase null values from the vector + buffers.erase( std::remove(buffers.begin(), buffers.end(), static_cast(0)) + , buffers.end()); + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates until there is no more memory +//and after that deallocates all except the last. +//If the allocation algorithm is a bottom-up algorithm +//the last buffer will be in the end of the segment. +//Then the test will start expanding backwards, until +//the buffer fills all the memory +template +bool test_allocation_with_reuse(Allocator &a) +{ + //We will repeat this test for different sized elements + for(int sizeof_object = 1; sizeof_object < 20; ++sizeof_object){ + std::vector buffers; + + //Allocate buffers with extra memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i*sizeof_object, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + buffers.push_back(ptr); + } + + //Now deallocate all except the latest + //Now try to expand to the double of the sizeof_object + for(int i = 0, max = (int)buffers.size() - 1 + ;i < max + ;++i){ + a.deallocate(buffers[i]); + } + + //Save the unique buffer and clear vector + void *ptr = buffers.back(); + buffers.clear(); + + //Now allocate with reuse + typename Allocator::size_type received_size = 0; + for(int i = 0; true; ++i){ + std::size_t min_size = (received_size + 1); + std::size_t prf_size = (received_size + (i+1)*2); + void *reuse = ptr; + void *ret = a.raw_allocation_command + ( boost::interprocess::expand_bwd | boost::interprocess::nothrow_allocation, min_size + , received_size = prf_size, reuse, sizeof_object); + if(!ret) + break; + //If we have memory, this must be a buffer reuse + if(!reuse) + return 1; + if(received_size < min_size) + return 1; + ptr = ret; + } + //There is only a single block so deallocate it + a.deallocate(ptr); + + if(!a.all_memory_deallocated() || !a.check_sanity()) + return false; + } + return true; +} + + +//This test allocates memory with different alignments +//and checks returned memory is aligned. +template +bool test_aligned_allocation(Allocator &a) +{ + //Allocate aligned buffers in a loop + //and then deallocate it + bool continue_loop = true; + for(unsigned int i = 1; continue_loop; i <<= 1){ + for(unsigned int j = 1; true; j <<= 1){ + void *ptr = a.allocate_aligned(i-1, j, std::nothrow); + if(!ptr){ + if(j == 1) + continue_loop = false; + break; + } + + if(((std::size_t)ptr & (j - 1)) != 0) + return false; + a.deallocate(ptr); + if(!a.all_memory_deallocated() || !a.check_sanity()){ + return false; + } + } + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates memory with different alignments +//and checks returned memory is aligned. +template +bool test_continuous_aligned_allocation(Allocator &a) +{ + std::vector buffers; + //Allocate aligned buffers in a loop + //and then deallocate it + bool continue_loop = true; + for(unsigned i = 1; continue_loop && i; i <<= 1){ + for(unsigned int j = 1; j; j <<= 1){ + for(bool any_allocated = false; 1;){ + void *ptr = a.allocate_aligned(i-1, j, std::nothrow); + buffers.push_back(ptr); + if(!ptr){ + if(j == 1 && !any_allocated){ + continue_loop = false; + } + break; + } + else{ + any_allocated = true; + } + + if(((std::size_t)ptr & (j - 1)) != 0) + return false; + } + //Deallocate all + for(unsigned int k = (int)buffers.size(); k--;){ + a.deallocate(buffers[k]); + } + buffers.clear(); + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + if(!continue_loop) + break; + } + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates memory, writes it with a non-zero value and +//tests zero_free_memory initializes to zero for the next allocation +template +bool test_clear_free_memory(Allocator &a) +{ + std::vector buffers; + + //Allocate memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 1, size); + buffers.push_back(ptr); + } + + //Mark it + for(int i = 0, max = buffers.size(); i < max; ++i){ + std::memset(buffers[i], 1, i); + } + + //Deallocate all + for(int j = (int)buffers.size() + ;j-- + ;){ + a.deallocate(buffers[j]); + } + buffers.clear(); + + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + //Now clear all free memory + a.zero_free_memory(); + + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + //Now test all allocated memory is zero + //Allocate memory + const char *first_addr = 0; + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + if(i == 0){ + first_addr = (char*)ptr; + } + std::size_t memsize = a.size(ptr); + buffers.push_back(ptr); + + for(int j = 0; j < (int)memsize; ++j){ + if(static_cast((char*)ptr)[j]){ + std::cout << "Zero memory test failed. in buffer " << i + << " byte " << j << " first address " << (void*) first_addr << " offset " << ((char*)ptr+j) - (char*)first_addr << " memsize: " << memsize << std::endl; + return false; + } + } + } + + //Deallocate all + for(int j = (int)buffers.size() + ;j-- + ;){ + a.deallocate(buffers[j]); + } + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + return true; +} + + +//This test uses tests grow and shrink_to_fit functions +template +bool test_grow_shrink_to_fit(Allocator &a) +{ + std::vector buffers; + + typename Allocator::size_type original_size = a.get_size(); + typename Allocator::size_type original_free = a.get_free_memory(); + + a.shrink_to_fit(); + + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + typename Allocator::size_type shrunk_size = a.get_size(); + typename Allocator::size_type shrunk_free_memory = a.get_free_memory(); + if(shrunk_size != a.get_min_size()) + return 1; + + a.grow(original_size - shrunk_size); + + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + if(original_size != a.get_size()) + return false; + if(original_free != a.get_free_memory()) + return false; + + //Allocate memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + buffers.push_back(ptr); + } + + //Now deallocate the half of the blocks + //so expand maybe can merge new free blocks + for(int i = 0, max = (int)buffers.size() + ;i < max + ;++i){ + if(i%2){ + a.deallocate(buffers[i]); + buffers[i] = 0; + } + } + + //Deallocate the rest of the blocks + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%5)*((int)buffers.size())/4; + if(pos == int(buffers.size())) + --pos; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + typename Allocator::size_type old_free = a.get_free_memory(); + a.shrink_to_fit(); + if(!a.check_sanity()) return false; + if(original_size < a.get_size()) return false; + if(old_free < a.get_free_memory()) return false; + + a.grow(original_size - a.get_size()); + + if(!a.check_sanity()) return false; + if(original_size != a.get_size()) return false; + if(old_free != a.get_free_memory()) return false; + } + + //Now shrink it to the maximum + a.shrink_to_fit(); + + if(a.get_size() != a.get_min_size()) + return 1; + + if(shrunk_free_memory != a.get_free_memory()) + return 1; + + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + a.grow(original_size - shrunk_size); + + if(original_size != a.get_size()) + return false; + if(original_free != a.get_free_memory()) + return false; + + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + return true; +} + +//This test allocates multiple values until there is no more memory +//and after that deallocates all in the inverse order +template +bool test_many_equal_allocation(Allocator &a) +{ + for( deallocation_type t = DirectDeallocation + ; t != EndDeallocationType + ; t = (deallocation_type)((int)t + 1)){ + typename Allocator::size_type free_memory = a.get_free_memory(); + + std::vector buffers2; + + //Allocate buffers with extra memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + if(!a.check_sanity()) + return false; + buffers2.push_back(ptr); + } + + //Now deallocate the half of the blocks + //so expand maybe can merge new free blocks + for(int i = 0, max = (int)buffers2.size() + ;i < max + ;++i){ + if(i%2){ + a.deallocate(buffers2[i]); + buffers2[i] = 0; + } + } + + if(!a.check_sanity()) + return false; + + typedef typename Allocator::multiallocation_chain multiallocation_chain; + std::vector buffers; + for(int i = 0; true; ++i){ + multiallocation_chain chain; + a.allocate_many(std::nothrow, i+1, (i+1)*2, chain); + if(chain.empty()) + break; + + typename multiallocation_chain::size_type n = chain.size(); + while(!chain.empty()){ + buffers.push_back(ipcdetail::to_raw_pointer(chain.pop_front())); + } + if(n != std::size_t((i+1)*2)) + return false; + } + + if(!a.check_sanity()) + return false; + + switch(t){ + case DirectDeallocation: + { + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + a.deallocate(buffers[j]); + } + } + break; + case InverseDeallocation: + { + for(int j = (int)buffers.size() + ;j-- + ;){ + a.deallocate(buffers[j]); + } + } + break; + case MixedDeallocation: + { + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + } + break; + default: + break; + } + + //Deallocate the rest of the blocks + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers2.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers2.size())/4; + a.deallocate(buffers2[pos]); + buffers2.erase(buffers2.begin()+pos); + } + + bool ok = free_memory == a.get_free_memory() && + a.all_memory_deallocated() && a.check_sanity(); + if(!ok) return ok; + } + return true; +} + +//This test allocates multiple values until there is no more memory +//and after that deallocates all in the inverse order +template +bool test_many_different_allocation(Allocator &a) +{ + typedef typename Allocator::multiallocation_chain multiallocation_chain; + const std::size_t ArraySize = 11; + typename Allocator::size_type requested_sizes[ArraySize]; + for(std::size_t i = 0; i < ArraySize; ++i){ + requested_sizes[i] = 4*i; + } + + for( deallocation_type t = DirectDeallocation + ; t != EndDeallocationType + ; t = (deallocation_type)((int)t + 1)){ + typename Allocator::size_type free_memory = a.get_free_memory(); + + std::vector buffers2; + + //Allocate buffers with extra memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) + break; + std::size_t size = a.size(ptr); + std::memset(ptr, 0, size); + buffers2.push_back(ptr); + } + + //Now deallocate the half of the blocks + //so expand maybe can merge new free blocks + for(int i = 0, max = (int)buffers2.size() + ;i < max + ;++i){ + if(i%2){ + a.deallocate(buffers2[i]); + buffers2[i] = 0; + } + } + + std::vector buffers; + for(int i = 0; true; ++i){ + multiallocation_chain chain; + a.allocate_many(std::nothrow, requested_sizes, ArraySize, 1, chain); + if(chain.empty()) + break; + typename multiallocation_chain::size_type n = chain.size(); + while(!chain.empty()){ + buffers.push_back(ipcdetail::to_raw_pointer(chain.pop_front())); + } + if(n != ArraySize) + return false; + } + + switch(t){ + case DirectDeallocation: + { + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + a.deallocate(buffers[j]); + } + } + break; + case InverseDeallocation: + { + for(int j = (int)buffers.size() + ;j-- + ;){ + a.deallocate(buffers[j]); + } + } + break; + case MixedDeallocation: + { + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + } + break; + default: + break; + } + + //Deallocate the rest of the blocks + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers2.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers2.size())/4; + a.deallocate(buffers2[pos]); + buffers2.erase(buffers2.begin()+pos); + } + + bool ok = free_memory == a.get_free_memory() && + a.all_memory_deallocated() && a.check_sanity(); + if(!ok) return ok; + } + return true; +} + +//This test allocates multiple values until there is no more memory +//and after that deallocates all in the inverse order +template +bool test_many_deallocation(Allocator &a) +{ + typedef typename Allocator::multiallocation_chain multiallocation_chain; + + typedef typename Allocator::multiallocation_chain multiallocation_chain; + const std::size_t ArraySize = 11; + vector buffers; + typename Allocator::size_type requested_sizes[ArraySize]; + for(std::size_t i = 0; i < ArraySize; ++i){ + requested_sizes[i] = 4*i; + } + typename Allocator::size_type free_memory = a.get_free_memory(); + + { + for(int i = 0; true; ++i){ + multiallocation_chain chain; + a.allocate_many(std::nothrow, requested_sizes, ArraySize, 1, chain); + if(chain.empty()) + break; + buffers.push_back(boost::move(chain)); + } + for(int i = 0, max = (int)buffers.size(); i != max; ++i){ + a.deallocate_many(buffers[i]); + } + buffers.clear(); + bool ok = free_memory == a.get_free_memory() && + a.all_memory_deallocated() && a.check_sanity(); + if(!ok) return ok; + } + + { + for(int i = 0; true; ++i){ + multiallocation_chain chain; + a.allocate_many(std::nothrow, i*4, ArraySize, chain); + if(chain.empty()) + break; + buffers.push_back(boost::move(chain)); + } + for(int i = 0, max = (int)buffers.size(); i != max; ++i){ + a.deallocate_many(buffers[i]); + } + buffers.clear(); + + bool ok = free_memory == a.get_free_memory() && + a.all_memory_deallocated() && a.check_sanity(); + if(!ok) return ok; + } + + return true; +} + + +//This function calls all tests +template +bool test_all_allocation(Allocator &a) +{ + std::cout << "Starting test_allocation. Class: " + << typeid(a).name() << std::endl; + + if(!test_allocation(a)){ + std::cout << "test_allocation_direct_deallocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_many_equal_allocation. Class: " + << typeid(a).name() << std::endl; + + if(!test_many_equal_allocation(a)){ + std::cout << "test_many_equal_allocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_many_different_allocation. Class: " + << typeid(a).name() << std::endl; + + if(!test_many_different_allocation(a)){ + std::cout << "test_many_different_allocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + if(!test_many_deallocation(a)){ + std::cout << "test_many_deallocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_allocation_shrink. Class: " + << typeid(a).name() << std::endl; + + if(!test_allocation_shrink(a)){ + std::cout << "test_allocation_shrink failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + if(!test_allocation_shrink_and_expand(a)){ + std::cout << "test_allocation_shrink_and_expand failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_allocation_expand. Class: " + << typeid(a).name() << std::endl; + + if(!test_allocation_expand(a)){ + std::cout << "test_allocation_expand failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_allocation_deallocation_expand. Class: " + << typeid(a).name() << std::endl; + + if(!test_allocation_deallocation_expand(a)){ + std::cout << "test_allocation_deallocation_expand failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_allocation_with_reuse. Class: " + << typeid(a).name() << std::endl; + + if(!test_allocation_with_reuse(a)){ + std::cout << "test_allocation_with_reuse failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_aligned_allocation. Class: " + << typeid(a).name() << std::endl; + + if(!test_aligned_allocation(a)){ + std::cout << "test_aligned_allocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_continuous_aligned_allocation. Class: " + << typeid(a).name() << std::endl; + + if(!test_continuous_aligned_allocation(a)){ + std::cout << "test_continuous_aligned_allocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_clear_free_memory. Class: " + << typeid(a).name() << std::endl; + + if(!test_clear_free_memory(a)){ + std::cout << "test_clear_free_memory failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + std::cout << "Starting test_grow_shrink_to_fit. Class: " + << typeid(a).name() << std::endl; + + if(!test_grow_shrink_to_fit(a)){ + std::cout << "test_grow_shrink_to_fit failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + return true; +} + +}}} //namespace boost { namespace interprocess { namespace test { + +#include + +#endif //BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER + diff --git a/src/boost/libs/interprocess/test/message_queue_test.cpp b/src/boost/libs/interprocess/test/message_queue_test.cpp new file mode 100644 index 00000000..fe76cad5 --- /dev/null +++ b/src/boost/libs/interprocess/test/message_queue_test.cpp @@ -0,0 +1,376 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +// intrusive/detail +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "get_process_id_name.hpp" + +//////////////////////////////////////////////////////////////////////////////// +// // +// This example tests the process shared message queue. // +// // +//////////////////////////////////////////////////////////////////////////////// + +using namespace boost::interprocess; + +//This test inserts messages with different priority and marks them with a +//time-stamp to check if receiver obtains highest priority messages first and +//messages with same priority are received in fifo order +bool test_priority_order() +{ + message_queue::remove(test::get_process_id_name()); + { + message_queue mq1 + (open_or_create, test::get_process_id_name(), 100, sizeof(std::size_t)), + mq2 + (open_or_create, test::get_process_id_name(), 100, sizeof(std::size_t)); + + //We test that the queue is ordered by priority and in the + //same priority, is a FIFO + message_queue::size_type recvd = 0; + unsigned int priority = 0; + std::size_t tstamp; + unsigned int priority_prev; + std::size_t tstamp_prev; + + //We will send 100 message with priority 0-9 + //The message will contain the timestamp of the message + for(std::size_t i = 0; i < 100; ++i){ + tstamp = i; + mq1.send(&tstamp, sizeof(tstamp), (unsigned int)(i%10)); + } + + priority_prev = (std::numeric_limits::max)(); + tstamp_prev = 0; + + //Receive all messages and test those are ordered + //by priority and by FIFO in the same priority + for(std::size_t i = 0; i < 100; ++i){ + mq1.receive(&tstamp, sizeof(tstamp), recvd, priority); + if(priority > priority_prev) + return false; + if(priority == priority_prev && + tstamp <= tstamp_prev){ + return false; + } + priority_prev = priority; + tstamp_prev = tstamp; + } + + //Now retry it with different priority order + for(std::size_t i = 0; i < 100; ++i){ + tstamp = i; + mq1.send(&tstamp, sizeof(tstamp), (unsigned int)(9 - i%10)); + } + + priority_prev = (std::numeric_limits::max)(); + tstamp_prev = 0; + + //Receive all messages and test those are ordered + //by priority and by FIFO in the same priority + for(std::size_t i = 0; i < 100; ++i){ + mq1.receive(&tstamp, sizeof(tstamp), recvd, priority); + if(priority > priority_prev) + return false; + if(priority == priority_prev && + tstamp <= tstamp_prev){ + return false; + } + priority_prev = priority; + tstamp_prev = tstamp; + } + } + message_queue::remove(test::get_process_id_name()); + return true; +} + +//[message_queue_test_test_serialize_db +//This test creates a in memory data-base using Interprocess machinery and +//serializes it through a message queue. Then rebuilds the data-base in +//another buffer and checks it against the original data-base +bool test_serialize_db() +{ + //Typedef data to create a Interprocess map + typedef std::pair MyPair; + typedef std::less MyLess; + typedef node_allocator + node_allocator_t; + typedef map, + node_allocator_t> + MyMap; + + //Some constants + const std::size_t BufferSize = 65536; + const std::size_t MaxMsgSize = 100; + + //Allocate a memory buffer to hold the destiny database using vector + std::vector buffer_destiny(BufferSize, 0); + + message_queue::remove(test::get_process_id_name()); + { + //Create the message-queues + message_queue mq1(create_only, test::get_process_id_name(), 1, MaxMsgSize); + + //Open previously created message-queue simulating other process + message_queue mq2(open_only, test::get_process_id_name()); + + //A managed heap memory to create the origin database + managed_heap_memory db_origin(buffer_destiny.size()); + + //Construct the map in the first buffer + MyMap *map1 = db_origin.construct("MyMap") + (MyLess(), + db_origin.get_segment_manager()); + if(!map1) + return false; + + //Fill map1 until is full + try{ + std::size_t i = 0; + while(1){ + (*map1)[i] = i; + ++i; + } + } + catch(boost::interprocess::bad_alloc &){} + + //Data control data sending through the message queue + std::size_t sent = 0; + message_queue::size_type recvd = 0; + message_queue::size_type total_recvd = 0; + unsigned int priority; + + //Send whole first buffer through the mq1, read it + //through mq2 to the second buffer + while(1){ + //Send a fragment of buffer1 through mq1 + std::size_t bytes_to_send = MaxMsgSize < (db_origin.get_size() - sent) ? + MaxMsgSize : (db_origin.get_size() - sent); + mq1.send( &static_cast(db_origin.get_address())[sent] + , bytes_to_send + , 0); + sent += bytes_to_send; + //Receive the fragment through mq2 to buffer_destiny + mq2.receive( &buffer_destiny[total_recvd] + , BufferSize - recvd + , recvd + , priority); + total_recvd += recvd; + + //Check if we have received all the buffer + if(total_recvd == BufferSize){ + break; + } + } + + //The buffer will contain a copy of the original database + //so let's interpret the buffer with managed_external_buffer + managed_external_buffer db_destiny(open_only, &buffer_destiny[0], BufferSize); + + //Let's find the map + std::pair ret = db_destiny.find("MyMap"); + MyMap *map2 = ret.first; + + //Check if we have found it + if(!map2){ + return false; + } + + //Check if it is a single variable (not an array) + if(ret.second != 1){ + return false; + } + + //Now let's compare size + if(map1->size() != map2->size()){ + return false; + } + + //Now let's compare all db values + MyMap::size_type num_elements = map1->size(); + for(std::size_t i = 0; i < num_elements; ++i){ + if((*map1)[i] != (*map2)[i]){ + return false; + } + } + + //Destroy maps from db-s + db_origin.destroy_ptr(map1); + db_destiny.destroy_ptr(map2); + } + message_queue::remove(test::get_process_id_name()); + return true; +} +//] + +static const int MsgSize = 10; +static const int NumMsg = 1000; +static char msgsend [10]; +static char msgrecv [10]; + +static boost::interprocess::message_queue *pmessage_queue; + +void receiver() +{ + boost::interprocess::message_queue::size_type recvd_size; + unsigned int priority; + int nummsg = NumMsg; + + while(nummsg--){ + pmessage_queue->receive(msgrecv, MsgSize, recvd_size, priority); + } +} + +bool test_buffer_overflow() +{ + boost::interprocess::message_queue::remove(test::get_process_id_name()); + { + boost::movelib::unique_ptr + ptr(new boost::interprocess::message_queue + (create_only, test::get_process_id_name(), 10, 10)); + pmessage_queue = ptr.get(); + + //Launch the receiver thread + boost::interprocess::ipcdetail::OS_thread_t thread; + boost::interprocess::ipcdetail::thread_launch(thread, &receiver); + boost::interprocess::ipcdetail::thread_yield(); + + int nummsg = NumMsg; + + while(nummsg--){ + pmessage_queue->send(msgsend, MsgSize, 0); + } + + boost::interprocess::ipcdetail::thread_join(thread); + } + boost::interprocess::message_queue::remove(test::get_process_id_name()); + return true; +} + + +////////////////////////////////////////////////////////////////////////////// +// +// test_multi_sender_receiver is based on Alexander (aalutov's) +// testcase for ticket #9221. Many thanks. +// +////////////////////////////////////////////////////////////////////////////// + +static boost::interprocess::message_queue *global_queue = 0; +//We'll send MULTI_NUM_MSG_PER_SENDER messages per sender +static const int MULTI_NUM_MSG_PER_SENDER = 10000; +//Message queue message capacity +static const int MULTI_QUEUE_SIZE = (MULTI_NUM_MSG_PER_SENDER - 1)/MULTI_NUM_MSG_PER_SENDER + 1; +//We'll launch MULTI_THREAD_COUNT senders and MULTI_THREAD_COUNT receivers +static const int MULTI_THREAD_COUNT = 10; + +static void multisend() +{ + char buff; + for (int i = 0; i < MULTI_NUM_MSG_PER_SENDER; i++) { + global_queue->send(&buff, 1, 0); + } + global_queue->send(&buff, 0, 0); + //std::cout<<"writer thread complete"<receive(&buff, 1, size, priority); + ++received_msgs; + } while (size > 0); + --received_msgs; + //std::cout << "reader thread complete, read msgs: " << received_msgs << std::endl; +} + + +bool test_multi_sender_receiver() +{ + bool ret = true; + //std::cout << "Testing multi-sender / multi-receiver " << std::endl; + try { + boost::interprocess::message_queue::remove(test::get_process_id_name()); + boost::interprocess::message_queue mq + (boost::interprocess::open_or_create, test::get_process_id_name(), MULTI_QUEUE_SIZE, 1); + global_queue = &mq; + std::vector threads(MULTI_THREAD_COUNT*2); + + //Launch senders receiver thread + for (int i = 0; i < MULTI_THREAD_COUNT; i++) { + boost::interprocess::ipcdetail::thread_launch + (threads[i], &multisend); + } + + for (int i = 0; i < MULTI_THREAD_COUNT; i++) { + boost::interprocess::ipcdetail::thread_launch + (threads[MULTI_THREAD_COUNT+i], &multireceive); + } + + for (int i = 0; i < MULTI_THREAD_COUNT*2; i++) { + boost::interprocess::ipcdetail::thread_join(threads[i]); + //std::cout << "Joined thread " << i << std::endl; + } + } + catch (std::exception &e) { + std::cout << "error " << e.what() << std::endl; + ret = false; + } + boost::interprocess::message_queue::remove(test::get_process_id_name()); + return ret; +} + + +int main () +{ + if(!test_priority_order()){ + return 1; + } + + if(!test_serialize_db()){ + return 1; + } + + if(!test_buffer_overflow()){ + return 1; + } + + if(!test_multi_sender_receiver()){ + return 1; + } + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/movable_int.hpp b/src/boost/libs/interprocess/test/movable_int.hpp new file mode 100644 index 00000000..3890a468 --- /dev/null +++ b/src/boost/libs/interprocess/test/movable_int.hpp @@ -0,0 +1,293 @@ +/////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TEST_MOVABLE_INT_HEADER +#define BOOST_INTERPROCESS_TEST_MOVABLE_INT_HEADER + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace test { + +template +struct is_copyable; + +template<> +struct is_copyable +{ + static const bool value = true; +}; + + +class movable_int +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_int) + + public: + movable_int() + : m_int(0) + {} + + explicit movable_int(int a) + : m_int(a) + {} + + movable_int(BOOST_RV_REF(movable_int) mmi) + : m_int(mmi.m_int) + { mmi.m_int = 0; } + + movable_int & operator= (BOOST_RV_REF(movable_int) mmi) + { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } + + movable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const movable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const movable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const movable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const movable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const movable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const movable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + friend bool operator==(const movable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const movable_int &r) + { return l == r.get_int(); } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_int const & p) + +{ + os << p.get_int(); + return os; +} + + +template<> +struct is_copyable +{ + static const bool value = false; +}; + +class movable_and_copyable_int +{ + BOOST_COPYABLE_AND_MOVABLE(movable_and_copyable_int) + + public: + movable_and_copyable_int() + : m_int(0) + {} + + explicit movable_and_copyable_int(int a) + : m_int(a) + {} + + movable_and_copyable_int(const movable_and_copyable_int& mmi) + : m_int(mmi.m_int) + {} + + movable_and_copyable_int(BOOST_RV_REF(movable_and_copyable_int) mmi) + : m_int(mmi.m_int) + { mmi.m_int = 0; } + + movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi) + { this->m_int = mi.m_int; return *this; } + + movable_and_copyable_int & operator= (BOOST_RV_REF(movable_and_copyable_int) mmi) + { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } + + movable_and_copyable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const movable_and_copyable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const movable_and_copyable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const movable_and_copyable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const movable_and_copyable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const movable_and_copyable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const movable_and_copyable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + friend bool operator==(const movable_and_copyable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const movable_and_copyable_int &r) + { return l == r.get_int(); } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_and_copyable_int const & p) + +{ + os << p.get_int(); + return os; +} + +template<> +struct is_copyable +{ + static const bool value = true; +}; + +class copyable_int +{ + public: + copyable_int() + : m_int(0) + {} + + explicit copyable_int(int a) + : m_int(a) + {} + + copyable_int(const copyable_int& mmi) + : m_int(mmi.m_int) + {} + + copyable_int & operator= (int i) + { this->m_int = i; return *this; } + + bool operator ==(const copyable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const copyable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const copyable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const copyable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const copyable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const copyable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + friend bool operator==(const copyable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const copyable_int &r) + { return l == r.get_int(); } + + private: + int m_int; +}; + +template +std::basic_ostream & operator<< + (std::basic_ostream & os, copyable_int const & p) + +{ + os << p.get_int(); + return os; +} + +template<> +struct is_copyable +{ + static const bool value = true; +}; + +class non_copymovable_int +{ + non_copymovable_int(const non_copymovable_int& mmi); + non_copymovable_int & operator= (const non_copymovable_int &mi); + + public: + non_copymovable_int() + : m_int(0) + {} + + explicit non_copymovable_int(int a) + : m_int(a) + {} + + bool operator ==(const non_copymovable_int &mi) const + { return this->m_int == mi.m_int; } + + bool operator !=(const non_copymovable_int &mi) const + { return this->m_int != mi.m_int; } + + bool operator <(const non_copymovable_int &mi) const + { return this->m_int < mi.m_int; } + + bool operator <=(const non_copymovable_int &mi) const + { return this->m_int <= mi.m_int; } + + bool operator >=(const non_copymovable_int &mi) const + { return this->m_int >= mi.m_int; } + + bool operator >(const non_copymovable_int &mi) const + { return this->m_int > mi.m_int; } + + int get_int() const + { return m_int; } + + friend bool operator==(const non_copymovable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const non_copymovable_int &r) + { return l == r.get_int(); } + + private: + int m_int; +}; + +} //namespace test { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_TEST_MOVABLE_INT_HEADER diff --git a/src/boost/libs/interprocess/test/mutex_test.cpp b/src/boost/libs/interprocess/test/mutex_test.cpp new file mode 100644 index 00000000..e3bd4820 --- /dev/null +++ b/src/boost/libs/interprocess/test/mutex_test.cpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "mutex_test_template.hpp" + +#if defined(BOOST_INTERPROCESS_WINDOWS) +#include +#include +#endif + +int main () +{ + using namespace boost::interprocess; + + #if defined(BOOST_INTERPROCESS_WINDOWS) + test::test_all_lock(); + test::test_all_mutex(); + test::test_all_lock(); + test::test_all_mutex(); + #endif + + test::test_all_lock(); + test::test_all_mutex(); + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/mutex_test_template.hpp b/src/boost/libs/interprocess/test/mutex_test_template.hpp new file mode 100644 index 00000000..f298fb8b --- /dev/null +++ b/src/boost/libs/interprocess/test/mutex_test_template.hpp @@ -0,0 +1,394 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_INTERPROCESS_TEST_MUTEX_TEST_TEMPLATE_HEADER +#define BOOST_INTERPROCESS_TEST_MUTEX_TEST_TEMPLATE_HEADER + +#include +#include +#include "boost_interprocess_check.hpp" +#include "util.hpp" +#include +#include +#include +#include + +namespace boost { namespace interprocess { namespace test { + +template +struct test_lock +{ + typedef M mutex_type; + typedef boost::interprocess::scoped_lock lock_type; + + + void operator()() + { + mutex_type interprocess_mutex; + + // Test the lock's constructors. + { + lock_type lock(interprocess_mutex, boost::interprocess::defer_lock); + BOOST_INTERPROCESS_CHECK(!lock); + } + lock_type lock(interprocess_mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + + // Test the lock and unlock methods. + lock.unlock(); + BOOST_INTERPROCESS_CHECK(!lock); + lock.lock(); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + } +}; + +template +struct test_trylock +{ + typedef M mutex_type; + typedef boost::interprocess::scoped_lock try_to_lock_type; + + void operator()() + { + mutex_type interprocess_mutex; + + // Test the lock's constructors. + { + try_to_lock_type lock(interprocess_mutex, boost::interprocess::try_to_lock); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + } + { + try_to_lock_type lock(interprocess_mutex, boost::interprocess::defer_lock); + BOOST_INTERPROCESS_CHECK(!lock); + } + try_to_lock_type lock(interprocess_mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + + // Test the lock, unlock and trylock methods. + lock.unlock(); + BOOST_INTERPROCESS_CHECK(!lock); + lock.lock(); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + lock.unlock(); + BOOST_INTERPROCESS_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(lock.try_lock()); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + } +}; + +template +struct test_timedlock +{ + typedef M mutex_type; + typedef boost::interprocess::scoped_lock timed_lock_type; + + void operator()() + { + mutex_type interprocess_mutex; + + // Test the lock's constructors. + { + // Construct and initialize an ptime for a fast time out. + boost::posix_time::ptime pt = delay(1*BaseSeconds, 0); + + timed_lock_type lock(interprocess_mutex, pt); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + } + { + timed_lock_type lock(interprocess_mutex, boost::interprocess::defer_lock); + BOOST_INTERPROCESS_CHECK(!lock); + } + timed_lock_type lock(interprocess_mutex); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + + // Test the lock, unlock and timedlock methods. + lock.unlock(); + BOOST_INTERPROCESS_CHECK(!lock); + lock.lock(); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + lock.unlock(); + BOOST_INTERPROCESS_CHECK(!lock); + boost::posix_time::ptime pt = delay(3*BaseSeconds, 0); + BOOST_INTERPROCESS_CHECK(lock.timed_lock(pt)); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + } +}; + +template +struct test_recursive_lock +{ + typedef M mutex_type; + typedef boost::interprocess::scoped_lock lock_type; + + void operator()() + { + mutex_type mx; + { + lock_type lock1(mx); + lock_type lock2(mx); + } + { + lock_type lock1(mx, defer_lock); + lock_type lock2(mx, defer_lock); + } + { + lock_type lock1(mx, try_to_lock); + lock_type lock2(mx, try_to_lock); + } + { + //This should always lock + boost::posix_time::ptime pt = delay(2*BaseSeconds); + lock_type lock1(mx, pt); + lock_type lock2(mx, pt); + } + } +}; + +// plain_exclusive exercises the "infinite" lock for each +// read_write_mutex type. + +template +void lock_and_sleep(void *arg, M &sm) +{ + data *pdata = static_cast*>(arg); + boost::interprocess::scoped_lock l(sm); + if(pdata->m_secs){ + boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs)); + } + else{ + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); + } + + ++shared_val; + pdata->m_value = shared_val; +} + +template +void lock_and_catch_errors(void *arg, M &sm) +{ + data *pdata = static_cast*>(arg); + try + { + boost::interprocess::scoped_lock l(sm); + if(pdata->m_secs){ + boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs)); + } + else{ + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); + } + ++shared_val; + pdata->m_value = shared_val; + } + catch(interprocess_exception const & e) + { + pdata->m_error = e.get_error_code(); + } +} + +template +void try_lock_and_sleep(void *arg, M &sm) +{ + data *pdata = static_cast*>(arg); + boost::interprocess::scoped_lock l(sm, boost::interprocess::defer_lock); + if (l.try_lock()){ + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); + ++shared_val; + pdata->m_value = shared_val; + } +} + +template +void timed_lock_and_sleep(void *arg, M &sm) +{ + data *pdata = static_cast*>(arg); + boost::posix_time::ptime pt(delay(pdata->m_secs)); + boost::interprocess::scoped_lock + l (sm, boost::interprocess::defer_lock); + if (l.timed_lock(pt)){ + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); + ++shared_val; + pdata->m_value = shared_val; + } +} + +template +void test_mutex_lock() +{ + shared_val = 0; + + M mtx; + + data d1(1); + data d2(2); + + // Locker one launches, holds the lock for 2*BaseSeconds seconds. + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&lock_and_sleep, &d1, mtx)); + + //Wait 1*BaseSeconds + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + + // Locker two launches, but it won't hold the lock for 2*BaseSeconds seconds. + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&lock_and_sleep, &d2, mtx)); + + //Wait completion + + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_join(tm2); + + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == 2); +} + +template +void test_mutex_lock_timeout() +{ + shared_val = 0; + + M mtx; + + int wait_time_s = BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS / 1000; + if (wait_time_s == 0 ) + wait_time_s = 1; + + data d1(1, wait_time_s * 3); + data d2(2, wait_time_s * 2); + + // Locker one launches, and holds the lock for wait_time_s * 2 seconds. + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&lock_and_sleep, &d1, mtx)); + + //Wait 1*BaseSeconds + boost::interprocess::ipcdetail::thread_sleep((1000*wait_time_s)); + + // Locker two launches, and attempts to hold the lock for wait_time_s * 2 seconds. + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&lock_and_catch_errors, &d2, mtx)); + + //Wait completion + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_join(tm2); + + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == -1); + BOOST_INTERPROCESS_CHECK(d1.m_error == no_error); + BOOST_INTERPROCESS_CHECK(d2.m_error == boost::interprocess::timeout_when_locking_error); +} + +template +void test_mutex_try_lock() +{ + shared_val = 0; + + M mtx; + + data d1(1); + data d2(2); + + // Locker one launches, holds the lock for 2*BaseSeconds seconds. + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&try_lock_and_sleep, &d1, mtx)); + + //Wait 1*BaseSeconds + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + + // Locker two launches, but it should fail acquiring the lock + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&try_lock_and_sleep, &d2, mtx)); + + //Wait completion + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_join(tm2); + + //Only the first should succeed locking + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == -1); +} + +template +void test_mutex_timed_lock() + +{ + shared_val = 0; + + M mtx, m2; + + data d1(1, 2*BaseSeconds); + data d2(2, 2*BaseSeconds); + + // Locker one launches, holds the lock for 2*BaseSeconds seconds. + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&timed_lock_and_sleep, &d1, mtx)); + + //Wait 1*BaseSeconds + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + + // Locker two launches, holds the lock for 2*BaseSeconds seconds. + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&timed_lock_and_sleep, &d2, mtx)); + + //Wait completion + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_join(tm2); + + //Both should succeed locking + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == 2); +} + +template +inline void test_all_lock() +{ + //Now generic interprocess_mutex tests + std::cout << "test_lock<" << typeid(M).name() << ">" << std::endl; + test_lock()(); + std::cout << "test_trylock<" << typeid(M).name() << ">" << std::endl; + test_trylock()(); + std::cout << "test_timedlock<" << typeid(M).name() << ">" << std::endl; + test_timedlock()(); +} + +template +inline void test_all_recursive_lock() +{ + //Now generic interprocess_mutex tests + std::cout << "test_recursive_lock<" << typeid(M).name() << ">" << std::endl; + test_recursive_lock()(); +} + +template +void test_all_mutex() +{ + std::cout << "test_mutex_lock<" << typeid(M).name() << ">" << std::endl; + test_mutex_lock(); + std::cout << "test_mutex_try_lock<" << typeid(M).name() << ">" << std::endl; + test_mutex_try_lock(); + std::cout << "test_mutex_timed_lock<" << typeid(M).name() << ">" << std::endl; + test_mutex_timed_lock(); +} + +}}} //namespace boost { namespace interprocess { namespace test { + +#include + +#endif //BOOST_INTERPROCESS_TEST_MUTEX_TEST_TEMPLATE_HEADER diff --git a/src/boost/libs/interprocess/test/mutex_timeout_test.cpp b/src/boost/libs/interprocess/test/mutex_timeout_test.cpp new file mode 100644 index 00000000..7dc4df52 --- /dev/null +++ b/src/boost/libs/interprocess/test/mutex_timeout_test.cpp @@ -0,0 +1,30 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +// enable timeout feature +#define BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING +#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 1000 + +#include +#include +#include +#include +#include "mutex_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + test::test_mutex_lock_timeout(); + test::test_mutex_lock_timeout(); + + return 0; +} + +#include diff --git a/src/boost/libs/interprocess/test/named_allocation_test_template.hpp b/src/boost/libs/interprocess/test/named_allocation_test_template.hpp new file mode 100644 index 00000000..ca796349 --- /dev/null +++ b/src/boost/libs/interprocess/test/named_allocation_test_template.hpp @@ -0,0 +1,495 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER +#define BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER + +#include + +// interprocess +#include +#include +#include +#include +// container +#include +#include //char_traits +// std +#include +#include +#include +#include +#include + +// local +#include "get_process_id_name.hpp" + +namespace boost { namespace interprocess { namespace test { + +namespace { + const wchar_t *get_prefix(wchar_t) + { return L"prefix_name_"; } + + const char *get_prefix(char) + { return "prefix_name_"; } +} + +//This test allocates until there is no more memory +//and after that deallocates all in the same order +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_type name[BufferLen]; + + basic_bufferstream formatter(name, BufferLen); + + for(int i = 0; true; ++i){ + formatter.seekp(0); + formatter << get_prefix(char_type()) << i << std::ends; + + char *ptr = m.template construct(name, std::nothrow)(i); + + if(!ptr) + break; + + std::size_t namelen = char_traits_type::length(m.get_instance_name(ptr)); + if(namelen != char_traits_type::length(name)){ + return 1; + } + + if(char_traits_type::compare(m.get_instance_name(ptr), name, namelen) != 0){ + return 1; + } + + if(m.template find(name).first == 0) + return false; + + if(m.get_instance_type(ptr) != named_type) + return false; + + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + 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; + m.shrink_to_fit_indexes(); + if(!m.all_memory_deallocated()) + 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_named_iterators(ManagedMemory &m) +{ + typedef typename ManagedMemory::char_type char_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 << get_prefix(char_type()) << 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::size_t)boost::container::iterator_distance(named_beg, named_end) != (std::size_t)buffers.size()){ + return 1; + } + + for(; named_beg != named_end; ++named_beg){ + const char_type *name_str = named_beg->name(); + aux_str = name_str; + 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_str).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; + m.shrink_to_fit_indexes(); + if(!m.all_memory_deallocated()) + 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_shrink_to_fit(ManagedMemory &m) +{ + typedef typename ManagedMemory::char_type char_type; + std::vector buffers; + const int BufferLen = 100; + char_type name[BufferLen]; + + basic_bufferstream formatter(name, BufferLen); + + std::size_t free_memory_before = m.get_free_memory(); + + for(int i = 0; true; ++i){ + formatter.seekp(0); + formatter << get_prefix(char_type()) << i << std::ends; + + char *ptr = m.template construct(name, std::nothrow)(i); + + if(!ptr) + break; + buffers.push_back(ptr); + } + + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + m.destroy_ptr(buffers[j]); + } + + std::size_t free_memory_after = m.get_free_memory(); + + if(free_memory_before != free_memory_after){ + m.shrink_to_fit_indexes(); + if(free_memory_before != free_memory_after) + 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; + std::vector buffers; + const int BufferLen = 100; + char_type name[BufferLen]; + + basic_bufferstream formatter(name, BufferLen); + + for(int i = 0; true; ++i){ + formatter.seekp(0); + formatter << get_prefix(char_type()) << i << std::ends; + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + if(m.template find(name).first == 0) + return false; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + 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; + m.shrink_to_fit_indexes(); + if(!m.all_memory_deallocated()) + return false; + return true; +} + +//This test allocates until there is no more memory +//and after that deallocates all in the inverse order +template +bool test_named_allocation_inverse_destruction(ManagedMemory &m) +{ + typedef typename ManagedMemory::char_type char_type; + + std::vector buffers; + const int BufferLen = 100; + char_type name[BufferLen]; + + basic_bufferstream formatter(name, BufferLen); + + for(int i = 0; true; ++i){ + formatter.seekp(0); + formatter << get_prefix(char_type()) << i << std::ends; + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(int j = (int)buffers.size() + ;j-- + ;){ + m.destroy_ptr(buffers[j]); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + m.shrink_to_fit_indexes(); + if(!m.all_memory_deallocated()) + return false; + return true; +} + +//This test allocates until there is no more memory +//and after that deallocates all following a pattern +template +bool test_named_allocation_mixed_destruction(ManagedMemory &m) +{ + typedef typename ManagedMemory::char_type char_type; + + std::vector buffers; + const int BufferLen = 100; + char_type name[BufferLen]; + + basic_bufferstream formatter(name, BufferLen); + + for(int i = 0; true; ++i){ + formatter.seekp(0); + formatter << get_prefix(char_type()) << i << std::ends; + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + m.destroy_ptr(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + m.shrink_to_fit_indexes(); + if(!m.all_memory_deallocated()) + 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_inverse_named_allocation_destruction(ManagedMemory &m) +{ + typedef typename ManagedMemory::char_type char_type; + + std::vector buffers; + const int BufferLen = 100; + char_type name[BufferLen]; + + basic_bufferstream formatter(name, BufferLen); + + for(unsigned int i = 0; true; ++i){ + formatter.seekp(0); + formatter << get_prefix(char_type()) << i << std::ends; + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(unsigned int j = 0, max = (unsigned int)buffers.size() + ;j < max + ;++j){ + m.destroy_ptr(buffers[j]); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + m.shrink_to_fit_indexes(); + if(!m.all_memory_deallocated()) + return false; + return true; +} + +///This function calls all tests +template +bool test_all_named_allocation(ManagedMemory &m) +{ + std::cout << "Starting test_names_and_types. Class: " + << typeid(m).name() << std::endl; + + if(!test_names_and_types(m)){ + std::cout << "test_names_and_types failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_direct_named_allocation_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_direct_named_allocation_destruction(m)){ + std::cout << "test_direct_named_allocation_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_named_allocation_inverse_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_named_allocation_inverse_destruction(m)){ + std::cout << "test_named_allocation_inverse_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_named_allocation_mixed_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_named_allocation_mixed_destruction(m)){ + std::cout << "test_named_allocation_mixed_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_inverse_named_allocation_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_inverse_named_allocation_destruction(m)){ + std::cout << "test_inverse_named_allocation_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + if(!test_named_iterators(m)){ + std::cout << "test_named_iterators failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + return true; +} + +//This function calls all tests +template