1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03
10 
11 // <experimental/memory_resource>
12 
13 // template <class Alloc> class resource_adaptor_imp;
14 
15 // void * do_allocate(size_t size, size_t align)
16 // void   do_deallocate(void*, size_t, size_t)
17 
18 #include <experimental/memory_resource>
19 #include <type_traits>
20 #include <memory>
21 #include <exception>
22 #include <cassert>
23 
24 #include "test_macros.h"
25 #include "test_memory_resource.h"
26 
27 namespace ex = std::experimental::pmr;
28 
29 template <class Alloc>
check_allocate_deallocate()30 void check_allocate_deallocate()
31 {
32     typedef ex::resource_adaptor<Alloc> R1;
33     const std::size_t max_align = alignof(std::max_align_t);
34 
35     for (std::size_t s = 1; s < 5012; ++s)
36     {
37         for(std::size_t align_req = 1; align_req <= (max_align * 2); align_req *= 2)
38         {
39             const std::size_t align_exp = align_req > max_align
40                                                     ? max_align : align_req;
41             AllocController P;
42             R1 r{Alloc(P)};
43             ex::memory_resource & m1 = r;
44 
45             void * const ret = m1.allocate(s, align_req);
46             assert(P.alive == 1);
47             assert(P.alloc_count == 1);
48             assert(P.checkAllocAtLeast(ret, s, align_exp));
49 
50             assert(((std::size_t)ret % align_exp) == 0);
51 
52             m1.deallocate(ret, s, align_req);
53             assert(P.alive == 0);
54             assert(P.dealloc_count == 1);
55             assert(P.checkDeallocMatchesAlloc());
56         }
57     }
58 }
59 
check_alloc_max_size()60 void check_alloc_max_size() {
61     using Alloc = NullAllocator<char>;
62     using R1 = ex::resource_adaptor<Alloc>;
63     const std::size_t max_align = alignof(std::max_align_t);
64 
65     auto check = [=](std::size_t s, std::size_t align_req) {
66         const std::size_t align_exp = align_req > max_align
67                                                 ? max_align : align_req;
68         AllocController P;
69         R1 r{Alloc(P)};
70         ex::memory_resource & m1 = r;
71 
72         void * const ret = m1.allocate(s, align_req);
73         assert(P.alive == 1);
74         assert(P.alloc_count == 1);
75         assert(P.checkAllocAtLeast(ret, s, align_exp));
76 
77         m1.deallocate(ret, s, align_req);
78         assert(P.alive == 0);
79         assert(P.dealloc_count == 1);
80         assert(P.checkDeallocMatchesAlloc());
81     };
82 
83     const std::size_t sizeTypeMax = ~0;
84     const std::size_t testSizeStart = sizeTypeMax - (max_align * 3);
85     const std::size_t testSizeEnd = sizeTypeMax - max_align;
86 
87     for (std::size_t size = testSizeStart; size <= testSizeEnd; ++size) {
88         for (std::size_t align=1; align <= (max_align * 2); align *= 2) {
89             check(size, align);
90         }
91     }
92 
93 #ifndef TEST_HAS_NO_EXCEPTIONS
94     for (std::size_t size = sizeTypeMax; size > testSizeEnd; --size) {
95         AllocController P;
96         R1 r{Alloc(P)};
97         ex::memory_resource & m1 = r;
98 
99         try {
100             m1.allocate(size);
101             assert(false);
102         } catch (std::exception const&) {
103         }
104     }
105 #endif
106 }
107 
main(int,char **)108 int main(int, char**)
109 {
110     check_allocate_deallocate<CountingAllocator<char>>();
111     check_allocate_deallocate<MinAlignedAllocator<char>>();
112     check_alloc_max_size();
113 
114   return 0;
115 }
116