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