CXXR (C++ R) API
CellPool.hpp
Go to the documentation of this file.
1 /*CXXR $Id: CellPool.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 CELLPOOL_HPP
41 #define CELLPOOL_HPP
42 
43 #include <cstddef>
44 #include <new>
45 #include <vector>
46 
47 #include "CXXR/config.hpp"
48 
49 namespace CXXR {
70  class CellPool {
71  public:
78  : m_free_cells(0),
79 #ifdef CELLFIFO
80  m_last_free_cell(0),
81 #endif
82  m_admin(0)
83  {}
84 
93  ~CellPool();
94 
102  void* allocate() throw (std::bad_alloc)
103  {
104  if (!m_free_cells)
105  m_free_cells = seekMemory();
106  Cell* c = m_free_cells;
107  m_free_cells = c->m_next;
108 #ifdef CELLFIFO
109  if (!m_free_cells)
110  m_last_free_cell = 0;
111 #endif
112  return c;
113  }
114 
120  size_t cellSize() const
121  {
122  return m_admin->m_cellsize;
123  }
124 
130  unsigned int cellsAllocated() const
131  {
132  return m_admin->cellsExisting() - cellsFree();
133  }
134 
143  bool check() const;
144 
151  void deallocate(void* p)
152  {
153  if (!p) return;
154 #ifdef DEBUG_RELEASE_MEM
155  checkAllocatedCell(p);
156 #endif
157  Cell* c = static_cast<Cell*>(p);
158 #ifdef CELLFIFO
159  c->m_next = 0;
160  if (!m_free_cells)
161  m_free_cells = m_last_free_cell = c;
162  else {
163  m_last_free_cell->m_next = c;
164  m_last_free_cell = c;
165  }
166 #else
167  c->m_next = m_free_cells;
168  m_free_cells = c;
169 #endif
170  }
171 
178  void defragment();
179 
197  void initialize(size_t dbls_per_cell, size_t cells_per_superblock);
198 
203  size_t superblockSize() const
204  {
205  return m_admin->m_superblocksize;
206  }
207  private:
208  struct Cell {
209  Cell* m_next;
210 
211  Cell(Cell* next = 0) : m_next(next) {}
212  };
213 
214  // We put data fields that are used relatively rarely in a
215  // separate data structure stored on the heap, so that an
216  // array of CellPool objects, as used in MemoryBank, can be as
217  // compact as possible.
218  struct Admin {
219  const size_t m_cellsize;
220  const size_t m_cells_per_superblock;
221  const size_t m_superblocksize;
222  std::vector<void*> m_superblocks;
223 
224  Admin(size_t dbls_per_cell, size_t cells_per_superblock)
225  : m_cellsize(dbls_per_cell*sizeof(double)),
226  m_cells_per_superblock(cells_per_superblock),
227  m_superblocksize(m_cellsize*cells_per_superblock)
228  {}
229 
230  size_t cellsExisting() const
231  {
232  return m_cells_per_superblock*m_superblocks.size();
233  }
234  };
235 
236  Cell* m_free_cells;
237 #ifdef CELLFIFO
238  Cell* m_last_free_cell;
239 #endif
240  Admin* m_admin;
241 
242  // Number of cells on the free list:
243  unsigned int cellsFree() const;
244 
245  // Checks that p is either null or points to a cell belonging
246  // to this pool; aborts if not.
247  void checkCell(const void* p) const;
248 
249  // Calls checkCell, and further checks that the cell is not on
250  // the free list:
251  void checkAllocatedCell(const void* p) const;
252 
253  // Allocates a new superblock and returns a pointer to the
254  // first free cell in it.
255  Cell* seekMemory() throw (std::bad_alloc);
256  };
257 }
258 
259 #endif /* CELLPOOL_HPP */