/root/bitcoin/src/leveldb/util/arena.cc
| Line | Count | Source | 
| 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 |  | #include "util/arena.h" | 
| 6 |  |  | 
| 7 |  | namespace leveldb { | 
| 8 |  |  | 
| 9 |  | static const int kBlockSize = 4096; | 
| 10 |  |  | 
| 11 |  | Arena::Arena() | 
| 12 | 0 |     : alloc_ptr_(nullptr), alloc_bytes_remaining_(0), memory_usage_(0) {} | 
| 13 |  |  | 
| 14 | 2 | Arena::~Arena() { | 
| 15 | 4 |   for (size_t i = 0; i < blocks_.size(); i++) { | 
| 16 | 2 |     delete[] blocks_[i]; | 
| 17 | 2 |   } | 
| 18 | 2 | } | 
| 19 |  |  | 
| 20 | 0 | char* Arena::AllocateFallback(size_t bytes) { | 
| 21 | 0 |   if (bytes > kBlockSize / 4) { | 
| 22 |  |     // Object is more than a quarter of our block size.  Allocate it separately | 
| 23 |  |     // to avoid wasting too much space in leftover bytes. | 
| 24 | 0 |     char* result = AllocateNewBlock(bytes); | 
| 25 | 0 |     return result; | 
| 26 | 0 |   } | 
| 27 |  |  | 
| 28 |  |   // We waste the remaining space in the current block. | 
| 29 | 0 |   alloc_ptr_ = AllocateNewBlock(kBlockSize); | 
| 30 | 0 |   alloc_bytes_remaining_ = kBlockSize; | 
| 31 |  | 
 | 
| 32 | 0 |   char* result = alloc_ptr_; | 
| 33 | 0 |   alloc_ptr_ += bytes; | 
| 34 | 0 |   alloc_bytes_remaining_ -= bytes; | 
| 35 | 0 |   return result; | 
| 36 | 0 | } | 
| 37 |  |  | 
| 38 | 0 | char* Arena::AllocateAligned(size_t bytes) { | 
| 39 | 0 |   const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; | 
| 40 | 0 |   static_assert((align & (align - 1)) == 0, | 
| 41 | 0 |                 "Pointer size should be a power of 2"); | 
| 42 | 0 |   size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align - 1); | 
| 43 | 0 |   size_t slop = (current_mod == 0 ? 0 : align - current_mod); | 
| 44 | 0 |   size_t needed = bytes + slop; | 
| 45 | 0 |   char* result; | 
| 46 | 0 |   if (needed <= alloc_bytes_remaining_) { | 
| 47 | 0 |     result = alloc_ptr_ + slop; | 
| 48 | 0 |     alloc_ptr_ += needed; | 
| 49 | 0 |     alloc_bytes_remaining_ -= needed; | 
| 50 | 0 |   } else { | 
| 51 |  |     // AllocateFallback always returned aligned memory | 
| 52 | 0 |     result = AllocateFallback(bytes); | 
| 53 | 0 |   } | 
| 54 | 0 |   assert((reinterpret_cast<uintptr_t>(result) & (align - 1)) == 0); | 
| 55 | 0 |   return result; | 
| 56 | 0 | } | 
| 57 |  |  | 
| 58 | 0 | char* Arena::AllocateNewBlock(size_t block_bytes) { | 
| 59 | 0 |   char* result = new char[block_bytes]; | 
| 60 | 0 |   blocks_.push_back(result); | 
| 61 | 0 |   memory_usage_.fetch_add(block_bytes + sizeof(char*), | 
| 62 | 0 |                           std::memory_order_relaxed); | 
| 63 | 0 |   return result; | 
| 64 | 0 | } | 
| 65 |  |  | 
| 66 |  | }  // namespace leveldb |