1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/container for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | |
11 | |
12 | #ifdef _MSC_VER |
13 | #pragma warning (disable:4702) |
14 | #endif |
15 | |
16 | #include <vector> |
17 | #include <iostream> |
18 | #include <cstring> |
19 | #include <algorithm> //std::remove |
20 | #include <boost/container/detail/dlmalloc.hpp> |
21 | |
22 | namespace boost { namespace container { namespace test { |
23 | |
24 | static const std::size_t NumIt = 200; |
25 | |
26 | enum deallocation_type { DirectDeallocation, InverseDeallocation, MixedDeallocation, EndDeallocationType }; |
27 | |
28 | //This test allocates until there is no more memory |
29 | //and after that deallocates all in the inverse order |
30 | |
31 | bool test_allocation() |
32 | { |
33 | if(!dlmalloc_all_deallocated()) |
34 | return false; |
35 | dlmalloc_malloc_check(); |
36 | for( deallocation_type t = DirectDeallocation |
37 | ; t != EndDeallocationType |
38 | ; t = (deallocation_type)((int)t + 1)){ |
39 | std::vector<void*> buffers; |
40 | //std::size_t free_memory = a.get_free_memory(); |
41 | |
42 | for(std::size_t i = 0; i != NumIt; ++i){ |
43 | void *ptr = dlmalloc_malloc(bytes: i); |
44 | if(!ptr) |
45 | break; |
46 | buffers.push_back(x: ptr); |
47 | } |
48 | |
49 | switch(t){ |
50 | case DirectDeallocation: |
51 | { |
52 | for(std::size_t j = 0, max = buffers.size() |
53 | ;j < max |
54 | ;++j){ |
55 | dlmalloc_free(mem: buffers[j]); |
56 | } |
57 | } |
58 | break; |
59 | case InverseDeallocation: |
60 | { |
61 | for(std::size_t j = buffers.size() |
62 | ;j-- |
63 | ;){ |
64 | dlmalloc_free(mem: buffers[j]); |
65 | } |
66 | } |
67 | break; |
68 | case MixedDeallocation: |
69 | { |
70 | for(std::size_t j = 0, max = buffers.size() |
71 | ;j < max |
72 | ;++j){ |
73 | std::size_t pos = (j%4)*(buffers.size())/4; |
74 | dlmalloc_free(mem: buffers[pos]); |
75 | buffers.erase(position: buffers.begin()+(std::ptrdiff_t)pos); |
76 | } |
77 | } |
78 | break; |
79 | default: |
80 | break; |
81 | } |
82 | if(!dlmalloc_all_deallocated()) |
83 | return false; |
84 | //bool ok = free_memory == a.get_free_memory() && |
85 | //a.all_memory_deallocated() && a.check_sanity(); |
86 | //if(!ok) return ok; |
87 | } |
88 | dlmalloc_malloc_check(); |
89 | return 0 != dlmalloc_all_deallocated(); |
90 | } |
91 | |
92 | //This test allocates until there is no more memory |
93 | //and after that tries to shrink all the buffers to the |
94 | //half of the original size |
95 | |
96 | bool test_allocation_shrink() |
97 | { |
98 | dlmalloc_malloc_check(); |
99 | std::vector<void*> buffers; |
100 | |
101 | //Allocate buffers with extra memory |
102 | for(std::size_t i = 0; i != NumIt; ++i){ |
103 | void *ptr = dlmalloc_malloc(bytes: i*2u); |
104 | if(!ptr) |
105 | break; |
106 | buffers.push_back(x: ptr); |
107 | } |
108 | |
109 | //Now shrink to half |
110 | for(std::size_t i = 0, max = buffers.size() |
111 | ;i < max |
112 | ; ++i){ |
113 | std::size_t try_received_size = 0; |
114 | void* try_result = dlmalloc_allocation_command |
115 | ( command: BOOST_CONTAINER_TRY_SHRINK_IN_PLACE, sizeof_object: 1, limit_objects: i*2 |
116 | , preferred_objects: i, received_objects: &try_received_size, reuse_ptr: (char*)buffers[i]).first; |
117 | |
118 | std::size_t received_size = 0; |
119 | void* result = dlmalloc_allocation_command |
120 | ( command: BOOST_CONTAINER_SHRINK_IN_PLACE, sizeof_object: 1, limit_objects: i*2 |
121 | , preferred_objects: i, received_objects: &received_size, reuse_ptr: (char*)buffers[i]).first; |
122 | |
123 | if(result != try_result) |
124 | return false; |
125 | |
126 | if(received_size != try_received_size) |
127 | return false; |
128 | |
129 | if(result){ |
130 | if(received_size > std::size_t(i*2)){ |
131 | return false; |
132 | } |
133 | if(received_size < std::size_t(i)){ |
134 | return false; |
135 | } |
136 | } |
137 | } |
138 | |
139 | //Deallocate it in non sequential order |
140 | for(std::size_t j = 0, max = buffers.size() |
141 | ;j < max |
142 | ;++j){ |
143 | std::size_t pos = (j%4u)*(buffers.size())/4u; |
144 | dlmalloc_free(mem: buffers[pos]); |
145 | buffers.erase(position: buffers.begin()+(std::ptrdiff_t)pos); |
146 | } |
147 | dlmalloc_malloc_check(); |
148 | return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity(); |
149 | } |
150 | |
151 | //This test allocates until there is no more memory |
152 | //and after that tries to expand all the buffers to |
153 | //avoid the wasted internal fragmentation |
154 | |
155 | bool test_allocation_expand() |
156 | { |
157 | dlmalloc_malloc_check(); |
158 | std::vector<void*> buffers; |
159 | |
160 | //Allocate buffers with extra memory |
161 | for(std::size_t i = 0; i != NumIt; ++i){ |
162 | void *ptr = dlmalloc_malloc(bytes: i); |
163 | if(!ptr) |
164 | break; |
165 | buffers.push_back(x: ptr); |
166 | } |
167 | |
168 | //Now try to expand to the double of the size |
169 | for(std::size_t i = 0, max = buffers.size() |
170 | ;i < max |
171 | ;++i){ |
172 | std::size_t received_size = 0; |
173 | std::size_t min_size = i+1; |
174 | std::size_t preferred_size = i*2; |
175 | preferred_size = min_size > preferred_size ? min_size : preferred_size; |
176 | while(dlmalloc_allocation_command |
177 | ( command: BOOST_CONTAINER_EXPAND_FWD, sizeof_object: 1, limit_objects: min_size |
178 | , preferred_objects: preferred_size, received_objects: &received_size, reuse_ptr: (char*)buffers[i]).first){ |
179 | //Check received size is bigger than minimum |
180 | if(received_size < min_size){ |
181 | return false; |
182 | } |
183 | //Now, try to expand further |
184 | min_size = received_size+1; |
185 | preferred_size = min_size*2; |
186 | } |
187 | } |
188 | |
189 | //Deallocate it in non sequential order |
190 | for(std::size_t j = 0, max = buffers.size() |
191 | ;j < max |
192 | ;++j){ |
193 | std::size_t pos = (j%4u)*(buffers.size())/4u; |
194 | dlmalloc_free(mem: buffers[pos]); |
195 | buffers.erase(position: buffers.begin()+(std::ptrdiff_t)pos); |
196 | } |
197 | dlmalloc_malloc_check(); |
198 | return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity(); |
199 | } |
200 | |
201 | //This test allocates until there is no more memory |
202 | //and after that tries to expand all the buffers to |
203 | //avoid the wasted internal fragmentation |
204 | bool test_allocation_shrink_and_expand() |
205 | { |
206 | std::vector<void*> buffers; |
207 | std::vector<std::size_t> received_sizes; |
208 | std::vector<bool> size_reduced; |
209 | |
210 | //Allocate buffers wand store received sizes |
211 | for(std::size_t i = 0; i != NumIt; ++i){ |
212 | std::size_t received_size = 0; |
213 | void *ptr = dlmalloc_allocation_command |
214 | (command: BOOST_CONTAINER_ALLOCATE_NEW, sizeof_object: 1u, limit_objects: i, preferred_objects: i*2u, received_objects: &received_size, reuse_ptr: 0).first; |
215 | if(!ptr){ |
216 | ptr = dlmalloc_allocation_command |
217 | ( command: BOOST_CONTAINER_ALLOCATE_NEW, sizeof_object: 1u, limit_objects: 1u, preferred_objects: i*2, received_objects: &received_size, reuse_ptr: 0).first; |
218 | if(!ptr) |
219 | break; |
220 | } |
221 | buffers.push_back(x: ptr); |
222 | received_sizes.push_back(x: received_size); |
223 | } |
224 | |
225 | //Now shrink to half |
226 | for(std::size_t i = 0, max = buffers.size() |
227 | ; i < max |
228 | ; ++i){ |
229 | std::size_t received_size = 0; |
230 | bool size_reduced_flag; |
231 | if(true == (size_reduced_flag = !! |
232 | dlmalloc_allocation_command |
233 | ( command: BOOST_CONTAINER_SHRINK_IN_PLACE, sizeof_object: 1, limit_objects: received_sizes[i] |
234 | , preferred_objects: i, received_objects: &received_size, reuse_ptr: (char*)buffers[i]).first)){ |
235 | if(received_size > std::size_t(received_sizes[i])){ |
236 | return false; |
237 | } |
238 | if(received_size < std::size_t(i)){ |
239 | return false; |
240 | } |
241 | } |
242 | size_reduced.push_back(x: size_reduced_flag); |
243 | } |
244 | |
245 | //Now try to expand to the original size |
246 | for(std::size_t i = 0, max = buffers.size() |
247 | ;i < max |
248 | ;++i){ |
249 | if(!size_reduced[i]) continue; |
250 | std::size_t received_size = 0; |
251 | std::size_t request_size = received_sizes[i]; |
252 | if(dlmalloc_allocation_command |
253 | ( command: BOOST_CONTAINER_EXPAND_FWD, sizeof_object: 1, limit_objects: request_size |
254 | , preferred_objects: request_size, received_objects: &received_size, reuse_ptr: (char*)buffers[i]).first){ |
255 | if(received_size != request_size){ |
256 | return false; |
257 | } |
258 | } |
259 | else{ |
260 | return false; |
261 | } |
262 | } |
263 | |
264 | //Deallocate it in non sequential order |
265 | for(std::size_t j = 0, max = buffers.size() |
266 | ;j < max |
267 | ;++j){ |
268 | std::size_t pos = (j%4u)*(buffers.size())/4u; |
269 | dlmalloc_free(mem: buffers[pos]); |
270 | buffers.erase(position: buffers.begin()+(std::ptrdiff_t)pos); |
271 | } |
272 | |
273 | return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity(); |
274 | } |
275 | |
276 | //This test allocates until there is no more memory |
277 | //and after that deallocates the odd buffers to |
278 | //make room for expansions. The expansion will probably |
279 | //success since the deallocation left room for that. |
280 | |
281 | bool test_allocation_deallocation_expand() |
282 | { |
283 | dlmalloc_malloc_check(); |
284 | std::vector<void*> buffers; |
285 | |
286 | //Allocate buffers with extra memory |
287 | for(std::size_t i = 0; i != NumIt; ++i){ |
288 | void *ptr = dlmalloc_malloc(bytes: i); |
289 | if(!ptr) |
290 | break; |
291 | buffers.push_back(x: ptr); |
292 | } |
293 | |
294 | //Now deallocate the half of the blocks |
295 | //so expand maybe can merge new free blocks |
296 | for(std::size_t i = 0, max = buffers.size() |
297 | ;i < max |
298 | ;++i){ |
299 | if(i%2){ |
300 | dlmalloc_free(mem: buffers[i]); |
301 | buffers[i] = 0; |
302 | } |
303 | } |
304 | |
305 | //Now try to expand to the double of the size |
306 | for(std::size_t i = 0, max = buffers.size() |
307 | ;i < max |
308 | ;++i){ |
309 | // |
310 | if(buffers[i]){ |
311 | std::size_t received_size = 0; |
312 | std::size_t min_size = i+1; |
313 | std::size_t preferred_size = i*2; |
314 | preferred_size = min_size > preferred_size ? min_size : preferred_size; |
315 | |
316 | while(dlmalloc_allocation_command |
317 | ( command: BOOST_CONTAINER_EXPAND_FWD, sizeof_object: 1, limit_objects: min_size |
318 | , preferred_objects: preferred_size, received_objects: &received_size, reuse_ptr: (char*)buffers[i]).first){ |
319 | //Check received size is bigger than minimum |
320 | if(received_size < min_size){ |
321 | return false; |
322 | } |
323 | //Now, try to expand further |
324 | min_size = received_size+1; |
325 | preferred_size = min_size*2; |
326 | } |
327 | } |
328 | } |
329 | |
330 | //Now erase null values from the vector |
331 | buffers.erase(first: std::remove(first: buffers.begin(), last: buffers.end(), value: (void*)0) |
332 | ,last: buffers.end()); |
333 | |
334 | //Deallocate it in non sequential order |
335 | for(std::size_t j = 0, max = buffers.size() |
336 | ;j < max |
337 | ;++j){ |
338 | std::size_t pos = (j%4u)*(buffers.size())/4u; |
339 | dlmalloc_free(mem: buffers[pos]); |
340 | buffers.erase(position: buffers.begin()+(std::ptrdiff_t)pos); |
341 | } |
342 | dlmalloc_malloc_check(); |
343 | return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity(); |
344 | } |
345 | |
346 | //This test allocates until there is no more memory |
347 | //and after that deallocates all except the last. |
348 | //If the allocation algorithm is a bottom-up algorithm |
349 | //the last buffer will be in the end of the segment. |
350 | //Then the test will start expanding backwards, until |
351 | //the buffer fills all the memory |
352 | |
353 | bool test_allocation_with_reuse() |
354 | { |
355 | dlmalloc_malloc_check(); |
356 | //We will repeat this test for different sized elements |
357 | for(std::size_t sizeof_object = 1; sizeof_object < 20; ++sizeof_object){ |
358 | std::vector<void*> buffers; |
359 | |
360 | //Allocate buffers with extra memory |
361 | for(std::size_t i = 0; i != NumIt; ++i){ |
362 | void *ptr = dlmalloc_malloc(bytes: i*sizeof_object); |
363 | if(!ptr) |
364 | break; |
365 | buffers.push_back(x: ptr); |
366 | } |
367 | |
368 | //Now deallocate all except the latest |
369 | //Now try to expand to the double of the size |
370 | for(std::size_t i = 0, max = buffers.size() - 1 |
371 | ;i < max |
372 | ;++i){ |
373 | dlmalloc_free(mem: buffers[i]); |
374 | } |
375 | |
376 | //Save the unique buffer and clear vector |
377 | void *ptr = buffers.back(); |
378 | buffers.clear(); |
379 | |
380 | //Now allocate with reuse |
381 | std::size_t received_size = 0; |
382 | for(std::size_t i = 0; i != NumIt; ++i){ |
383 | std::size_t min_size = (received_size/sizeof_object + 1u)*sizeof_object; |
384 | std::size_t prf_size = (received_size/sizeof_object + (i+1u)*2u)*sizeof_object; |
385 | dlmalloc_command_ret_t ret = dlmalloc_allocation_command |
386 | ( command: BOOST_CONTAINER_EXPAND_BWD, sizeof_object, limit_objects: min_size |
387 | , preferred_objects: prf_size, received_objects: &received_size, reuse_ptr: (char*)ptr); |
388 | //If we have memory, this must be a buffer reuse |
389 | if(!ret.first) |
390 | break; |
391 | //If we have memory, this must be a buffer reuse |
392 | if(!ret.second) |
393 | return false; |
394 | if(received_size < min_size) |
395 | return false; |
396 | ptr = ret.first; |
397 | } |
398 | //There should be only a single block so deallocate it |
399 | dlmalloc_free(mem: ptr); |
400 | dlmalloc_malloc_check(); |
401 | if(!dlmalloc_all_deallocated()) |
402 | return false; |
403 | } |
404 | return true; |
405 | } |
406 | |
407 | |
408 | //This test allocates memory with different alignments |
409 | //and checks returned memory is aligned. |
410 | |
411 | bool test_aligned_allocation() |
412 | { |
413 | dlmalloc_malloc_check(); |
414 | //Allocate aligned buffers in a loop |
415 | //and then deallocate it |
416 | for(std::size_t i = 1u; i != (1u << (sizeof(int)/2u)); i <<= 1u){ |
417 | for(std::size_t j = 1u; j != 512u; j <<= 1){ |
418 | void *ptr = dlmalloc_memalign(bytes: i-1, alignment: j); |
419 | if(!ptr){ |
420 | return false; |
421 | } |
422 | |
423 | if(((std::size_t)ptr & (j - 1)) != 0) |
424 | return false; |
425 | dlmalloc_free(mem: ptr); |
426 | //if(!a.all_memory_deallocated() || !a.check_sanity()){ |
427 | // return false; |
428 | //} |
429 | } |
430 | } |
431 | dlmalloc_malloc_check(); |
432 | return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity(); |
433 | } |
434 | |
435 | //This test allocates memory with different alignments |
436 | //and checks returned memory is aligned. |
437 | |
438 | bool test_continuous_aligned_allocation() |
439 | { |
440 | dlmalloc_malloc_check(); |
441 | std::vector<void*> buffers; |
442 | //Allocate aligned buffers in a loop |
443 | //and then deallocate it |
444 | bool continue_loop = true; |
445 | std::size_t MaxAlign = 4096; |
446 | std::size_t MaxSize = 4096; |
447 | for(std::size_t i = 1; i < MaxSize; i <<= 1){ |
448 | for(std::size_t j = 1; j < MaxAlign; j <<= 1){ |
449 | for(std::size_t k = 0; k != NumIt; ++k){ |
450 | void *ptr = dlmalloc_memalign(bytes: i-1, alignment: j); |
451 | buffers.push_back(x: ptr); |
452 | if(!ptr){ |
453 | continue_loop = false; |
454 | break; |
455 | } |
456 | |
457 | if(((std::size_t)ptr & (j - 1)) != 0) |
458 | return false; |
459 | } |
460 | //Deallocate all |
461 | for(std::size_t k = buffers.size(); k--;){ |
462 | dlmalloc_free(mem: buffers[k]); |
463 | } |
464 | buffers.clear(); |
465 | //if(!a.all_memory_deallocated() && a.check_sanity()) |
466 | // return false; |
467 | if(!continue_loop) |
468 | break; |
469 | } |
470 | } |
471 | dlmalloc_malloc_check(); |
472 | return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity(); |
473 | } |
474 | |
475 | //This test allocates multiple values until there is no more memory |
476 | //and after that deallocates all in the inverse order |
477 | bool test_many_equal_allocation() |
478 | { |
479 | dlmalloc_malloc_check(); |
480 | for( deallocation_type t = DirectDeallocation |
481 | ; t != EndDeallocationType |
482 | ; t = (deallocation_type)((int)t + 1)){ |
483 | //std::size_t free_memory = a.get_free_memory(); |
484 | |
485 | std::vector<void*> buffers2; |
486 | |
487 | //Allocate buffers with extra memory |
488 | for(std::size_t i = 0; i != NumIt; ++i){ |
489 | void *ptr = dlmalloc_malloc(bytes: i); |
490 | if(!ptr) |
491 | break; |
492 | //if(!a.check_sanity()) |
493 | //return false; |
494 | buffers2.push_back(x: ptr); |
495 | } |
496 | |
497 | //Now deallocate the half of the blocks |
498 | //so expand maybe can merge new free blocks |
499 | for(std::size_t i = 0, max = buffers2.size() |
500 | ;i < max |
501 | ;++i){ |
502 | if(i%2){ |
503 | dlmalloc_free(mem: buffers2[i]); |
504 | buffers2[i] = 0; |
505 | } |
506 | } |
507 | |
508 | //if(!a.check_sanity()) |
509 | //return false; |
510 | |
511 | std::vector<void*> buffers; |
512 | for(std::size_t i = 0; i != NumIt/10; ++i){ |
513 | dlmalloc_memchain chain; |
514 | BOOST_CONTAINER_MEMCHAIN_INIT(&chain); |
515 | dlmalloc_multialloc_nodes(n_elements: (i+1)*2, elem_size: i+1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, pchain: &chain); |
516 | dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain); |
517 | if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it)) |
518 | break; |
519 | |
520 | std::size_t n = 0; |
521 | for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){ |
522 | buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it)); |
523 | BOOST_CONTAINER_MEMIT_NEXT(it); |
524 | } |
525 | if(n != std::size_t((i+1)*2)) |
526 | return false; |
527 | } |
528 | |
529 | //if(!a.check_sanity()) |
530 | //return false; |
531 | |
532 | switch(t){ |
533 | case DirectDeallocation: |
534 | { |
535 | for(std::size_t j = 0, max = buffers.size() |
536 | ;j < max |
537 | ;++j){ |
538 | dlmalloc_free(mem: buffers[j]); |
539 | } |
540 | } |
541 | break; |
542 | case InverseDeallocation: |
543 | { |
544 | for(std::size_t j = buffers.size() |
545 | ;j-- |
546 | ;){ |
547 | dlmalloc_free(mem: buffers[j]); |
548 | } |
549 | } |
550 | break; |
551 | case MixedDeallocation: |
552 | { |
553 | for(std::size_t j = 0, max = buffers.size() |
554 | ;j < max |
555 | ;++j){ |
556 | std::size_t pos = (j%4u)*(buffers.size())/4u; |
557 | dlmalloc_free(mem: buffers[pos]); |
558 | buffers.erase(position: buffers.begin()+(std::ptrdiff_t)pos); |
559 | } |
560 | } |
561 | break; |
562 | default: |
563 | break; |
564 | } |
565 | |
566 | //Deallocate the rest of the blocks |
567 | |
568 | //Deallocate it in non sequential order |
569 | for(std::size_t j = 0, max = buffers2.size() |
570 | ;j < max |
571 | ;++j){ |
572 | std::size_t pos = (j%4u)*(buffers2.size())/4u; |
573 | dlmalloc_free(mem: buffers2[pos]); |
574 | buffers2.erase(position: buffers2.begin()+(std::ptrdiff_t)pos); |
575 | } |
576 | |
577 | //bool ok = free_memory == a.get_free_memory() && |
578 | //a.all_memory_deallocated() && a.check_sanity(); |
579 | //if(!ok) return ok; |
580 | } |
581 | dlmalloc_malloc_check(); |
582 | return 0 != dlmalloc_all_deallocated(); |
583 | } |
584 | |
585 | //This test allocates multiple values until there is no more memory |
586 | //and after that deallocates all in the inverse order |
587 | |
588 | bool test_many_different_allocation() |
589 | { |
590 | dlmalloc_malloc_check(); |
591 | const std::size_t ArraySize = 11; |
592 | std::size_t requested_sizes[ArraySize]; |
593 | for(std::size_t i = 0; i < ArraySize; ++i){ |
594 | requested_sizes[i] = 4*i; |
595 | } |
596 | |
597 | for( deallocation_type t = DirectDeallocation |
598 | ; t != EndDeallocationType |
599 | ; t = (deallocation_type)((int)t + 1)){ |
600 | //std::size_t free_memory = a.get_free_memory(); |
601 | |
602 | std::vector<void*> buffers2; |
603 | |
604 | //Allocate buffers with extra memory |
605 | for(std::size_t i = 0; i != NumIt; ++i){ |
606 | void *ptr = dlmalloc_malloc(bytes: i); |
607 | if(!ptr) |
608 | break; |
609 | buffers2.push_back(x: ptr); |
610 | } |
611 | |
612 | //Now deallocate the half of the blocks |
613 | //so expand maybe can merge new free blocks |
614 | for(std::size_t i = 0, max = buffers2.size() |
615 | ;i < max |
616 | ;++i){ |
617 | if(i%2){ |
618 | dlmalloc_free(mem: buffers2[i]); |
619 | buffers2[i] = 0; |
620 | } |
621 | } |
622 | |
623 | std::vector<void*> buffers; |
624 | for(std::size_t i = 0; i != NumIt; ++i){ |
625 | dlmalloc_memchain chain; |
626 | BOOST_CONTAINER_MEMCHAIN_INIT(&chain); |
627 | dlmalloc_multialloc_arrays(n_elements: ArraySize, sizes: requested_sizes, sizeof_element: 1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, pchain: &chain); |
628 | dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain); |
629 | if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it)) |
630 | break; |
631 | std::size_t n = 0; |
632 | for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){ |
633 | buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it)); |
634 | BOOST_CONTAINER_MEMIT_NEXT(it); |
635 | } |
636 | if(n != ArraySize) |
637 | return false; |
638 | } |
639 | |
640 | switch(t){ |
641 | case DirectDeallocation: |
642 | { |
643 | for(std::size_t j = 0, max = buffers.size() |
644 | ;j < max |
645 | ;++j){ |
646 | dlmalloc_free(mem: buffers[j]); |
647 | } |
648 | } |
649 | break; |
650 | case InverseDeallocation: |
651 | { |
652 | for(std::size_t j = buffers.size() |
653 | ;j-- |
654 | ;){ |
655 | dlmalloc_free(mem: buffers[j]); |
656 | } |
657 | } |
658 | break; |
659 | case MixedDeallocation: |
660 | { |
661 | for(std::size_t j = 0, max = buffers.size() |
662 | ;j < max |
663 | ;++j){ |
664 | std::size_t pos = (j%4)*(buffers.size())/4; |
665 | dlmalloc_free(mem: buffers[pos]); |
666 | buffers.erase(position: buffers.begin()+(std::ptrdiff_t)pos); |
667 | } |
668 | } |
669 | break; |
670 | default: |
671 | break; |
672 | } |
673 | |
674 | //Deallocate the rest of the blocks |
675 | |
676 | //Deallocate it in non sequential order |
677 | for(std::size_t j = 0, max = buffers2.size() |
678 | ;j < max |
679 | ;++j){ |
680 | std::size_t pos = (j%4u)*(buffers2.size())/4u; |
681 | dlmalloc_free(mem: buffers2[pos]); |
682 | buffers2.erase(position: buffers2.begin()+(std::ptrdiff_t)pos); |
683 | } |
684 | |
685 | //bool ok = free_memory == a.get_free_memory() && |
686 | //a.all_memory_deallocated() && a.check_sanity(); |
687 | //if(!ok) return ok; |
688 | } |
689 | dlmalloc_malloc_check(); |
690 | return 0 != dlmalloc_all_deallocated(); |
691 | } |
692 | |
693 | bool test_many_deallocation() |
694 | { |
695 | const std::size_t ArraySize = 11; |
696 | std::vector<dlmalloc_memchain> buffers; |
697 | std::size_t requested_sizes[ArraySize]; |
698 | for(std::size_t i = 0; i < ArraySize; ++i){ |
699 | requested_sizes[i] = 4*i; |
700 | } |
701 | |
702 | for(std::size_t i = 0; i != NumIt; ++i){ |
703 | dlmalloc_memchain chain; |
704 | BOOST_CONTAINER_MEMCHAIN_INIT(&chain); |
705 | dlmalloc_multialloc_arrays(n_elements: ArraySize, sizes: requested_sizes, sizeof_element: 1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, pchain: &chain); |
706 | dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain); |
707 | if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it)) |
708 | return false; |
709 | buffers.push_back(x: chain); |
710 | } |
711 | for(std::size_t i = 0; i != NumIt; ++i){ |
712 | dlmalloc_multidealloc(pchain: &buffers[i]); |
713 | } |
714 | buffers.clear(); |
715 | |
716 | dlmalloc_malloc_check(); |
717 | if(!dlmalloc_all_deallocated()) |
718 | return false; |
719 | |
720 | for(std::size_t i = 0; i != NumIt; ++i){ |
721 | dlmalloc_memchain chain; |
722 | BOOST_CONTAINER_MEMCHAIN_INIT(&chain); |
723 | dlmalloc_multialloc_nodes(n_elements: ArraySize, elem_size: i*4+1, BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, pchain: &chain); |
724 | dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain); |
725 | if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it)) |
726 | return false; |
727 | buffers.push_back(x: chain); |
728 | } |
729 | for(std::size_t i = 0; i != NumIt; ++i){ |
730 | dlmalloc_multidealloc(pchain: &buffers[i]); |
731 | } |
732 | buffers.clear(); |
733 | |
734 | dlmalloc_malloc_check(); |
735 | if(!dlmalloc_all_deallocated()) |
736 | return false; |
737 | |
738 | return true; |
739 | } |
740 | |
741 | //This function calls all tests |
742 | |
743 | bool test_all_allocation() |
744 | { |
745 | std::cout << "Starting test_allocation" |
746 | << std::endl; |
747 | |
748 | if(!test_allocation()){ |
749 | std::cout << "test_allocation_direct_deallocation failed" |
750 | << std::endl; |
751 | return false; |
752 | } |
753 | |
754 | std::cout << "Starting test_many_equal_allocation" |
755 | << std::endl; |
756 | |
757 | if(!test_many_equal_allocation()){ |
758 | std::cout << "test_many_equal_allocation failed" |
759 | << std::endl; |
760 | return false; |
761 | } |
762 | |
763 | std::cout << "Starting test_many_different_allocation" |
764 | << std::endl; |
765 | |
766 | if(!test_many_different_allocation()){ |
767 | std::cout << "test_many_different_allocation failed" |
768 | << std::endl; |
769 | return false; |
770 | } |
771 | |
772 | std::cout << "Starting test_allocation_shrink" |
773 | << std::endl; |
774 | |
775 | if(!test_allocation_shrink()){ |
776 | std::cout << "test_allocation_shrink failed" |
777 | << std::endl; |
778 | return false; |
779 | } |
780 | |
781 | if(!test_allocation_shrink_and_expand()){ |
782 | std::cout << "test_allocation_shrink_and_expand failed" |
783 | << std::endl; |
784 | return false; |
785 | } |
786 | |
787 | std::cout << "Starting test_allocation_expand" |
788 | << std::endl; |
789 | |
790 | if(!test_allocation_expand()){ |
791 | std::cout << "test_allocation_expand failed" |
792 | << std::endl; |
793 | return false; |
794 | } |
795 | |
796 | std::cout << "Starting test_allocation_deallocation_expand" |
797 | << std::endl; |
798 | |
799 | if(!test_allocation_deallocation_expand()){ |
800 | std::cout << "test_allocation_deallocation_expand failed" |
801 | << std::endl; |
802 | return false; |
803 | } |
804 | |
805 | std::cout << "Starting test_allocation_with_reuse" |
806 | << std::endl; |
807 | |
808 | if(!test_allocation_with_reuse()){ |
809 | std::cout << "test_allocation_with_reuse failed" |
810 | << std::endl; |
811 | return false; |
812 | } |
813 | |
814 | std::cout << "Starting test_aligned_allocation" |
815 | << std::endl; |
816 | |
817 | if(!test_aligned_allocation()){ |
818 | std::cout << "test_aligned_allocation failed" |
819 | << std::endl; |
820 | return false; |
821 | } |
822 | |
823 | std::cout << "Starting test_continuous_aligned_allocation" |
824 | << std::endl; |
825 | |
826 | if(!test_continuous_aligned_allocation()){ |
827 | std::cout << "test_continuous_aligned_allocation failed" |
828 | << std::endl; |
829 | return false; |
830 | } |
831 | |
832 | if(!test_many_deallocation()){ |
833 | std::cout << "test_many_deallocation failed" |
834 | << std::endl; |
835 | return false; |
836 | } |
837 | |
838 | return 0 != dlmalloc_all_deallocated(); |
839 | } |
840 | |
841 | }}} //namespace boost { namespace container { namespace test { |
842 | |
843 | |
844 | int main() |
845 | { |
846 | if(!boost::container::test::test_all_allocation()) |
847 | return 1; |
848 | return 0; |
849 | } |
850 | |