• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
9 #define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
10 
11 #include <cstddef>
12 
13 #include "absl/container/flat_hash_set.h"
14 #include "absl/log/absl_check.h"
15 #include "google/protobuf/arena.h"
16 #include "google/protobuf/io/coded_stream.h"
17 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
18 
19 // Must be included last.
20 #include "google/protobuf/port_def.inc"
21 
22 namespace google {
23 namespace protobuf {
24 namespace internal {
25 
26 struct ArenaTestPeer {
ReturnArrayMemoryArenaTestPeer27   static void ReturnArrayMemory(Arena* arena, void* p, size_t size) {
28     arena->ReturnArrayMemory(p, size);
29   }
PeekCleanupListForTestingArenaTestPeer30   static auto PeekCleanupListForTesting(Arena* arena) {
31     return arena->PeekCleanupListForTesting();
32   }
33   template <typename T, typename... U>
GetConstructTypeArenaTestPeer34   static constexpr auto GetConstructType() {
35     return Arena::GetConstructType<T, U...>();
36   }
37   using ConstructType = Arena::ConstructType;
38 };
39 
40 struct CleanupGrowthInfo {
41   size_t space_used;
42   absl::flat_hash_set<void*> cleanups;
43 };
44 
45 template <typename Func>
CleanupGrowth(Arena & arena,Func f)46 CleanupGrowthInfo CleanupGrowth(Arena& arena, Func f) {
47   auto old_space_used = arena.SpaceUsed();
48   auto old_cleanups = ArenaTestPeer::PeekCleanupListForTesting(&arena);
49   f();
50   auto new_space_used = arena.SpaceUsed();
51   auto new_cleanups = ArenaTestPeer::PeekCleanupListForTesting(&arena);
52   CleanupGrowthInfo res;
53   res.space_used = new_space_used - old_space_used;
54   res.cleanups.insert(new_cleanups.begin(), new_cleanups.end());
55   for (auto p : old_cleanups) res.cleanups.erase(p);
56   return res;
57 }
58 
59 class NoHeapChecker {
60  public:
NoHeapChecker()61   NoHeapChecker() { capture_alloc.Hook(); }
62   ~NoHeapChecker();
63 
64  private:
65   class NewDeleteCapture {
66    public:
67     // TODO: Implement this for opensource protobuf.
Hook()68     void Hook() {}
Unhook()69     void Unhook() {}
alloc_count()70     int alloc_count() { return 0; }
free_count()71     int free_count() { return 0; }
72   } capture_alloc;
73 };
74 
75 // Owns the internal T only if it's not owned by an arena.
76 // T needs to be arena constructible and destructor skippable.
77 template <typename T>
78 class ArenaHolder {
79  public:
ArenaHolder(Arena * arena)80   explicit ArenaHolder(Arena* arena)
81       : field_(Arena::Create<T>(arena)), owned_by_arena_(arena != nullptr) {
82     ABSL_DCHECK(google::protobuf::Arena::is_arena_constructable<T>::value);
83     ABSL_DCHECK(google::protobuf::Arena::is_destructor_skippable<T>::value);
84   }
85 
~ArenaHolder()86   ~ArenaHolder() {
87     if (!owned_by_arena_) {
88       delete field_;
89     }
90   }
91 
get()92   T* get() { return field_; }
93   T* operator->() { return field_; }
94   T& operator*() { return *field_; }
95 
96  private:
97   T* field_;
98   bool owned_by_arena_;
99 };
100 
101 }  // namespace internal
102 }  // namespace protobuf
103 }  // namespace google
104 
105 #include "google/protobuf/port_undef.inc"
106 
107 #endif  // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
108