Chunnel: Adjust z position of vehicles in chunnels to go "under" the water.
[openttd-joker.git] / src / core / dyn_arena_alloc.hpp
blob40f10bc240644746a6838cc86ab2259e05fee4fa
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
10 /** @file dyn_arena_alloc.hpp Dynamic chunk-size arena allocator. */
12 #include <vector>
14 /**
15 * Custom arena allocator for uniform-size allocations of a variable size.
16 * The allocation and chunk sizes may only be changed when the arena is empty.
18 class DynUniformArenaAllocator {
19 std::vector<void *> used_blocks;
21 void *current_block = nullptr;
22 void *last_freed = nullptr;
23 size_t next_position = 0;
25 size_t item_size = 0;
26 size_t items_per_chunk = 0;
28 void NewBlock()
30 current_block = malloc(item_size * items_per_chunk);
31 assert(current_block != nullptr);
32 next_position = 0;
33 used_blocks.push_back(current_block);
36 public:
37 DynUniformArenaAllocator() = default;
38 DynUniformArenaAllocator(const DynUniformArenaAllocator &other) = delete;
39 DynUniformArenaAllocator& operator=(const DynUniformArenaAllocator &other) = delete;
41 ~DynUniformArenaAllocator()
43 EmptyArena();
46 void EmptyArena()
48 current_block = nullptr;
49 last_freed = nullptr;
50 next_position = 0;
51 for (void *block : used_blocks) {
52 free(block);
54 used_blocks.clear();
57 void ResetArena()
59 EmptyArena();
60 item_size = 0;
61 items_per_chunk = 0;
64 void *Allocate() {
65 assert(item_size != 0);
66 if (last_freed) {
67 void *ptr = last_freed;
68 last_freed = *reinterpret_cast<void**>(ptr);
69 return ptr;
70 } else {
71 if (current_block == nullptr || next_position == items_per_chunk) {
72 NewBlock();
74 void *out = reinterpret_cast<char *>(current_block) + (item_size * next_position);
75 next_position++;
76 return out;
80 void Free(void *ptr) {
81 if (!ptr) return;
82 assert(current_block != nullptr);
84 *reinterpret_cast<void**>(ptr) = last_freed;
85 last_freed = ptr;
88 void SetParameters(size_t item_size, size_t items_per_chunk)
90 if (item_size < sizeof(void *)) item_size = sizeof(void *);
91 if (this->item_size == item_size && this->items_per_chunk == items_per_chunk) return;
93 assert(current_block == nullptr);
94 this->item_size = item_size;
95 this->items_per_chunk = items_per_chunk;