1 // Copyright (C) 2017 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef SERIALIZE_ARENA_PTR_H_
16 #define SERIALIZE_ARENA_PTR_H_
17
18 #include <google/protobuf/arena.h>
19 #include <memory>
20
21 namespace iorap {
22 namespace serialize {
23
24 /**
25 * @file
26 *
27 * Helpers for protobuf arena allocators. We use smart pointers
28 * with an arena embedded inside of them to avoid caring about the
29 * arena in other parts of libiorap.
30 */
31
32 // Arena-managed objects must not be deleted manually.
33 // When the Arena goes out of scope, it cleans everything up itself.
34 template <typename T>
DoNotDelete(T *)35 void DoNotDelete(T*) {}
36
37 template <typename T, typename Base = std::unique_ptr<T, decltype(&DoNotDelete<T>)>>
38 struct ArenaPtr : public Base {
39 template <typename... Args>
MakeArenaPtr40 static ArenaPtr<T> Make(Args&& ... args) {
41 ArenaPtr<T> arena_ptr(nullptr);
42 arena_ptr.reset(google::protobuf::Arena::Create<T>(arena_ptr.arena_.get(),
43 std::forward<Args>(args)...));
44 return arena_ptr;
45 }
46
ArenaPtrArenaPtr47 ArenaPtr(std::nullptr_t) : Base(nullptr, &DoNotDelete<T>) {} // NOLINT explicit.
48
49 private:
50 // Use a unique_ptr because Arena doesn't support move semantics.
51 std::unique_ptr<google::protobuf::Arena> arena_{new google::protobuf::Arena{}};
52 };
53
54 template <typename T, typename Base = std::shared_ptr<T>>
55 struct ArenaSharedPtr : public Base {
56 template <typename... Args>
MakeArenaSharedPtr57 static ArenaSharedPtr<T> Make(Args&& ... args) {
58 ArenaSharedPtr<T> arena_ptr(nullptr, &DoNotDelete<T>);
59 arena_ptr.reset(google::protobuf::Arena::Create<T>(arena_ptr.arena_.get(),
60 std::forward<Args>(args)...));
61 return arena_ptr;
62 }
63
64 ArenaSharedPtr() = default;
65 template <typename Deleter>
ArenaSharedPtrArenaSharedPtr66 ArenaSharedPtr(std::nullptr_t, Deleter d) : Base(nullptr, d) {} // NOLINT explicit.
67
68 private:
69 std::shared_ptr<google::protobuf::Arena> arena_{new google::protobuf::Arena{}};
70 };
71
72 } // namespace serialize
73 } // namespace iorap
74
75 #endif
76
77