1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: 3 #ident "$Id$" 4 /*====== 5 This file is part of PerconaFT. 6 7 8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. 9 10 PerconaFT is free software: you can redistribute it and/or modify 11 it under the terms of the GNU General Public License, version 2, 12 as published by the Free Software Foundation. 13 14 PerconaFT is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 21 22 ---------------------------------------- 23 24 PerconaFT is free software: you can redistribute it and/or modify 25 it under the terms of the GNU Affero General Public License, version 3, 26 as published by the Free Software Foundation. 27 28 PerconaFT is distributed in the hope that it will be useful, 29 but WITHOUT ANY WARRANTY; without even the implied warranty of 30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 GNU Affero General Public License for more details. 32 33 You should have received a copy of the GNU Affero General Public License 34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 35 36 ---------------------------------------- 37 38 Licensed under the Apache License, Version 2.0 (the "License"); 39 you may not use this file except in compliance with the License. 40 You may obtain a copy of the License at 41 42 http://www.apache.org/licenses/LICENSE-2.0 43 44 Unless required by applicable law or agreed to in writing, software 45 distributed under the License is distributed on an "AS IS" BASIS, 46 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 47 See the License for the specific language governing permissions and 48 limitations under the License. 49 ======= */ 50 51 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." 52 53 #pragma once 54 55 /* 56 * A memarena is used to efficiently store a collection of objects that never move 57 * The pattern is allocate more and more stuff and free all of the items at once. 58 * The underlying memory will store 1 or more objects per chunk. Each chunk is 59 * contiguously laid out in memory but chunks are not necessarily contiguous with 60 * each other. 61 */ 62 class memarena { 63 public: memarena()64 memarena() : 65 _current_chunk(arena_chunk()), 66 _other_chunks(nullptr), 67 _n_other_chunks(0), 68 _size_of_other_chunks(0), 69 _footprint_of_other_chunks(0) { 70 } 71 72 // Effect: Create a memarena with the specified initial size 73 void create(size_t initial_size); 74 75 void destroy(void); 76 77 // Effect: Allocate some memory. The returned value remains valid until the memarena is cleared or closed. 78 // In case of ENOMEM, aborts. 79 void *malloc_from_arena(size_t size); 80 81 // Effect: Move all the memory from this memarena into DEST. 82 // When SOURCE is closed the memory won't be freed. 83 // When DEST is closed, the memory will be freed, unless DEST moves its memory to another memarena... 84 void move_memory(memarena *dest); 85 86 // Effect: Calculate the amount of memory used by a memory arena. 87 size_t total_memory_size(void) const; 88 89 // Effect: Calculate the used space of the memory arena (ie: excludes unused space) 90 size_t total_size_in_use(void) const; 91 92 // Effect: Calculate the amount of memory used, according to toku_memory_footprint(), 93 // which is a more expensive but more accurate count of memory used. 94 size_t total_footprint(void) const; 95 96 // iterator over the underlying chunks that store objects in the memarena. 97 // a chunk is represented by a pointer to const memory and a usable byte count. 98 class chunk_iterator { 99 public: chunk_iterator(const memarena * ma)100 chunk_iterator(const memarena *ma) : 101 _ma(ma), _chunk_idx(-1) { 102 } 103 104 // returns: base pointer to the current chunk 105 // *used set to the number of usable bytes 106 // if more() is false, returns nullptr and *used = 0 107 const void *current(size_t *used) const; 108 109 // requires: more() is true 110 void next(); 111 112 bool more() const; 113 114 private: 115 // -1 represents the 'initial' chunk in a memarena, ie: ma->_current_chunk 116 // >= 0 represents the i'th chunk in the ma->_other_chunks array 117 const memarena *_ma; 118 int _chunk_idx; 119 }; 120 121 private: 122 struct arena_chunk { arena_chunkarena_chunk123 arena_chunk() : buf(nullptr), used(0), size(0) { } 124 char *buf; 125 size_t used; 126 size_t size; 127 }; 128 129 struct arena_chunk _current_chunk; 130 struct arena_chunk *_other_chunks; 131 int _n_other_chunks; 132 size_t _size_of_other_chunks; // the buf_size of all the other chunks. 133 size_t _footprint_of_other_chunks; // the footprint of all the other chunks. 134 135 friend class memarena_unit_test; 136 }; 137