1 | /* |
2 | * Copyright 2013-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | /* |
18 | * @author: Marcelo Juchem <marcelo@fb.com> |
19 | */ |
20 | |
21 | #include <folly/Memory.h> |
22 | #include <folly/memory/Arena.h> |
23 | #include <folly/portability/GTest.h> |
24 | |
25 | using namespace folly; |
26 | |
27 | struct global_counter { |
28 | global_counter() : count_(0) {} |
29 | |
30 | void increase() { |
31 | ++count_; |
32 | } |
33 | void decrease() { |
34 | EXPECT_GT(count_, 0); |
35 | --count_; |
36 | } |
37 | |
38 | unsigned count() const { |
39 | return count_; |
40 | } |
41 | |
42 | private: |
43 | unsigned count_; |
44 | }; |
45 | |
46 | struct Foo { |
47 | explicit Foo(global_counter& counter) : counter_(counter) { |
48 | counter_.increase(); |
49 | } |
50 | |
51 | ~Foo() { |
52 | counter_.decrease(); |
53 | } |
54 | |
55 | private: |
56 | global_counter& counter_; |
57 | }; |
58 | |
59 | template <typename Allocator> |
60 | void unique_ptr_test(Allocator& allocator) { |
61 | using ptr_type = std::unique_ptr<Foo, allocator_delete<Allocator>>; |
62 | |
63 | global_counter counter; |
64 | EXPECT_EQ(counter.count(), 0); |
65 | |
66 | Foo* foo = nullptr; |
67 | |
68 | { |
69 | auto p = folly::allocate_unique<Foo>(allocator, counter); |
70 | EXPECT_EQ(counter.count(), 1); |
71 | |
72 | p.reset(); |
73 | EXPECT_EQ(counter.count(), 0); |
74 | |
75 | p = folly::allocate_unique<Foo>(allocator, counter); |
76 | EXPECT_EQ(counter.count(), 1); |
77 | |
78 | foo = p.release(); |
79 | EXPECT_EQ(counter.count(), 1); |
80 | } |
81 | EXPECT_EQ(counter.count(), 1); |
82 | |
83 | { |
84 | auto p = folly::allocate_unique<Foo>(allocator, counter); |
85 | EXPECT_EQ(counter.count(), 2); |
86 | |
87 | [&](ptr_type g) { |
88 | EXPECT_EQ(counter.count(), 2); |
89 | g.reset(); |
90 | EXPECT_EQ(counter.count(), 1); |
91 | }(std::move(p)); |
92 | } |
93 | EXPECT_EQ(counter.count(), 1); |
94 | |
95 | std::allocator_traits<Allocator>::destroy(allocator, foo); |
96 | EXPECT_EQ(counter.count(), 0); |
97 | } |
98 | |
99 | TEST(ArenaSmartPtr, unique_ptr_SysArena) { |
100 | SysArena arena; |
101 | SysArenaAllocator<Foo> alloc(arena); |
102 | unique_ptr_test(alloc); |
103 | } |
104 | |
105 | template <typename Allocator> |
106 | void shared_ptr_test(Allocator& allocator) { |
107 | typedef std::shared_ptr<Foo> ptr_type; |
108 | |
109 | global_counter counter; |
110 | EXPECT_EQ(counter.count(), 0); |
111 | |
112 | ptr_type foo; |
113 | EXPECT_EQ(counter.count(), 0); |
114 | EXPECT_EQ(foo.use_count(), 0); |
115 | |
116 | { |
117 | auto p = std::allocate_shared<Foo>(allocator, counter); |
118 | EXPECT_EQ(counter.count(), 1); |
119 | EXPECT_EQ(p.use_count(), 1); |
120 | |
121 | p.reset(); |
122 | EXPECT_EQ(counter.count(), 0); |
123 | EXPECT_EQ(p.use_count(), 0); |
124 | |
125 | p = std::allocate_shared<Foo>(allocator, counter); |
126 | EXPECT_EQ(counter.count(), 1); |
127 | EXPECT_EQ(p.use_count(), 1); |
128 | |
129 | foo = p; |
130 | EXPECT_EQ(p.use_count(), 2); |
131 | } |
132 | EXPECT_EQ(counter.count(), 1); |
133 | EXPECT_EQ(foo.use_count(), 1); |
134 | |
135 | { |
136 | auto p = foo; |
137 | EXPECT_EQ(counter.count(), 1); |
138 | EXPECT_EQ(p.use_count(), 2); |
139 | |
140 | [&](ptr_type g) { |
141 | EXPECT_EQ(counter.count(), 1); |
142 | EXPECT_EQ(p.use_count(), 3); |
143 | EXPECT_EQ(g.use_count(), 3); |
144 | g.reset(); |
145 | EXPECT_EQ(counter.count(), 1); |
146 | EXPECT_EQ(p.use_count(), 2); |
147 | EXPECT_EQ(g.use_count(), 0); |
148 | }(p); |
149 | EXPECT_EQ(counter.count(), 1); |
150 | EXPECT_EQ(p.use_count(), 2); |
151 | } |
152 | EXPECT_EQ(counter.count(), 1); |
153 | EXPECT_EQ(foo.use_count(), 1); |
154 | |
155 | foo.reset(); |
156 | EXPECT_EQ(counter.count(), 0); |
157 | EXPECT_EQ(foo.use_count(), 0); |
158 | } |
159 | |
160 | TEST(ArenaSmartPtr, shared_ptr_SysArena) { |
161 | SysArena arena; |
162 | SysArenaAllocator<Foo> alloc(arena); |
163 | shared_ptr_test(alloc); |
164 | } |
165 | |
166 | int main(int argc, char* argv[]) { |
167 | testing::InitGoogleTest(&argc, argv); |
168 | return RUN_ALL_TESTS(); |
169 | } |
170 | |