LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
Arena.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
29 #ifndef LSST_AP_UTILS_ARENA_CC
30 #define LSST_AP_UTILS_ARENA_CC
31 
32 #include "Arena.h"
33 
34 namespace lsst { namespace ap { namespace utils {
35 
40 template <typename T>
41 Arena<T>::Arena(size_t blockCapacity) :
42  _blocks(),
43  _masks(),
44  _blockCapacity(blockCapacity),
45  _nFree(0),
46  _free(0)
47 {
48  if (blockCapacity == 0) {
49  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
50  "Cannot create Arena with 0 capacity");
51  }
52  _grow();
53 }
54 
55 template <typename T>
57  typedef std::vector<unsigned char *>::iterator Iter;
58 
59  if (_nFree == 0) {
60  assert(_free == 0 &&
61  "No free elements, but free list head is non-null");
62  // call destructor for every element of every block
63  for (Iter i = _blocks.begin(), e = _blocks.end(); i != e; ++i) {
64  unsigned char *block = _align(*i);
65  unsigned char *blockEnd = block + _blockCapacity*SIZE;
66  for (; block < blockEnd; block += SIZE) {
67  reinterpret_cast<T *>(block)->~T();
68  }
69  }
70  } else if (_nFree < _blocks.size()*_blockCapacity) {
71  assert(_free != 0 &&
72  "Free count is non zero, but free list head is null");
73  // need to call destructor for each allocated entry -
74  // first compute free bits for every block.
75  std::sort(_blocks.begin(), _blocks.end());
76  unsigned char *ptr = _free;
77  while (ptr != 0) {
78  // figure out which block ptr is from and mark the element free
79  Iter b = std::upper_bound(_blocks.begin(), _blocks.end(), ptr);
80  assert(b != _blocks.begin() &&
81  "Free list contains pointer not belonging to arena");
82  --b;
83  unsigned char *ab = _align(*b);
84  assert((ptr - ab) % SIZE == 0 &&
85  "Free list contains unaligned pointer");
86  _masks[b - _blocks.begin()][(ptr - ab)/SIZE] = true;
87  --_nFree;
88  ptr = *reinterpret_cast<unsigned char **>(ptr);
89  }
90  assert(_nFree == 0 && "Free list does not contain all free elements");
91  // free any element not flagged as free in its occupancy mask
92  for (size_t i = 0; i < _blocks.size(); ++i) {
93  unsigned char *block = _align(_blocks[i]);
94  std::vector<bool> const & free = _masks[i];
95  for (size_t j = 0; j < _blocks.size(); block += SIZE, ++j) {
96  if (!free[j]) {
97  reinterpret_cast<T *>(block)->~T();
98  }
99  }
100  }
101  } else {
102  assert(_nFree == _blocks.size()*_blockCapacity &&
103  "Number of free elements exceeds arena capacity");
104  }
105  // free the memory for each block
106  for (Iter i = _blocks.begin(), e = _blocks.end(); i != e; ++i) {
107  std::free(*i);
108  *i = 0;
109  }
110 }
111 
115 template <typename T>
116 inline void *Arena<T>::_alloc() {
117  if (_free == 0) {
118  _grow();
119  }
120  unsigned char *next = _free;
121  _free = *reinterpret_cast<unsigned char **>(next);
122  --_nFree;
123  return next;
124 }
125 
128 template <typename T>
129 inline void Arena<T>::_dealloc(void *ptr) {
130  unsigned char *next = static_cast<unsigned char *>(ptr);
131  *reinterpret_cast<unsigned char **>(next) = _free;
132  _free = next;
133  ++_nFree;
134 }
135 
138 template <typename T>
139 inline void Arena<T>::destroy(T *ptr) {
140  ptr->~T();
141  _dealloc(ptr);
142 }
143 
146 template <typename T>
147 inline size_t Arena<T>::capacity() const {
148  return _blockCapacity*_blocks.size();
149 }
150 
153 template <typename T>
154 inline size_t Arena<T>::getNumBytes() const {
155  return capacity()*SIZE;
156 }
157 
160 template <typename T>
161 inline size_t Arena<T>::getBlockCapacity() const {
162  return _blockCapacity;
163 }
164 
165 
166 template <typename T>
168  // pre-allocate space in block and block mask list
169  if (_blocks.size() == _blocks.capacity()) {
170  if (_blocks.size() == _blocks.max_size()) {
171  throw std::length_error("cannot expand vector: "
172  "max_size() would be exceeded");
173  }
174  std::vector<unsigned char *>::size_type c = 2*_blocks.capacity();
175  if (c == 0) {
176  ++ c;
177  }
178  if (c < _blocks.capacity() || c > _blocks.max_size()) {
179  c = _blocks.max_size();
180  }
181  _blocks.reserve(c);
182  }
183  if (_masks.size() == _masks.capacity()) {
184  if (_masks.size() == _masks.max_size()) {
185  throw std::length_error("cannot expand vector: "
186  "max_size() would be exceeded");
187  }
188  std::vector<std::vector<bool> >::size_type c = 2*_masks.capacity();
189  if (c == 0) {
190  ++c;
191  }
192  if (c < _masks.capacity() || c > _masks.max_size()) {
193  c = _masks.max_size();
194  }
195  _masks.reserve(c);
196  }
197  std::vector<bool> mask(_blockCapacity, false);
198  // allocate another block
199  unsigned char *block = static_cast<unsigned char *>(
200  std::malloc(_blockCapacity*SIZE + ALIGN));
201  if (block == 0) {
202  throw std::bad_alloc();
203  }
204  // what follows will not throw so long as the std::vector default
205  // constructor does not throw
206  _masks.push_back(std::vector<bool>());
207  std::swap(_masks.back(), mask);
208  // initialize free-list
209  unsigned char *item = _align(block);
210  for (size_t i = 0; i < _blockCapacity - 1; ++i, item += SIZE) {
211  *reinterpret_cast<unsigned char **>(item) = item + SIZE;
212  }
213  *reinterpret_cast<unsigned char **>(item) = 0;
214  // set _free to head of free-list and store new block pointer
215  _free = _align(block);
216  _nFree += _blockCapacity;
217  _blocks.push_back(block);
218 }
219 
220 template <typename T>
221 inline unsigned char * Arena<T>::_align(unsigned char *ptr) {
222  return reinterpret_cast<unsigned char *>(
223  reinterpret_cast<size_t>(ptr + ALIGN) & ~(ALIGN - 1));
224 }
225 
226 }}} // namespace lsst::ap::utils
227 
228 #endif // LSST_AP_UTILS_ARENA_CC
229 
Edge * next
Definition: ImageUtils.cc:91
static unsigned char * _align(unsigned char *p)
Definition: Arena.cc:221
size_t getNumBytes() const
Definition: Arena.cc:154
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
Definition: Image.cc:291
size_t getBlockCapacity() const
Definition: Arena.cc:161
void _dealloc(void *ptr)
Definition: Arena.cc:129
size_t capacity() const
Definition: Arena.cc:147
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
Single threaded arena (pool) memory allocator.
afw::table::Key< double > b
void destroy(T *ptr)
Definition: Arena.cc:139
Arena(size_t blockCapacity=262144/sizeof(T))
Definition: Arena.cc:41