| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-09 20:56:23 +00:00
										 |  |  | // Copyright 2006-2009 Daniel James.
 | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | // 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)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(BOOST_UNORDERED_TEST_MEMORY_HEADER)
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_TEST_MEMORY_HEADER
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #include "../helpers/test.hpp"
 | 
					
						
							| 
									
										
										
										
											2008-01-12 14:43:40 +00:00
										 |  |  | #include <boost/assert.hpp>
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #include <boost/unordered/detail/implementation.hpp>
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #include <map>
 | 
					
						
							|  |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | namespace test { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |   namespace detail { | 
					
						
							|  |  |  |     struct memory_area | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       void const* start; | 
					
						
							|  |  |  |       void const* end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       memory_area(void const* s, void const* e) : start(s), end(e) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         BOOST_ASSERT(start != end); | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct memory_track | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       int constructed_; | 
					
						
							|  |  |  |       int tag_; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // This is a bit dodgy as it defines overlapping
 | 
					
						
							|  |  |  |     // areas as 'equal', so this isn't a total ordering.
 | 
					
						
							|  |  |  |     // But it is for non-overlapping memory regions - which
 | 
					
						
							|  |  |  |     // is what'll be stored.
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // All searches will be for areas entirely contained by
 | 
					
						
							|  |  |  |     // a member of the set - so it should find the area that contains
 | 
					
						
							|  |  |  |     // the region that is searched for.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct memory_area_compare | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       bool operator()(memory_area const& x, memory_area const& y) const | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         return x.end <= y.start; | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |     struct memory_tracker | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       typedef std::map<memory_area, memory_track, memory_area_compare, | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         std::allocator<std::pair<memory_area const, memory_track> > > | 
					
						
							|  |  |  |         allocated_memory_type; | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       allocated_memory_type allocated_memory; | 
					
						
							|  |  |  |       unsigned int count_allocators; | 
					
						
							|  |  |  |       unsigned int count_allocations; | 
					
						
							|  |  |  |       unsigned int count_constructions; | 
					
						
							|  |  |  |       bool tracking_constructions; | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       memory_tracker() | 
					
						
							|  |  |  |           : count_allocators(0), count_allocations(0), count_constructions(0), | 
					
						
							|  |  |  |             tracking_constructions(true) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-18 09:36:04 -08:00
										 |  |  |       ~memory_tracker() { BOOST_ASSERT(count_allocators == 0); } | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       void allocator_ref() | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         if (count_allocators == 0) { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           count_allocations = 0; | 
					
						
							|  |  |  |           count_constructions = 0; | 
					
						
							|  |  |  |           allocated_memory.clear(); | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         ++count_allocators; | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       void allocator_unref() | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         BOOST_TEST(count_allocators > 0); | 
					
						
							|  |  |  |         if (count_allocators > 0) { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           --count_allocators; | 
					
						
							|  |  |  |           if (count_allocators == 0) { | 
					
						
							|  |  |  |             bool no_allocations_left = (count_allocations == 0); | 
					
						
							|  |  |  |             bool no_constructions_left = (count_constructions == 0); | 
					
						
							|  |  |  |             bool allocated_memory_empty = allocated_memory.empty(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Clearing the data before the checks terminate the
 | 
					
						
							|  |  |  |             // tests.
 | 
					
						
							|  |  |  |             count_allocations = 0; | 
					
						
							|  |  |  |             count_constructions = 0; | 
					
						
							|  |  |  |             allocated_memory.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             BOOST_TEST(no_allocations_left); | 
					
						
							|  |  |  |             BOOST_TEST(no_constructions_left); | 
					
						
							|  |  |  |             BOOST_TEST(allocated_memory_empty); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         if (n == 0) { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           BOOST_ERROR("Allocating 0 length array."); | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           ++count_allocations; | 
					
						
							|  |  |  |           allocated_memory.insert(std::pair<memory_area const, memory_track>( | 
					
						
							|  |  |  |             memory_area(ptr, (char*)ptr + n * size), memory_track(tag))); | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag, | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         bool check_tag_ = true) | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         allocated_memory_type::iterator pos = | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           allocated_memory.find(memory_area(ptr, (char*)ptr + n * size)); | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         if (pos == allocated_memory.end()) { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           BOOST_ERROR("Deallocating unknown pointer."); | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           BOOST_TEST(pos->first.start == ptr); | 
					
						
							|  |  |  |           BOOST_TEST(pos->first.end == (char*)ptr + n * size); | 
					
						
							|  |  |  |           if (check_tag_) | 
					
						
							|  |  |  |             BOOST_TEST(pos->second.tag_ == tag); | 
					
						
							|  |  |  |           allocated_memory.erase(pos); | 
					
						
							| 
									
										
										
										
											2011-08-14 18:53:29 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         BOOST_TEST(count_allocations > 0); | 
					
						
							|  |  |  |         if (count_allocations > 0) | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           --count_allocations; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |         if (tracking_constructions) { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           ++count_constructions; | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |         if (tracking_constructions) { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |           BOOST_TEST(count_constructions > 0); | 
					
						
							|  |  |  |           if (count_constructions > 0) | 
					
						
							|  |  |  |             --count_constructions; | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   namespace detail { | 
					
						
							|  |  |  |     // This won't be a problem as I'm only using a single compile unit
 | 
					
						
							|  |  |  |     // in each test (this is actually required by the minimal test
 | 
					
						
							|  |  |  |     // framework).
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // boostinspect:nounnamed
 | 
					
						
							|  |  |  |     namespace { | 
					
						
							|  |  |  |       test::detail::memory_tracker tracker; | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |   namespace detail { | 
					
						
							|  |  |  |     struct disable_construction_tracking | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       bool old_value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       disable_construction_tracking() | 
					
						
							|  |  |  |           : old_value(detail::tracker.tracking_constructions) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |         test::detail::tracker.tracking_constructions = false; | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       ~disable_construction_tracking() | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |         test::detail::tracker.tracking_constructions = old_value; | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |     private: | 
					
						
							|  |  |  |       disable_construction_tracking(disable_construction_tracking const&); | 
					
						
							|  |  |  |       disable_construction_tracking& operator=( | 
					
						
							| 
									
										
										
										
											2017-04-18 10:14:26 +01:00
										 |  |  |         disable_construction_tracking const&); | 
					
						
							| 
									
										
										
										
											2017-06-11 20:55:59 +01:00
										 |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-01-10 22:30:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |