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.
5 #include "util/arena.h"
10 static const int kBlockSize
= 4096;
12 Arena::Arena() : memory_usage_(0) {
13 alloc_ptr_
= NULL
; // First allocation will allocate a block
14 alloc_bytes_remaining_
= 0;
18 for (size_t i
= 0; i
< blocks_
.size(); i
++) {
23 char* Arena::AllocateFallback(size_t bytes
) {
24 if (bytes
> kBlockSize
/ 4) {
25 // Object is more than a quarter of our block size. Allocate it separately
26 // to avoid wasting too much space in leftover bytes.
27 char* result
= AllocateNewBlock(bytes
);
31 // We waste the remaining space in the current block.
32 alloc_ptr_
= AllocateNewBlock(kBlockSize
);
33 alloc_bytes_remaining_
= kBlockSize
;
35 char* result
= alloc_ptr_
;
37 alloc_bytes_remaining_
-= bytes
;
41 char* Arena::AllocateAligned(size_t bytes
) {
42 const int align
= (sizeof(void*) > 8) ? sizeof(void*) : 8;
43 assert((align
& (align
-1)) == 0); // Pointer size should be a power of 2
44 size_t current_mod
= reinterpret_cast<uintptr_t>(alloc_ptr_
) & (align
-1);
45 size_t slop
= (current_mod
== 0 ? 0 : align
- current_mod
);
46 size_t needed
= bytes
+ slop
;
48 if (needed
<= alloc_bytes_remaining_
) {
49 result
= alloc_ptr_
+ slop
;
51 alloc_bytes_remaining_
-= needed
;
53 // AllocateFallback always returned aligned memory
54 result
= AllocateFallback(bytes
);
56 assert((reinterpret_cast<uintptr_t>(result
) & (align
-1)) == 0);
60 char* Arena::AllocateNewBlock(size_t block_bytes
) {
61 char* result
= new char[block_bytes
];
62 blocks_
.push_back(result
);
63 memory_usage_
.NoBarrier_Store(
64 reinterpret_cast<void*>(MemoryUsage() + block_bytes
+ sizeof(char*)));
68 } // namespace leveldb