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 \
52     "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
53 
54 #pragma once
55 
56 #include <stdlib.h>
57 
58 /*
59  * A memarena is used to efficiently store a collection of objects that never
60  * move The pattern is allocate more and more stuff and free all of the items at
61  * once. The underlying memory will store 1 or more objects per chunk. Each
62  * chunk is contiguously laid out in memory but chunks are not necessarily
63  * contiguous with each other.
64  */
65 class memarena {
66  public:
memarena()67   memarena()
68       : _current_chunk(arena_chunk()),
69         _other_chunks(nullptr),
70         _n_other_chunks(0),
71         _size_of_other_chunks(0),
72         _footprint_of_other_chunks(0) {}
73 
74   // Effect: Create a memarena with the specified initial size
75   void create(size_t initial_size);
76 
77   void destroy(void);
78 
79   // Effect: Allocate some memory.  The returned value remains valid until the
80   // memarena is cleared or closed.
81   //  In case of ENOMEM, aborts.
82   void *malloc_from_arena(size_t size);
83 
84   // Effect: Move all the memory from this memarena into DEST.
85   //         When SOURCE is closed the memory won't be freed.
86   //         When DEST is closed, the memory will be freed, unless DEST moves
87   //         its memory to another memarena...
88   void move_memory(memarena *dest);
89 
90   // Effect: Calculate the amount of memory used by a memory arena.
91   size_t total_memory_size(void) const;
92 
93   // Effect: Calculate the used space of the memory arena (ie: excludes unused
94   // space)
95   size_t total_size_in_use(void) const;
96 
97   // Effect: Calculate the amount of memory used, according to
98   // toku_memory_footprint(),
99   //         which is a more expensive but more accurate count of memory used.
100   size_t total_footprint(void) const;
101 
102   // iterator over the underlying chunks that store objects in the memarena.
103   // a chunk is represented by a pointer to const memory and a usable byte
104   // count.
105   class chunk_iterator {
106    public:
chunk_iterator(const memarena * ma)107     chunk_iterator(const memarena *ma) : _ma(ma), _chunk_idx(-1) {}
108 
109     // returns: base pointer to the current chunk
110     //          *used set to the number of usable bytes
111     //          if more() is false, returns nullptr and *used = 0
112     const void *current(size_t *used) const;
113 
114     // requires: more() is true
115     void next();
116 
117     bool more() const;
118 
119    private:
120     // -1 represents the 'initial' chunk in a memarena, ie: ma->_current_chunk
121     // >= 0 represents the i'th chunk in the ma->_other_chunks array
122     const memarena *_ma;
123     int _chunk_idx;
124   };
125 
126  private:
127   struct arena_chunk {
arena_chunkarena_chunk128     arena_chunk() : buf(nullptr), used(0), size(0) {}
129     char *buf;
130     size_t used;
131     size_t size;
132   };
133 
134   struct arena_chunk _current_chunk;
135   struct arena_chunk *_other_chunks;
136   int _n_other_chunks;
137   size_t _size_of_other_chunks;       // the buf_size of all the other chunks.
138   size_t _footprint_of_other_chunks;  // the footprint of all the other chunks.
139 
140   friend class memarena_unit_test;
141 };
142