зеркало из https://github.com/mozilla/moz-skia.git
234 строки
5.8 KiB
C++
Executable File
234 строки
5.8 KiB
C++
Executable File
|
|
/*
|
|
* Copyright 2010 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
|
|
|
|
#ifndef GrAllocator_DEFINED
|
|
#define GrAllocator_DEFINED
|
|
|
|
#include "GrConfig.h"
|
|
#include "GrTArray.h"
|
|
|
|
class GrAllocator {
|
|
public:
|
|
virtual ~GrAllocator() {
|
|
reset();
|
|
}
|
|
|
|
/**
|
|
* Create an allocator
|
|
*
|
|
* @param itemSize the size of each item to allocate
|
|
* @param itemsPerBlock the number of items to allocate at once
|
|
* @param initialBlock optional memory to use for the first block.
|
|
* Must be at least itemSize*itemsPerBlock sized.
|
|
* Caller is responsible for freeing this memory.
|
|
*/
|
|
GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
|
|
fBlocks(fBlockInitialStorage, NUM_INIT_BLOCK_PTRS),
|
|
fItemSize(itemSize),
|
|
fItemsPerBlock(itemsPerBlock),
|
|
fOwnFirstBlock(NULL == initialBlock),
|
|
fCount(0) {
|
|
GrAssert(itemsPerBlock > 0);
|
|
fBlockSize = fItemSize * fItemsPerBlock;
|
|
fBlocks.push_back() = initialBlock;
|
|
GR_DEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
|
|
}
|
|
|
|
/**
|
|
* Adds an item and returns pointer to it.
|
|
*
|
|
* @return pointer to the added item.
|
|
*/
|
|
void* push_back() {
|
|
int indexInBlock = fCount % fItemsPerBlock;
|
|
// we always have at least one block
|
|
if (0 == indexInBlock) {
|
|
if (0 != fCount) {
|
|
fBlocks.push_back() = GrMalloc(fBlockSize);
|
|
} else if (fOwnFirstBlock) {
|
|
fBlocks[0] = GrMalloc(fBlockSize);
|
|
}
|
|
}
|
|
void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
|
|
fItemSize * indexInBlock;
|
|
++fCount;
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* removes all added items
|
|
*/
|
|
void reset() {
|
|
int blockCount = GrMax((unsigned)1,
|
|
GrUIDivRoundUp(fCount, fItemsPerBlock));
|
|
for (int i = 1; i < blockCount; ++i) {
|
|
GrFree(fBlocks[i]);
|
|
}
|
|
if (fOwnFirstBlock) {
|
|
GrFree(fBlocks[0]);
|
|
fBlocks[0] = NULL;
|
|
}
|
|
fBlocks.pop_back_n(blockCount-1);
|
|
fCount = 0;
|
|
}
|
|
|
|
/**
|
|
* count of items
|
|
*/
|
|
int count() const {
|
|
return fCount;
|
|
}
|
|
|
|
/**
|
|
* is the count 0
|
|
*/
|
|
bool empty() const { return fCount == 0; }
|
|
|
|
/**
|
|
* access last item, only call if count() != 0
|
|
*/
|
|
void* back() {
|
|
GrAssert(fCount);
|
|
return (*this)[fCount-1];
|
|
}
|
|
|
|
/**
|
|
* access last item, only call if count() != 0
|
|
*/
|
|
const void* back() const {
|
|
GrAssert(fCount);
|
|
return (*this)[fCount-1];
|
|
}
|
|
|
|
/**
|
|
* access item by index.
|
|
*/
|
|
void* operator[] (int i) {
|
|
GrAssert(i >= 0 && i < fCount);
|
|
return (char*)fBlocks[i / fItemsPerBlock] +
|
|
fItemSize * (i % fItemsPerBlock);
|
|
}
|
|
|
|
/**
|
|
* access item by index.
|
|
*/
|
|
const void* operator[] (int i) const {
|
|
GrAssert(i >= 0 && i < fCount);
|
|
return (const char*)fBlocks[i / fItemsPerBlock] +
|
|
fItemSize * (i % fItemsPerBlock);
|
|
}
|
|
|
|
private:
|
|
static const int NUM_INIT_BLOCK_PTRS = 8;
|
|
|
|
GrTArray<void*> fBlocks;
|
|
size_t fBlockSize;
|
|
char fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)];
|
|
size_t fItemSize;
|
|
int fItemsPerBlock;
|
|
bool fOwnFirstBlock;
|
|
int fCount;
|
|
};
|
|
|
|
template <typename T>
|
|
class GrTAllocator {
|
|
private:
|
|
GrAllocator fAllocator;
|
|
|
|
public:
|
|
virtual ~GrTAllocator() {};
|
|
|
|
/**
|
|
* Create an allocator
|
|
*
|
|
* @param itemsPerBlock the number of items to allocate at once
|
|
* @param initialBlock optional memory to use for the first block.
|
|
* Must be at least size(T)*itemsPerBlock sized.
|
|
* Caller is responsible for freeing this memory.
|
|
*/
|
|
GrTAllocator(int itemsPerBlock, void* initialBlock)
|
|
: fAllocator(sizeof(T), itemsPerBlock, initialBlock) {}
|
|
|
|
/**
|
|
* Create an allocator using a GrAlignedTAlloc as the initial block.
|
|
*
|
|
* @param initialBlock specifies the storage for the initial block
|
|
* and the size of subsequent blocks.
|
|
*/
|
|
template <int N>
|
|
GrTAllocator(GrAlignedSTStorage<N,T>* initialBlock)
|
|
: fAllocator(sizeof(T), N, initialBlock->get()) {}
|
|
|
|
/**
|
|
* Adds an item and returns it.
|
|
*
|
|
* @return the added item.
|
|
*/
|
|
T& push_back() {
|
|
void* item = fAllocator.push_back();
|
|
GrAssert(NULL != item);
|
|
new (item) T;
|
|
return *(T*)item;
|
|
}
|
|
|
|
/**
|
|
* removes all added items
|
|
*/
|
|
void reset() {
|
|
int c = fAllocator.count();
|
|
for (int i = 0; i < c; ++i) {
|
|
((T*)fAllocator[i])->~T();
|
|
}
|
|
fAllocator.reset();
|
|
}
|
|
|
|
/**
|
|
* count of items
|
|
*/
|
|
int count() const {
|
|
return fAllocator.count();
|
|
}
|
|
|
|
/**
|
|
* is the count 0
|
|
*/
|
|
bool empty() const { return fAllocator.empty(); }
|
|
|
|
/**
|
|
* access last item, only call if count() != 0
|
|
*/
|
|
T& back() {
|
|
return *(T*)fAllocator.back();
|
|
}
|
|
|
|
/**
|
|
* access last item, only call if count() != 0
|
|
*/
|
|
const T& back() const {
|
|
return *(const T*)fAllocator.back();
|
|
}
|
|
|
|
/**
|
|
* access item by index.
|
|
*/
|
|
T& operator[] (int i) {
|
|
return *(T*)(fAllocator[i]);
|
|
}
|
|
|
|
/**
|
|
* access item by index.
|
|
*/
|
|
const T& operator[] (int i) const {
|
|
return *(const T*)(fAllocator[i]);
|
|
}
|
|
};
|
|
|
|
#endif
|