2012-06-08 18:18:20 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Copyright 2013 Pixar
|
2012-06-08 18:18:20 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
|
|
// with the following modification; you may not use this file except in
|
|
|
|
// compliance with the Apache License and the following modification to it:
|
|
|
|
// Section 6. Trademarks. is deleted and replaced with:
|
2012-06-08 18:18:20 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 6. Trademarks. This License does not grant permission to use the trade
|
|
|
|
// names, trademarks, service marks, or product names of the Licensor
|
|
|
|
// and its affiliates, except as required to comply with Section 4(c) of
|
|
|
|
// the License and to reproduce the content of the NOTICE file.
|
2012-06-08 18:18:20 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// You may obtain a copy of the Apache License at
|
2012-06-08 18:18:20 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2013-07-18 21:19:50 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the Apache License with the above modification is
|
|
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
// KIND, either express or implied. See the Apache License for the specific
|
|
|
|
// language governing permissions and limitations under the Apache License.
|
2012-06-08 18:18:20 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
|
2012-06-08 18:18:20 +00:00
|
|
|
#ifndef HBRALLOCATOR_H
|
|
|
|
#define HBRALLOCATOR_H
|
|
|
|
|
2012-06-15 01:47:57 +00:00
|
|
|
#include "../version.h"
|
|
|
|
|
|
|
|
namespace OpenSubdiv {
|
|
|
|
namespace OPENSUBDIV_VERSION {
|
|
|
|
|
2013-01-10 21:33:04 +00:00
|
|
|
typedef void (*HbrMemStatFunction)(size_t bytes);
|
2012-06-08 18:18:20 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* HbrAllocator - derived from UtBlockAllocator.h, but embedded in
|
|
|
|
* libhbrep.
|
|
|
|
*/
|
|
|
|
template <typename T> class HbrAllocator {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/// Constructor
|
2013-01-10 21:33:04 +00:00
|
|
|
HbrAllocator(size_t *memorystat, int blocksize, void (*increment)(size_t bytes), void (*decrement)(size_t bytes), size_t elemsize = sizeof(T));
|
2012-06-08 18:18:20 +00:00
|
|
|
|
|
|
|
/// Destructor
|
|
|
|
~HbrAllocator();
|
|
|
|
|
|
|
|
/// Create an allocated object
|
|
|
|
T * Allocate();
|
|
|
|
|
|
|
|
/// Return an allocated object to the block allocator
|
|
|
|
void Deallocate(T *);
|
|
|
|
|
|
|
|
/// Clear the allocator, deleting all allocated objects.
|
|
|
|
void Clear();
|
|
|
|
|
2013-01-10 21:33:04 +00:00
|
|
|
void SetMemStatsIncrement(void (*increment)(size_t bytes)) { m_increment = increment; }
|
2012-06-08 18:18:20 +00:00
|
|
|
|
2013-01-10 21:33:04 +00:00
|
|
|
void SetMemStatsDecrement(void (*decrement)(size_t bytes)) { m_decrement = decrement; }
|
2012-08-04 02:51:27 +00:00
|
|
|
|
2012-06-08 18:18:20 +00:00
|
|
|
private:
|
|
|
|
size_t *m_memorystat;
|
|
|
|
const int m_blocksize;
|
|
|
|
int m_elemsize;
|
|
|
|
T** m_blocks;
|
|
|
|
|
|
|
|
// Number of actually allocated blocks
|
|
|
|
int m_nblocks;
|
|
|
|
|
|
|
|
// Size of the m_blocks array (which is NOT the number of actually
|
|
|
|
// allocated blocks)
|
|
|
|
int m_blockCapacity;
|
|
|
|
|
|
|
|
int m_freecount;
|
|
|
|
T * m_freelist;
|
|
|
|
|
|
|
|
// Memory statistics tracking routines
|
|
|
|
HbrMemStatFunction m_increment;
|
|
|
|
HbrMemStatFunction m_decrement;
|
|
|
|
};
|
2012-08-04 02:51:27 +00:00
|
|
|
|
2012-06-08 18:18:20 +00:00
|
|
|
template <typename T>
|
2013-01-10 21:33:04 +00:00
|
|
|
HbrAllocator<T>::HbrAllocator(size_t *memorystat, int blocksize, void (*increment)(size_t bytes), void (*decrement)(size_t bytes), size_t elemsize)
|
2012-08-04 02:51:27 +00:00
|
|
|
: m_memorystat(memorystat), m_blocksize(blocksize), m_elemsize((int)elemsize), m_blocks(0), m_nblocks(0), m_blockCapacity(0), m_freecount(0), m_increment(increment), m_decrement(decrement) {
|
2012-06-08 18:18:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
HbrAllocator<T>::~HbrAllocator() {
|
|
|
|
Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void HbrAllocator<T>::Clear() {
|
|
|
|
for (int i = 0; i < m_nblocks; ++i) {
|
2012-08-04 02:51:27 +00:00
|
|
|
// Run the destructors (placement)
|
|
|
|
T* blockptr = m_blocks[i];
|
|
|
|
T* startblock = blockptr;
|
|
|
|
for (int j = 0; j < m_blocksize; ++j) {
|
|
|
|
blockptr->~T();
|
|
|
|
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
|
|
|
}
|
|
|
|
free(startblock);
|
|
|
|
if (m_decrement) m_decrement(m_blocksize * m_elemsize);
|
2012-06-08 18:18:20 +00:00
|
|
|
*m_memorystat -= m_blocksize * m_elemsize;
|
|
|
|
}
|
|
|
|
free(m_blocks);
|
|
|
|
m_blocks = 0;
|
|
|
|
m_nblocks = 0;
|
|
|
|
m_blockCapacity = 0;
|
|
|
|
m_freecount = 0;
|
|
|
|
m_freelist = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2012-08-04 02:51:27 +00:00
|
|
|
T*
|
2012-06-08 18:18:20 +00:00
|
|
|
HbrAllocator<T>::Allocate() {
|
|
|
|
if (!m_freecount) {
|
|
|
|
|
2012-08-04 02:51:27 +00:00
|
|
|
// Allocate a new block
|
|
|
|
T* block = (T*) malloc(m_blocksize * m_elemsize);
|
|
|
|
T* blockptr = block;
|
|
|
|
// Run the constructors on each element using placement new
|
|
|
|
for (int i = 0; i < m_blocksize; ++i) {
|
|
|
|
new (blockptr) T();
|
|
|
|
blockptr = (T*) ((char*) blockptr + m_elemsize);
|
|
|
|
}
|
|
|
|
if (m_increment) m_increment(m_blocksize * m_elemsize);
|
2012-06-08 18:18:20 +00:00
|
|
|
*m_memorystat += m_blocksize * m_elemsize;
|
2012-08-04 02:51:27 +00:00
|
|
|
|
|
|
|
// Put the block's entries on the free list
|
|
|
|
blockptr = block;
|
|
|
|
for (int i = 0; i < m_blocksize - 1; ++i) {
|
|
|
|
T* next = (T*) ((char*) blockptr + m_elemsize);
|
|
|
|
blockptr->GetNext() = next;
|
|
|
|
blockptr = next;
|
|
|
|
}
|
|
|
|
blockptr->GetNext() = 0;
|
|
|
|
m_freelist = block;
|
|
|
|
|
|
|
|
// Keep track of the newly allocated block
|
|
|
|
if (m_nblocks + 1 >= m_blockCapacity) {
|
|
|
|
m_blockCapacity = m_blockCapacity * 2;
|
|
|
|
if (m_blockCapacity < 1) m_blockCapacity = 1;
|
|
|
|
m_blocks = (T**) realloc(m_blocks, m_blockCapacity * sizeof(T*));
|
|
|
|
}
|
|
|
|
m_blocks[m_nblocks] = block;
|
|
|
|
m_nblocks++;
|
|
|
|
m_freecount += m_blocksize;
|
2012-06-08 18:18:20 +00:00
|
|
|
}
|
|
|
|
T* obj = m_freelist;
|
|
|
|
m_freelist = obj->GetNext();
|
|
|
|
obj->GetNext() = 0;
|
|
|
|
m_freecount--;
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void
|
|
|
|
HbrAllocator<T>::Deallocate(T * obj) {
|
|
|
|
assert(!obj->GetNext());
|
|
|
|
obj->GetNext() = m_freelist;
|
|
|
|
m_freelist = obj;
|
|
|
|
m_freecount++;
|
|
|
|
}
|
|
|
|
|
2012-06-15 01:47:57 +00:00
|
|
|
} // end namespace OPENSUBDIV_VERSION
|
|
|
|
using namespace OPENSUBDIV_VERSION;
|
|
|
|
|
|
|
|
} // end namespace OpenSubdiv
|
|
|
|
|
2012-06-08 18:18:20 +00:00
|
|
|
#endif /* HBRALLOCATOR_H */
|