911c3c37bc256e502d4b4c42697b57c49cd77fba
[folly.git] / folly / test / ArenaSmartPtrTest.cpp
1 /*
2  * Copyright 2017 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/Arena.h>
22 #include <folly/Memory.h>
23 #include <folly/portability/GTest.h>
24
25 using namespace folly;
26
27 static_assert(
28   is_simple_allocator<int,SysArena>::value,
29   "SysArena should be a simple allocator"
30 );
31
32 struct global_counter {
33   global_counter(): count_(0) {}
34
35   void increase() { ++count_; }
36   void decrease() {
37     EXPECT_GT(count_, 0);
38     --count_;
39   }
40
41   unsigned count() const { return count_; }
42
43  private:
44   unsigned count_;
45 };
46
47 struct Foo {
48   explicit Foo(global_counter& counter):
49     counter_(counter)
50   {
51     counter_.increase();
52   }
53
54   ~Foo() {
55     counter_.decrease();
56   }
57
58  private:
59   global_counter& counter_;
60 };
61
62 template <typename Allocator>
63 void unique_ptr_test(Allocator& allocator) {
64   typedef typename AllocatorUniquePtr<Foo, Allocator>::type ptr_type;
65
66   global_counter counter;
67   EXPECT_EQ(counter.count(), 0);
68
69   Foo* foo = nullptr;
70
71   {
72     auto p = folly::allocate_unique<Foo>(allocator, counter);
73     EXPECT_EQ(counter.count(), 1);
74
75     p.reset();
76     EXPECT_EQ(counter.count(), 0);
77
78     p = folly::allocate_unique<Foo>(allocator, counter);
79     EXPECT_EQ(counter.count(), 1);
80
81     foo = p.release();
82     EXPECT_EQ(counter.count(), 1);
83   }
84   EXPECT_EQ(counter.count(), 1);
85
86   {
87     auto p = folly::allocate_unique<Foo>(allocator, counter);
88     EXPECT_EQ(counter.count(), 2);
89
90     [&](ptr_type g) {
91       EXPECT_EQ(counter.count(), 2);
92       g.reset();
93       EXPECT_EQ(counter.count(), 1);
94     }(std::move(p));
95   }
96   EXPECT_EQ(counter.count(), 1);
97
98   StlAllocator<Allocator, Foo>().destroy(foo);
99   EXPECT_EQ(counter.count(), 0);
100 }
101
102 TEST(ArenaSmartPtr, unique_ptr_SysArena) {
103   SysArena arena;
104   unique_ptr_test(arena);
105 }
106
107 TEST(ArenaSmartPtr, unique_ptr_StlAlloc_SysArena) {
108   SysArena arena;
109   StlAllocator<SysArena, Foo> alloc(&arena);
110   unique_ptr_test(alloc);
111 }
112
113 template <typename Allocator>
114 void shared_ptr_test(Allocator& allocator) {
115   typedef std::shared_ptr<Foo> ptr_type;
116
117   global_counter counter;
118   EXPECT_EQ(counter.count(), 0);
119
120   ptr_type foo;
121   EXPECT_EQ(counter.count(), 0);
122   EXPECT_EQ(foo.use_count(), 0);
123
124   {
125     auto p = folly::allocate_shared<Foo>(allocator, counter);
126     EXPECT_EQ(counter.count(), 1);
127     EXPECT_EQ(p.use_count(), 1);
128
129     p.reset();
130     EXPECT_EQ(counter.count(), 0);
131     EXPECT_EQ(p.use_count(), 0);
132
133     p = folly::allocate_shared<Foo>(allocator, counter);
134     EXPECT_EQ(counter.count(), 1);
135     EXPECT_EQ(p.use_count(), 1);
136
137     foo = p;
138     EXPECT_EQ(p.use_count(), 2);
139   }
140   EXPECT_EQ(counter.count(), 1);
141   EXPECT_EQ(foo.use_count(), 1);
142
143   {
144     auto p = foo;
145     EXPECT_EQ(counter.count(), 1);
146     EXPECT_EQ(p.use_count(), 2);
147
148     [&](ptr_type g) {
149       EXPECT_EQ(counter.count(), 1);
150       EXPECT_EQ(p.use_count(), 3);
151       EXPECT_EQ(g.use_count(), 3);
152       g.reset();
153       EXPECT_EQ(counter.count(), 1);
154       EXPECT_EQ(p.use_count(), 2);
155       EXPECT_EQ(g.use_count(), 0);
156     }(p);
157     EXPECT_EQ(counter.count(), 1);
158     EXPECT_EQ(p.use_count(), 2);
159   }
160   EXPECT_EQ(counter.count(), 1);
161   EXPECT_EQ(foo.use_count(), 1);
162
163   foo.reset();
164   EXPECT_EQ(counter.count(), 0);
165   EXPECT_EQ(foo.use_count(), 0);
166 }
167
168 TEST(ArenaSmartPtr, shared_ptr_SysArena) {
169   SysArena arena;
170   shared_ptr_test(arena);
171 }
172
173 TEST(ArenaSmartPtr, shared_ptr_StlAlloc_SysArena) {
174   SysArena arena;
175   StlAllocator<SysArena, Foo> alloc(&arena);
176   shared_ptr_test(alloc);
177 }
178
179 int main(int argc, char *argv[]) {
180   testing::InitGoogleTest(&argc, argv);
181   return RUN_ALL_TESTS();
182 }