1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// Author: Ge,Jun (gejun@baidu.com)
// Date: Fri Jun 5 18:25:40 CST 2015
// Do small memory allocations on continuous blocks.
#ifndef BUTIL_ARENA_H
#define BUTIL_ARENA_H
#include <stdint.h>
#include "butil/macros.h"
namespace butil {
struct ArenaOptions {
size_t initial_block_size;
size_t max_block_size;
// Constructed with default options.
ArenaOptions();
};
// Just a proof-of-concept, will be refactored in future CI.
class Arena {
public:
explicit Arena(const ArenaOptions& options = ArenaOptions());
~Arena();
void swap(Arena&);
void* allocate(size_t n);
void* allocate_aligned(size_t n); // not implemented.
void clear();
private:
DISALLOW_COPY_AND_ASSIGN(Arena);
struct Block {
uint32_t left_space() const { return size - alloc_size; }
Block* next;
uint32_t alloc_size;
uint32_t size;
char data[0];
};
void* allocate_in_other_blocks(size_t n);
void* allocate_new_block(size_t n);
Block* pop_block(Block* & head) {
Block* saved_head = head;
head = head->next;
return saved_head;
}
Block* _cur_block;
Block* _isolated_blocks;
size_t _block_size;
ArenaOptions _options;
};
inline void* Arena::allocate(size_t n) {
if (_cur_block != NULL && _cur_block->left_space() >= n) {
void* ret = _cur_block->data + _cur_block->alloc_size;
_cur_block->alloc_size += n;
return ret;
}
return allocate_in_other_blocks(n);
}
} // namespace butil
#endif // BUTIL_ARENA_H