29 #ifndef LSST_AP_UTILS_ARENA_CC
30 #define LSST_AP_UTILS_ARENA_CC
34 namespace lsst {
namespace ap {
namespace utils {
44 _blockCapacity(blockCapacity),
48 if (blockCapacity == 0) {
49 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
50 "Cannot create Arena with 0 capacity");
57 typedef std::vector<unsigned char *>::iterator Iter;
61 "No free elements, but free list head is non-null");
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();
70 }
else if (_nFree < _blocks.size()*_blockCapacity) {
72 "Free count is non zero, but free list head is null");
75 std::sort(_blocks.begin(), _blocks.end());
76 unsigned char *ptr = _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");
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;
88 ptr = *
reinterpret_cast<unsigned char **
>(ptr);
90 assert(_nFree == 0 &&
"Free list does not contain all free elements");
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) {
97 reinterpret_cast<T *
>(block)->~T();
102 assert(_nFree == _blocks.size()*_blockCapacity &&
103 "Number of free elements exceeds arena capacity");
106 for (Iter i = _blocks.begin(), e = _blocks.end(); i != e; ++i) {
115 template <
typename T>
120 unsigned char *
next = _free;
121 _free = *
reinterpret_cast<unsigned char **
>(
next);
128 template <
typename T>
130 unsigned char *
next =
static_cast<unsigned char *
>(ptr);
131 *
reinterpret_cast<unsigned char **
>(
next) = _free;
138 template <
typename T>
146 template <
typename T>
148 return _blockCapacity*_blocks.size();
153 template <
typename T>
155 return capacity()*SIZE;
160 template <
typename T>
162 return _blockCapacity;
166 template <
typename T>
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");
174 std::vector<unsigned char *>::size_type c = 2*_blocks.capacity();
178 if (c < _blocks.capacity() || c > _blocks.max_size()) {
179 c = _blocks.max_size();
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");
188 std::vector<std::vector<bool> >::size_type c = 2*_masks.capacity();
192 if (c < _masks.capacity() || c > _masks.max_size()) {
193 c = _masks.max_size();
197 std::vector<bool> mask(_blockCapacity,
false);
199 unsigned char *block =
static_cast<unsigned char *
>(
200 std::malloc(_blockCapacity*SIZE + ALIGN));
202 throw std::bad_alloc();
206 _masks.push_back(std::vector<bool>());
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;
213 *
reinterpret_cast<unsigned char **
>(item) = 0;
215 _free = _align(block);
216 _nFree += _blockCapacity;
217 _blocks.push_back(block);
220 template <
typename T>
222 return reinterpret_cast<unsigned char *
>(
223 reinterpret_cast<size_t>(ptr + ALIGN) & ~(ALIGN - 1));
228 #endif // LSST_AP_UTILS_ARENA_CC
static unsigned char * _align(unsigned char *p)
size_t getNumBytes() const
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
size_t getBlockCapacity() const
#define LSST_EXCEPT(type,...)
Single threaded arena (pool) memory allocator.
afw::table::Key< double > b
Arena(size_t blockCapacity=262144/sizeof(T))