CXXR (C++ R)
CellHeap.hpp
Go to the documentation of this file.
1 /*CXXR $Id: CellHeap.hpp 1348 2013-02-25 17:49:03Z arr $
2  *CXXR
3  *CXXR This file is part of CXXR, a project to refactor the R interpreter
4  *CXXR into C++. It may consist in whole or in part of program code and
5  *CXXR documentation taken from the R project itself, incorporated into
6  *CXXR CXXR (and possibly MODIFIED) under the terms of the GNU General Public
7  *CXXR Licence.
8  *CXXR
9  *CXXR CXXR is Copyright (C) 2008-13 Andrew R. Runnalls, subject to such other
10  *CXXR copyrights and copyright restrictions as may be stated below.
11  *CXXR
12  *CXXR CXXR is not part of the R project, and bugs and other issues should
13  *CXXR not be reported via r-bugs or other R project channels; instead refer
14  *CXXR to the CXXR website.
15  *CXXR */
16 
17 /*
18  * R : A Computer Language for Statistical Data Analysis
19  *
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation; either version 2.1 of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, a copy is available at
32  * http://www.r-project.org/Licenses/
33  */
34 
40 #ifndef CELLHEAP_HPP
41 #define CELLHEAP_HPP
42 
43 #include <cstddef>
44 #include <new>
45 #include <vector>
46 
47 #include "Rvalgrind.h"
48 
49 namespace CXXR {
62  class CellHeap {
63  public:
77  CellHeap(size_t dbls_per_cell, size_t cells_per_superblock)
78  : m_cellsize(dbls_per_cell*sizeof(double)),
79  m_cells_per_superblock(cells_per_superblock),
80  m_superblocksize(m_cellsize*cells_per_superblock),
81  m_free_cells(0),
82  m_cells_allocated(0)
83  {
84 #if VALGRIND_LEVEL >= 2
85  VALGRIND_CREATE_MEMPOOL(this, 0, 0);
86 #endif
87  }
88 
97  ~CellHeap();
98 
106  void* allocate() throw (std::bad_alloc)
107  {
108  if (!m_free_cells) seekMemory();
109  // check();
110  Cell* c = m_free_cells;
111  m_free_cells = meld(c->m_l, c->m_r);
112  ++m_cells_allocated;
113 #if VALGRIND_LEVEL >= 2
114  VALGRIND_MEMPOOL_ALLOC(this, c, cellSize());
115 #endif
116  // check();
117  return c;
118  }
119 
124  size_t cellSize() const {return m_cellsize;}
125 
130  unsigned int cellsAllocated() const {return m_cells_allocated;}
131 
140  bool check() const;
141 
148  void deallocate(void* p);
149  /*
150  {
151  if (!p) return;
152 #ifdef DEBUG_RELEASE_MEM
153  checkAllocatedCell(p);
154 #endif
155 #if VALGRIND_LEVEL >= 2
156  VALGRIND_MEMPOOL_FREE(this, p);
157  VALGRIND_MAKE_MEM_UNDEFINED(p, sizeof(Cell));
158 #endif
159  // check();
160  Cell* c = new (p) Cell;
161  m_free_cells = meld(c, m_free_cells);
162  --m_cells_allocated;
163  // check();
164  }
165  */
166 
176  void* easyAllocate() throw ()
177  {
178  if (!m_free_cells) return 0;
179  // check();
180  Cell* c = m_free_cells;
181  m_free_cells = meld(c->m_l, c->m_r);
182  ++m_cells_allocated;
183 #if VALGRIND_LEVEL >= 2
184  VALGRIND_MEMPOOL_ALLOC(this, c, cellSize());
185 #endif
186  // check();
187  return c;
188  }
189 
194  size_t superblockSize() const {return m_superblocksize;}
195  private:
196  struct Cell {
197  Cell* m_l;
198  Cell* m_r;
199 
200  Cell(Cell* next = 0) : m_l(next), m_r(0) {}
201  };
202 
203  const size_t m_cellsize;
204  const size_t m_cells_per_superblock;
205  const size_t m_superblocksize;
206  std::vector<void*> m_superblocks;
207  Cell* m_free_cells;
208  unsigned int m_cells_allocated;
209 
210  // Checks that p is either null or points to a cell belonging
211  // to this heap; aborts if not.
212  void checkCell(const void* p) const;
213 
214  // Calls checkCell, and further checks that the cell is not on
215  // the free list:
216  void checkAllocatedCell(const void* p) const;
217 
218  // Return number of cells in the heap at root, in the process
219  // checking that cells are organised in increasing address
220  // order, and that no cell has a right child but no left child.
221  static unsigned int countFreeCells(const Cell* root);
222 
223  // Return true iff c belongs to the heap at root:
224  static bool isFreeCell(const Cell* root, const Cell* c);
225 
226  // Combine the heaps pointed to by a and b into a single heap.
227  // a and b must pointers to disjoint skew heaps. b may be a
228  // null pointer, and a may be a null pointer provided b is too.
229  static Cell* meld(Cell* a, Cell* b)
230  {
231  if (!b) return a;
232  if (a > b) std::swap(a, b);
233  if (!a->m_l)
234  a->m_l = b;
235  else meld_aux(a, b);
236  return a;
237  }
238 
239  // Auxiliary function for meld:
240  static void meld_aux(Cell* host, Cell* guest);
241 
242  void seekMemory() throw (std::bad_alloc);
243  };
244 }
245 
246 #endif /* CELLHEAP_HPP */