xref: /aosp_15_r20/external/leveldb/util/arena.h (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker 
5*9507f98cSAndroid Build Coastguard Worker #ifndef STORAGE_LEVELDB_UTIL_ARENA_H_
6*9507f98cSAndroid Build Coastguard Worker #define STORAGE_LEVELDB_UTIL_ARENA_H_
7*9507f98cSAndroid Build Coastguard Worker 
8*9507f98cSAndroid Build Coastguard Worker #include <atomic>
9*9507f98cSAndroid Build Coastguard Worker #include <cassert>
10*9507f98cSAndroid Build Coastguard Worker #include <cstddef>
11*9507f98cSAndroid Build Coastguard Worker #include <cstdint>
12*9507f98cSAndroid Build Coastguard Worker #include <vector>
13*9507f98cSAndroid Build Coastguard Worker 
14*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
15*9507f98cSAndroid Build Coastguard Worker 
16*9507f98cSAndroid Build Coastguard Worker class Arena {
17*9507f98cSAndroid Build Coastguard Worker  public:
18*9507f98cSAndroid Build Coastguard Worker   Arena();
19*9507f98cSAndroid Build Coastguard Worker 
20*9507f98cSAndroid Build Coastguard Worker   Arena(const Arena&) = delete;
21*9507f98cSAndroid Build Coastguard Worker   Arena& operator=(const Arena&) = delete;
22*9507f98cSAndroid Build Coastguard Worker 
23*9507f98cSAndroid Build Coastguard Worker   ~Arena();
24*9507f98cSAndroid Build Coastguard Worker 
25*9507f98cSAndroid Build Coastguard Worker   // Return a pointer to a newly allocated memory block of "bytes" bytes.
26*9507f98cSAndroid Build Coastguard Worker   char* Allocate(size_t bytes);
27*9507f98cSAndroid Build Coastguard Worker 
28*9507f98cSAndroid Build Coastguard Worker   // Allocate memory with the normal alignment guarantees provided by malloc.
29*9507f98cSAndroid Build Coastguard Worker   char* AllocateAligned(size_t bytes);
30*9507f98cSAndroid Build Coastguard Worker 
31*9507f98cSAndroid Build Coastguard Worker   // Returns an estimate of the total memory usage of data allocated
32*9507f98cSAndroid Build Coastguard Worker   // by the arena.
MemoryUsage()33*9507f98cSAndroid Build Coastguard Worker   size_t MemoryUsage() const {
34*9507f98cSAndroid Build Coastguard Worker     return memory_usage_.load(std::memory_order_relaxed);
35*9507f98cSAndroid Build Coastguard Worker   }
36*9507f98cSAndroid Build Coastguard Worker 
37*9507f98cSAndroid Build Coastguard Worker  private:
38*9507f98cSAndroid Build Coastguard Worker   char* AllocateFallback(size_t bytes);
39*9507f98cSAndroid Build Coastguard Worker   char* AllocateNewBlock(size_t block_bytes);
40*9507f98cSAndroid Build Coastguard Worker 
41*9507f98cSAndroid Build Coastguard Worker   // Allocation state
42*9507f98cSAndroid Build Coastguard Worker   char* alloc_ptr_;
43*9507f98cSAndroid Build Coastguard Worker   size_t alloc_bytes_remaining_;
44*9507f98cSAndroid Build Coastguard Worker 
45*9507f98cSAndroid Build Coastguard Worker   // Array of new[] allocated memory blocks
46*9507f98cSAndroid Build Coastguard Worker   std::vector<char*> blocks_;
47*9507f98cSAndroid Build Coastguard Worker 
48*9507f98cSAndroid Build Coastguard Worker   // Total memory usage of the arena.
49*9507f98cSAndroid Build Coastguard Worker   //
50*9507f98cSAndroid Build Coastguard Worker   // TODO(costan): This member is accessed via atomics, but the others are
51*9507f98cSAndroid Build Coastguard Worker   //               accessed without any locking. Is this OK?
52*9507f98cSAndroid Build Coastguard Worker   std::atomic<size_t> memory_usage_;
53*9507f98cSAndroid Build Coastguard Worker };
54*9507f98cSAndroid Build Coastguard Worker 
Allocate(size_t bytes)55*9507f98cSAndroid Build Coastguard Worker inline char* Arena::Allocate(size_t bytes) {
56*9507f98cSAndroid Build Coastguard Worker   // The semantics of what to return are a bit messy if we allow
57*9507f98cSAndroid Build Coastguard Worker   // 0-byte allocations, so we disallow them here (we don't need
58*9507f98cSAndroid Build Coastguard Worker   // them for our internal use).
59*9507f98cSAndroid Build Coastguard Worker   assert(bytes > 0);
60*9507f98cSAndroid Build Coastguard Worker   if (bytes <= alloc_bytes_remaining_) {
61*9507f98cSAndroid Build Coastguard Worker     char* result = alloc_ptr_;
62*9507f98cSAndroid Build Coastguard Worker     alloc_ptr_ += bytes;
63*9507f98cSAndroid Build Coastguard Worker     alloc_bytes_remaining_ -= bytes;
64*9507f98cSAndroid Build Coastguard Worker     return result;
65*9507f98cSAndroid Build Coastguard Worker   }
66*9507f98cSAndroid Build Coastguard Worker   return AllocateFallback(bytes);
67*9507f98cSAndroid Build Coastguard Worker }
68*9507f98cSAndroid Build Coastguard Worker 
69*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
70*9507f98cSAndroid Build Coastguard Worker 
71*9507f98cSAndroid Build Coastguard Worker #endif  // STORAGE_LEVELDB_UTIL_ARENA_H_
72