6a77cc5dde
git-svn-id: http://skia.googlecode.com/svn/trunk@1209 2bbb7eff-a529-9590-31e7-b0007b416f81
241 lines
6.2 KiB
C++
Executable File
241 lines
6.2 KiB
C++
Executable File
/*
|
|
Copyright 2010 Google Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
|
|
#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
|