]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright 2006-2009 Daniel James. | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #if !defined(BOOST_UNORDERED_TEST_MEMORY_HEADER) | |
7 | #define BOOST_UNORDERED_TEST_MEMORY_HEADER | |
8 | ||
7c673cae | 9 | #include "../helpers/test.hpp" |
b32b8144 FG |
10 | #include <boost/assert.hpp> |
11 | #include <boost/unordered/detail/implementation.hpp> | |
12 | #include <map> | |
13 | #include <memory> | |
7c673cae | 14 | |
b32b8144 FG |
15 | namespace test { |
16 | namespace detail { | |
17 | struct memory_area | |
7c673cae | 18 | { |
b32b8144 FG |
19 | void const* start; |
20 | void const* end; | |
21 | ||
22 | memory_area(void const* s, void const* e) : start(s), end(e) | |
23 | { | |
24 | BOOST_ASSERT(start != end); | |
25 | } | |
26 | }; | |
27 | ||
28 | struct memory_track | |
29 | { | |
30 | explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {} | |
31 | ||
32 | int constructed_; | |
33 | int tag_; | |
34 | }; | |
35 | ||
36 | // This is a bit dodgy as it defines overlapping | |
37 | // areas as 'equal', so this isn't a total ordering. | |
38 | // But it is for non-overlapping memory regions - which | |
39 | // is what'll be stored. | |
40 | // | |
41 | // All searches will be for areas entirely contained by | |
42 | // a member of the set - so it should find the area that contains | |
43 | // the region that is searched for. | |
44 | ||
45 | struct memory_area_compare | |
46 | { | |
47 | bool operator()(memory_area const& x, memory_area const& y) const | |
48 | { | |
49 | return x.end <= y.start; | |
50 | } | |
51 | }; | |
7c673cae | 52 | |
b32b8144 | 53 | struct memory_tracker |
7c673cae | 54 | { |
b32b8144 FG |
55 | typedef std::map<memory_area, memory_track, memory_area_compare, |
56 | std::allocator<std::pair<memory_area const, memory_track> > > | |
57 | allocated_memory_type; | |
58 | ||
59 | allocated_memory_type allocated_memory; | |
60 | unsigned int count_allocators; | |
61 | unsigned int count_allocations; | |
62 | unsigned int count_constructions; | |
63 | bool tracking_constructions; | |
64 | ||
65 | memory_tracker() | |
66 | : count_allocators(0), count_allocations(0), count_constructions(0), | |
67 | tracking_constructions(true) | |
68 | { | |
69 | } | |
70 | ||
71 | ~memory_tracker() { BOOST_TEST(count_allocators == 0); } | |
72 | ||
73 | void allocator_ref() | |
74 | { | |
75 | if (count_allocators == 0) { | |
76 | count_allocations = 0; | |
77 | count_constructions = 0; | |
78 | allocated_memory.clear(); | |
79 | } | |
80 | ++count_allocators; | |
81 | } | |
82 | ||
83 | void allocator_unref() | |
84 | { | |
85 | BOOST_TEST(count_allocators > 0); | |
86 | if (count_allocators > 0) { | |
87 | --count_allocators; | |
88 | if (count_allocators == 0) { | |
89 | bool no_allocations_left = (count_allocations == 0); | |
90 | bool no_constructions_left = (count_constructions == 0); | |
91 | bool allocated_memory_empty = allocated_memory.empty(); | |
92 | ||
93 | // Clearing the data before the checks terminate the | |
94 | // tests. | |
95 | count_allocations = 0; | |
96 | count_constructions = 0; | |
97 | allocated_memory.clear(); | |
98 | ||
99 | BOOST_TEST(no_allocations_left); | |
100 | BOOST_TEST(no_constructions_left); | |
101 | BOOST_TEST(allocated_memory_empty); | |
102 | } | |
103 | } | |
104 | } | |
105 | ||
106 | void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag) | |
107 | { | |
108 | if (n == 0) { | |
109 | BOOST_ERROR("Allocating 0 length array."); | |
110 | } else { | |
111 | ++count_allocations; | |
112 | allocated_memory.insert(std::pair<memory_area const, memory_track>( | |
113 | memory_area(ptr, (char*)ptr + n * size), memory_track(tag))); | |
114 | } | |
115 | } | |
116 | ||
117 | void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag, | |
118 | bool check_tag_ = true) | |
119 | { | |
120 | allocated_memory_type::iterator pos = | |
121 | allocated_memory.find(memory_area(ptr, (char*)ptr + n * size)); | |
122 | if (pos == allocated_memory.end()) { | |
123 | BOOST_ERROR("Deallocating unknown pointer."); | |
124 | } else { | |
125 | BOOST_TEST(pos->first.start == ptr); | |
126 | BOOST_TEST(pos->first.end == (char*)ptr + n * size); | |
127 | if (check_tag_) | |
128 | BOOST_TEST(pos->second.tag_ == tag); | |
129 | allocated_memory.erase(pos); | |
7c673cae | 130 | } |
b32b8144 FG |
131 | BOOST_TEST(count_allocations > 0); |
132 | if (count_allocations > 0) | |
133 | --count_allocations; | |
134 | } | |
135 | ||
136 | void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) | |
137 | { | |
138 | if (tracking_constructions) { | |
139 | ++count_constructions; | |
140 | } | |
141 | } | |
142 | ||
143 | void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) | |
144 | { | |
145 | if (tracking_constructions) { | |
146 | BOOST_TEST(count_constructions > 0); | |
147 | if (count_constructions > 0) | |
148 | --count_constructions; | |
149 | } | |
150 | } | |
151 | }; | |
152 | } | |
153 | ||
154 | namespace detail { | |
155 | // This won't be a problem as I'm only using a single compile unit | |
156 | // in each test (this is actually required by the minimal test | |
157 | // framework). | |
158 | // | |
159 | // boostinspect:nounnamed | |
160 | namespace { | |
161 | test::detail::memory_tracker tracker; | |
7c673cae | 162 | } |
b32b8144 FG |
163 | } |
164 | ||
165 | namespace detail { | |
166 | struct disable_construction_tracking | |
167 | { | |
168 | bool old_value; | |
169 | ||
170 | disable_construction_tracking() | |
171 | : old_value(detail::tracker.tracking_constructions) | |
172 | { | |
173 | test::detail::tracker.tracking_constructions = false; | |
174 | } | |
175 | ||
176 | ~disable_construction_tracking() | |
177 | { | |
178 | test::detail::tracker.tracking_constructions = old_value; | |
179 | } | |
180 | ||
181 | private: | |
182 | disable_construction_tracking(disable_construction_tracking const&); | |
183 | disable_construction_tracking& operator=( | |
184 | disable_construction_tracking const&); | |
185 | }; | |
186 | } | |
7c673cae FG |
187 | } |
188 | ||
189 | #endif |