CUBRID Engine  latest
mem_block.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * mem_block.hpp - Memory Block Functionality
21  *
22  * Memory Block is defined as a contiguous memory buffer.
23  *
24  * Glossary:
25  *
26  * block - the pair of memory pointer and size.
27  * stack block - a block on stack memory
28  * heap block - a block on heap memory; does not have its own structure (a simple block can be used).
29  * extensible block - a block that can be extended when required
30  * extensible stack block - a block that starts as a stack block and can be extended to a heap block.
31  */
32 
33 #ifndef _MEM_BLOCK_HPP_
34 #define _MEM_BLOCK_HPP_
35 
36 #include <memory.h>
37 #include <functional>
38 
39 #include <cassert>
40 #include <cinttypes>
41 
42 namespace cubmem
43 {
44  const size_t DEFAULT_ALIGNMENT = 8;
45  template <typename T>
46  inline T *ptr_align (T *ptr);
47 
48  /*
49  * Memory Block
50  * - groups together memory address and its size
51  * - doesn't own the memory, just points to it
52  * - used to allocate, deallocate and share memory
53  * - could be extended with helper info: allocator, src file&line where allocation was made, ...
54  */
55  struct block
56  {
57  public:
58  size_t dim;
59  char *ptr;
60 
61  inline block ();
62  inline block (size_t dim, void *ptr);
63  inline block (block &&b); //move ctor
64 
65  inline block &operator= (block &&b); //move assign
66 
67  inline bool is_valid () const;
68 
69  inline char *move_ptr (); //NOT RECOMMENDED! use move semantics: std::move()
70 
71  private:
72  block (const block &) = delete;
73  block &operator= (const block &) = delete;
74  };
75 
76  // stack_block - 8-byte aligned stack block of size S
77  //
78  template <size_t S>
80  {
81  public:
82  static const size_t SIZE = S;
83 
84  stack_block (void) = default;
85  inline char *get_ptr (void);
86  inline const char *get_read_ptr () const;
87 
88  private:
89  union
90  {
91  char m_buf[SIZE];
92  std::int64_t dummy;
93  };
94  };
95 
96  // block_allocator - allocation, deallocation and reallocation of memory blocks. it preserves the contents of the
97  // block on reallocation
98  //
100  {
101  public:
102  using alloc_func = std::function<void (block &b, size_t size)>;
103  using dealloc_func = std::function<void (block &b)>;
104 
105  alloc_func m_alloc_f; // allocator/reallocator
106  dealloc_func m_dealloc_f; // deallocator
107 
108  block_allocator () = delete;
109  block_allocator (const alloc_func &alloc_f, const dealloc_func &dealloc_f);
110 
112  };
116 
117  // single_block_allocator - maintains and allocates a single memory block
118  //
119  // it is designed as a memory cache that can be reused for multiple purposes in multiple places. must be used with
120  // care because it doesn't guarantee exclusive access to memory
121  //
122  // use get_block_allocator to pass the cached memory block to structures like extensible_buffer
123  //
125  {
126  public:
127  single_block_allocator (const block_allocator &base_alloc);
129 
130  const block_allocator &get_block_allocator () const; // a block allocator that always outputs m_block
131  const block &get_block () const;
132 
133  char *get_ptr () const;
134  size_t get_size () const;
135 
136  void reserve (size_t size);
137 
138  private:
139 
140  void allocate (block &b, size_t size); // the output b will be always equal to m_block
141  void deallocate (block &b);
142 
143  const block_allocator &m_base_allocator; // allocator for m_block
144 
145  block m_block; // the single block
146  block_allocator m_allocator; // allocator that always outputs m_block
147  };
148 
149  /* Memory Block - Extensible
150  * - able to extend/reallocate to accommodate additional bytes
151  * - owns the memory by default and it will free the memory in destructor unless it is moved:
152  * {
153  * cubmem::block_ext block{some_realloc, some_dealloc};//some_realloc/dealloc = functions, functors or lambdas
154  * //...
155  * //move it or it will be deallocated; simple copy => compiler error because it is not designed to be copied
156  * cubmem::block b = std::move(block);
157  * }
158  */
160  {
161  public:
162  inline extensible_block (); //default ctor
163  inline extensible_block (extensible_block &&b); //move ctor
164  inline extensible_block (const block_allocator &alloc); //general ctor
165  inline ~extensible_block (); //dtor
166 
167  inline extensible_block &operator= (extensible_block &&b); //move assignment
168 
169  inline void extend_by (size_t additional_bytes);
170  inline void extend_to (size_t total_bytes);
171  inline void freemem ();
172 
173  inline char *get_ptr ();
174  inline const char *get_read_ptr () const;
175 
176  inline std::size_t get_size () const;
177 
178  inline char *release_ptr ();
179 
180  private:
183 
184  extensible_block (const extensible_block &) = delete; //copy ctor
185  extensible_block &operator= (const extensible_block &) = delete; //copy assignment
186  };
187 
188  // extensible_stack_block - extensible memory block that start with as a stack_block
189  //
190  template <size_t S>
192  {
193  public:
196 
197  inline void extend_by (size_t additional_bytes);
198  inline void extend_to (size_t total_bytes);
199 
200  inline char *get_ptr ();
201  inline const char *get_read_ptr () const;
202 
203  private:
207  };
208 } // namespace cubmem
209 
211 // inline/template implementation
213 
214 namespace cubmem
215 {
216  //
217  // alignment
218  //
219  template <typename T>
220  T *
222  {
223  std::uintptr_t pt = (std::uintptr_t) ptr;
224  pt = (pt + DEFAULT_ALIGNMENT - 1) & (DEFAULT_ALIGNMENT - 1);
225  return (T *) pt;
226  }
227 
228  //
229  // block
230  //
232  : dim { 0 }
233  , ptr { NULL }
234  {
235  }
236 
238  : dim {b.dim}
239  , ptr {b.ptr}
240  {
241  b.dim = 0;
242  b.ptr = NULL;
243  }
244 
245  block::block (size_t dim, void *ptr)
246  : dim {dim}
247  , ptr { (char *) ptr}
248  {
249  }
250 
251  block &
252  block::operator= (block &&b) //move assign
253  {
254  if (this != &b)
255  {
256  dim = b.dim;
257  ptr = b.ptr;
258  b.dim = 0;
259  b.ptr = NULL;
260  }
261  return *this;
262  }
263 
264  bool
266  {
267  return (dim != 0 && ptr != NULL);
268  }
269 
270  char *
272  {
273  char *p = ptr;
274 
275  dim = 0;
276  ptr = NULL;
277 
278  return p;
279  }
280 
281  //
282  // stack_block
283  //
284  template <size_t S>
285  char *
287  {
288  return &m_buf[0];
289  }
290 
291  template <size_t S>
292  const char *
294  {
295  return &m_buf[0];
296  }
297 
298  //
299  // extensible_block
300  //
303  {
304  }
305 
308  {
309  b.m_block.dim = 0;
310  b.m_block.ptr = NULL;
311  }
312 
314  : m_block {}
315  , m_allocator (&alloc)
316  {
317  }
318 
321  {
322  if (this != &b)
323  {
324  this->~extensible_block ();
325  m_allocator = b.m_allocator;
326  m_block.dim = b.m_block.dim;
327  m_block.ptr = b.m_block.ptr;
328  b.m_block.dim = 0;
329  b.m_block.ptr = NULL;
330  }
331  return *this;
332  }
333 
335  {
337  }
338 
339  void
340  extensible_block::extend_by (size_t additional_bytes)
341  {
342  m_allocator->m_alloc_f (m_block, m_block.dim + additional_bytes);
343  }
344 
345  void
346  extensible_block::extend_to (size_t total_bytes)
347  {
348  if (total_bytes <= m_block.dim)
349  {
350  return;
351  }
352  extend_by (total_bytes - m_block.dim);
353  }
354 
355  void
357  {
359  }
360 
361  char *
363  {
364  return m_block.ptr;
365  }
366 
367  const char *
369  {
370  return m_block.ptr;
371  }
372 
373  std::size_t
375  {
376  return m_block.dim;
377  }
378 
379  char *
381  {
382  char *ret_ptr = m_block.ptr;
383  m_block.ptr = NULL;
384  m_block.dim = 0;
385  return ret_ptr;
386  }
387 
388  //
389  // extensible_stack_block
390  //
391  template <size_t S>
393  : m_stack ()
394  , m_ext_block ()
395  , m_use_stack (true)
396  {
397  }
398 
399  template <size_t S>
401  : m_stack ()
402  , m_ext_block (alloc)
403  , m_use_stack (true)
404  {
405  }
406 
407  template <size_t S>
408  void
409  extensible_stack_block<S>::extend_by (size_t additional_bytes)
410  {
411  if (m_use_stack)
412  {
413  m_ext_block.extend_to (m_stack.SIZE + additional_bytes);
414  }
415  else
416  {
417  m_ext_block.extend_by (additional_bytes);
418  }
419  m_use_stack = false;
420  }
421 
422  template <size_t S>
423  void
425  {
426  if (total_bytes <= m_stack.SIZE)
427  {
428  return;
429  }
430  m_ext_block.extend_to (total_bytes);
431  m_use_stack = false;
432  }
433 
434  template <size_t S>
435  char *
437  {
438  return m_use_stack ? m_stack.get_ptr () : m_ext_block.get_ptr ();
439  }
440 
441  template <size_t S>
442  const char *
444  {
445  return m_use_stack ? m_stack.get_read_ptr () : m_ext_block.get_read_ptr ();
446  }
447 } // namespace cubmem
448 
449 #endif // _MEM_BLOCK_HPP_
void extend_by(size_t additional_bytes)
Definition: mem_block.hpp:340
const block_allocator CSTYLE_BLOCK_ALLOCATOR
Definition: mem_block.cpp:127
void extend_to(size_t total_bytes)
Definition: mem_block.hpp:424
std::function< void(block &b)> dealloc_func
Definition: mem_block.hpp:103
const char * get_read_ptr() const
Definition: mem_block.hpp:293
char * move_ptr()
Definition: mem_block.hpp:271
bool is_valid() const
Definition: mem_block.hpp:265
const block_allocator STANDARD_BLOCK_ALLOCATOR
Definition: mem_block.cpp:62
std::size_t get_size() const
Definition: mem_block.hpp:374
extensible_block m_ext_block
Definition: mem_block.hpp:205
const block_allocator & m_base_allocator
Definition: mem_block.hpp:143
char * get_ptr(void)
Definition: mem_block.hpp:286
extensible_block & operator=(extensible_block &&b)
Definition: mem_block.hpp:320
std::function< void(block &b, size_t size)> alloc_func
Definition: mem_block.hpp:102
#define NULL
Definition: freelistheap.h:34
const char * get_read_ptr() const
Definition: mem_block.hpp:368
dealloc_func m_dealloc_f
Definition: mem_block.hpp:106
std::int64_t dummy
Definition: mem_block.hpp:92
void extend_by(size_t additional_bytes)
Definition: mem_block.hpp:409
const block_allocator * m_allocator
Definition: mem_block.hpp:182
block & operator=(block &&b)
Definition: mem_block.hpp:252
T * ptr_align(T *ptr)
Definition: mem_block.hpp:221
const size_t DEFAULT_ALIGNMENT
Definition: mem_block.hpp:44
void extend_to(size_t total_bytes)
Definition: mem_block.hpp:346
const block_allocator EXPONENTIAL_STANDARD_BLOCK_ALLOCATOR
Definition: mem_block.cpp:94
const char * get_read_ptr() const
Definition: mem_block.hpp:443
const char ** p
Definition: dynamic_load.c:945