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