char storage[600];
- SkArenaAlloc allocator{storage, sizeof(storage), 512};
+ SkFixedAlloc fixedAlloc{storage, sizeof(storage)};
+ SkFallbackAlloc allocator{&fixedAlloc};
SkLinearBitmapPipeline pipeline{
fInvert, filterQuality, fXTile, fYTile, SK_ColorBLACK, srcPixmap, &allocator};
auto procN = SkXfermode::GetD32Proc(SkBlendMode::kSrcOver, flags);
char storage[512];
- SkArenaAlloc allocator{storage, sizeof(storage)};
+ SkFixedAlloc fixedAlloc{storage, sizeof(storage)};
+ SkFallbackAlloc allocator{&fixedAlloc};
SkLinearBitmapPipeline pipeline{
inv, filterQuality,
SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
private:
char fStorage[512 + 96];
- SkArenaAlloc fAllocator {fStorage, sizeof(fStorage)};
+ SkFixedAlloc fFixedAlloc {fStorage, sizeof(fStorage)};
+ SkFallbackAlloc fAllocator {&fFixedAlloc};
SkLinearBitmapPipeline* fShaderPipeline;
SkLinearBitmapPipeline* fBlitterPipeline;
SkXfermode::D32Proc fSrcModeProc;
#include "SkFixedAlloc.h"
-#include <algorithm>
-
SkFixedAlloc::SkFixedAlloc(void* ptr, size_t len)
: fStorage((char*)ptr), fCursor(fStorage), fEnd(fStorage + len) {}
}
fFixedAlloc->reset();
}
-
-struct Skipper {
- char* operator()(char* objEnd, ptrdiff_t size) { return objEnd + size; }
-};
-
-struct NextBlock {
- char* operator()(char* objEnd, ptrdiff_t size) { delete [] objEnd; return objEnd + size; }
-};
-
-SkArenaAlloc::SkArenaAlloc(char* block, size_t size, size_t extraSize)
- : fDtorCursor{block}
- , fCursor {block}
- , fEnd {block + size}
- , fExtraSize {extraSize}
-{
- if (size < sizeof(Footer)) {
- fEnd = fCursor = fDtorCursor = nullptr;
- }
-
- if (fCursor != nullptr) {
- this->installFooter(EndChain, 0);
- }
-}
-
-SkArenaAlloc::~SkArenaAlloc() {
- this->reset();
-}
-
-void SkArenaAlloc::reset() {
- char* releaser = fDtorCursor;
- while (releaser != nullptr) {
- releaser = this->callFooterAction(releaser);
- }
-}
-
-void SkArenaAlloc::installFooter(FooterAction* releaser, ptrdiff_t padding) {
- ptrdiff_t releaserDiff = (char *)releaser - (char *)EndChain;
- ptrdiff_t footerData = SkLeftShift((int64_t)releaserDiff, 5) | padding;
- if (padding >= 32 || !SkTFitsIn<int32_t>(footerData)) {
- // Footer data will not fit.
- SkFAIL("Constraints are busted.");
- }
-
- Footer footer = (Footer)(footerData);
- memmove(fCursor, &footer, sizeof(Footer));
- fCursor += sizeof(Footer);
- fDtorCursor = fCursor;
-}
-
-void SkArenaAlloc::ensureSpace(size_t size, size_t alignment) {
- constexpr size_t headerSize = sizeof(Footer) + sizeof(ptrdiff_t);
- // The chrome c++ library we use does not define std::max_align_t.
- // This must be conservative to add the right amount of extra memory to handle the alignment
- // padding.
- constexpr size_t alignof_max_align_t = 8;
- auto objSizeAndOverhead = size + headerSize + sizeof(Footer);
- if (alignment > alignof_max_align_t) {
- objSizeAndOverhead += alignment - 1;
- }
-
- auto allocationSize = std::max(objSizeAndOverhead, fExtraSize);
-
- // Round up to a nice size. If > 32K align to 4K boundary else up to max_align_t. The > 32K
- // heuristic is from the JEMalloc behavior.
- {
- size_t mask = allocationSize > (1 << 15) ? (1 << 12) - 1 : 32 - 1;
- allocationSize = (allocationSize + mask) & ~mask;
- }
-
- char* newBlock = new char[allocationSize];
-
- auto previousDtor = fDtorCursor;
- fCursor = newBlock;
- fDtorCursor = newBlock;
- fEnd = fCursor + allocationSize;
- this->installIntFooter<NextBlock>(previousDtor - fCursor, 0);
-}
-
-char* SkArenaAlloc::allocObject(size_t size, size_t alignment) {
- size_t mask = alignment - 1;
- char* objStart = (char*)((uintptr_t)(fCursor + mask) & ~mask);
- if (objStart + size > fEnd) {
- this->ensureSpace(size, alignment);
- objStart = (char*)((uintptr_t)(fCursor + mask) & ~mask);
- }
- return objStart;
-}
-
-// * sizeAndFooter - the memory for the footer in addition to the size for the object.
-// * alignment - alignment needed by the object.
-char* SkArenaAlloc::allocObjectWithFooter(size_t sizeIncludingFooter, size_t alignment) {
- size_t mask = alignment - 1;
-
- restart:
- size_t skipOverhead = 0;
- bool needsSkipFooter = fCursor != fDtorCursor;
- if (needsSkipFooter) {
- size_t skipSize = SkTFitsIn<int32_t>(fDtorCursor - fCursor)
- ? sizeof(int32_t)
- : sizeof(ptrdiff_t);
- skipOverhead = sizeof(Footer) + skipSize;
- }
- char* objStart = (char*)((uintptr_t)(fCursor + skipOverhead + mask) & ~mask);
- size_t totalSize = sizeIncludingFooter + skipOverhead;
-
- if (objStart + totalSize > fEnd) {
- this->ensureSpace(totalSize, alignment);
- goto restart;
- }
-
- SkASSERT(objStart + totalSize <= fEnd);
-
- // Install a skip footer if needed, thus terminating a run of POD data. The calling code is
- // responsible for installing the footer after the object.
- if (needsSkipFooter) {
- this->installIntFooter<Skipper>(fDtorCursor - fCursor, 0);
- }
-
- return objStart;
-}
-
-char* SkArenaAlloc::callFooterAction(char* end) {
- Footer footer;
- memcpy(&footer, end - sizeof(Footer), sizeof(Footer));
-
- FooterAction* releaser = (FooterAction*)((char*)EndChain + (footer >> 5));
- ptrdiff_t padding = footer & 31;
-
- return releaser(end) - padding;
-}
-
-char* SkArenaAlloc::EndChain(char*) { return nullptr; }
-
#include "SkTFitsIn.h"
#include "SkTypes.h"
-#include <cstddef>
#include <new>
-#include <type_traits>
#include <utility>
#include <vector>
return new (ptr) T(std::forward<Args>(args)...);
}
+ // Destroys the last object allocated and frees any space it used in the SkFixedAlloc.
+ void undo();
// Destroys all objects and frees all space in the SkFixedAlloc.
void reset();
private:
- // Destroys the last object allocated and frees any space it used in the SkFixedAlloc.
- void undo();
-
struct HeapAlloc {
void (*deleter)(char*);
char* ptr;
std::vector<HeapAlloc> fHeapAllocs;
};
-// SkArenaAlloc allocates object and destroys the allocated objects when destroyed. It's designed
-// to minimize the number of underlying block allocations. SkArenaAlloc allocates first out of an
-// (optional) user-provided block of memory, and when that's exhausted it allocates on the heap,
-// starting with an allocation of extraSize bytes. If your data (plus a small overhead) fits in
-// the user-provided block, SkArenaAlloc never uses the heap, and if it fits in extraSize bytes,
-// it'll use the heap only once. If you pass extraSize = 0, it allocates blocks for each call to
-// make<T>.
-//
-// Examples:
-//
-// char block[mostCasesSize];
-// SkArenaAlloc arena(block, almostAllCasesSize);
-//
-// If mostCasesSize is too large for the stack, you can use the following pattern.
-//
-// std::unique_ptr<char[]> block{new char[mostCasesSize]};
-// SkArenaAlloc arena(block.get(), mostCasesSize, almostAllCasesSize);
-//
-// If the program only sometimes allocates memory, use the following.
-//
-// SkArenaAlloc arena(nullptr, 0, almostAllCasesSize);
-//
-// The storage does not necessarily need to be on the stack. Embedding the storage in a class also
-// works.
-//
-// class Foo {
-// char storage[mostCasesSize];
-// SkArenaAlloc arena (storage, almostAllCasesSize);
-// };
-//
-// In addition, the system is optimized to handle POD data including arrays of PODs (where
-// POD is really data with no destructors). For POD data it has zero overhead per item, and a
-// typical block overhead of 8 bytes. For non-POD objects there is a per item overhead of 4 bytes.
-// For arrays of non-POD objects there is a per array overhead of typically 8 bytes. There is an
-// addition overhead when switching from POD data to non-POD data of typically 8 bytes.
-class SkArenaAlloc {
-public:
- SkArenaAlloc(char* block, size_t size, size_t extraSize = 0);
-
- template <size_t kSize>
- SkArenaAlloc(char (&block)[kSize], size_t extraSize = 0)
- : SkArenaAlloc(block, kSize, extraSize)
- {}
-
- ~SkArenaAlloc();
-
- template <typename T, typename... Args>
- T* make(Args&&... args) {
- char* objStart;
- if (std::is_trivially_destructible<T>::value) {
- objStart = this->allocObject(sizeof(T), alignof(T));
- fCursor = objStart + sizeof(T);
- } else {
- objStart = this->allocObjectWithFooter(sizeof(T) + sizeof(Footer), alignof(T));
- size_t padding = objStart - fCursor;
-
- // Advance to end of object to install footer.
- fCursor = objStart + sizeof(T);
- FooterAction* releaser = [](char* objEnd) {
- char* objStart = objEnd - (sizeof(T) + sizeof(Footer));
- ((T*)objStart)->~T();
- return objStart;
- };
- this->installFooter(releaser, padding);
- }
-
- // This must be last to make objects with nested use of this allocator work.
- return new(objStart) T(std::forward<Args>(args)...);
- }
-
- template <typename T>
- T* makeArrayDefault(size_t count) {
- char* objStart = this->commonArrayAlloc<T>(count);
-
- // If T is primitive then no initialization takes place.
- return new(objStart) T[count];
- }
-
- template <typename T>
- T* makeArray(size_t count) {
- char* objStart = this->commonArrayAlloc<T>(count);
-
- // If T is primitive then the memory is initialized. For example, an array of chars will
- // be zeroed.
- return new(objStart) T[count]();
- }
-
- // Destroy all allocated objects, free any heap allocations.
- void reset();
-
-private:
- using Footer = int32_t;
- using FooterAction = char* (char*);
-
- void installFooter(FooterAction* releaser, ptrdiff_t padding);
-
- // N.B. Action is different than FooterAction. FooterAction expects the end of the Footer,
- // and returns the start of the object. An Action expects the end of the *Object* and returns
- // the start of the object.
- template<typename Action>
- void installIntFooter(ptrdiff_t size, ptrdiff_t padding) {
- if (SkTFitsIn<int32_t>(size)) {
- int32_t smallSize = static_cast<int32_t>(size);
- memmove(fCursor, &smallSize, sizeof(int32_t));
- fCursor += sizeof(int32_t);
- this->installFooter(
- [](char* footerEnd) {
- char* objEnd = footerEnd - (sizeof(Footer) + sizeof(int32_t));
- int32_t data;
- memmove(&data, objEnd, sizeof(int32_t));
- return Action()(objEnd, data);
- },
- padding);
- } else {
- memmove(fCursor, &size, sizeof(ptrdiff_t));
- fCursor += sizeof(ptrdiff_t);
- this->installFooter(
- [](char* footerEnd) {
- char* objEnd = footerEnd - (sizeof(Footer) + sizeof(ptrdiff_t));
- ptrdiff_t data;
- memmove(&data, objEnd, sizeof(ptrdiff_t));
- return Action()(objEnd, data);
- },
- padding);
- }
- }
-
- void ensureSpace(size_t size, size_t alignment);
-
- char* allocObject(size_t size, size_t alignment);
-
- char* allocObjectWithFooter(size_t sizeIncludingFooter, size_t alignment);
-
- template <typename T>
- char* commonArrayAlloc(size_t count) {
- char* objStart;
- size_t arraySize = count * sizeof(T);
-
- SkASSERT(arraySize > 0);
-
- if (std::is_trivially_destructible<T>::value) {
- objStart = this->allocObject(arraySize, alignof(T));
- fCursor = objStart + arraySize;
- } else {
- size_t countSize = SkTFitsIn<int32_t>(count) ? sizeof(int32_t) : sizeof(ptrdiff_t);
- size_t totalSize = arraySize + sizeof(Footer) + countSize;
- objStart = this->allocObjectWithFooter(totalSize, alignof(T));
- size_t padding = objStart - fCursor;
-
- // Advance to end of array to install footer.
- fCursor = objStart + arraySize;
- this->installIntFooter<ArrayDestructor<T>> (count, padding);
- }
-
- return objStart;
- }
-
- char* callFooterAction(char* end);
-
- static char* EndChain(char*);
-
- template<typename T>
- struct ArrayDestructor {
- char* operator()(char* objEnd, ptrdiff_t count) {
- char* objStart = objEnd - count * sizeof(T);
- T* array = (T*) objStart;
- for (int i = 0; i < count; i++) {
- array[i].~T();
- }
- return objStart;
- }
- };
-
- char* fDtorCursor;
- char* fCursor;
- char* fEnd;
- size_t fExtraSize;
-};
-
#endif//SkFixedAlloc_DEFINED
SkShader::TileMode xTile, SkShader::TileMode yTile,
SkColor paintColor,
const SkPixmap& srcPixmap,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
SkISize dimensions = srcPixmap.info().dimensions();
const SkImageInfo& srcImageInfo = srcPixmap.info();
const SkPixmap& srcPixmap,
SkBlendMode mode,
const SkImageInfo& dstInfo,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver);
SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType()
float finalAlpha,
SkBlendMode blendMode,
const SkImageInfo& dstInfo,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
if (blendMode == SkBlendMode::kSrcOver && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
blendMode = SkBlendMode::kSrc;
SkLinearBitmapPipeline::chooseMatrix(
PointProcessorInterface* next,
const SkMatrix& inverse,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
if (inverse.hasPerspective()) {
auto matrixStage = allocator->make<PerspectiveMatrix<>>(
SkVector{inverse.getPerspX(), inverse.getPerspY()},
inverse.get(SkMatrix::kMPersp2));
fMatrixStageCloner =
- [matrixStage](PointProcessorInterface* cloneNext, SkArenaAlloc* memory) {
+ [matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<PerspectiveMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
SkVector{inverse.getScaleX(), inverse.getScaleY()},
SkVector{inverse.getSkewX(), inverse.getSkewY()});
fMatrixStageCloner =
- [matrixStage](PointProcessorInterface* cloneNext, SkArenaAlloc* memory) {
+ [matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<AffineMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
SkVector{inverse.getScaleX(), inverse.getScaleY()});
fMatrixStageCloner =
- [matrixStage](PointProcessorInterface* cloneNext, SkArenaAlloc* memory) {
+ [matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<ScaleMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
fMatrixStageCloner =
- [matrixStage](PointProcessorInterface* cloneNext, SkArenaAlloc* memory) {
+ [matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<TranslateMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
} else {
- fMatrixStageCloner = [](PointProcessorInterface* cloneNext, SkArenaAlloc* memory) {
+ fMatrixStageCloner = [](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return cloneNext;
};
return next;
SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::createTiler(
SampleProcessorInterface* next,
SkISize dimensions,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
auto tilerStage = allocator->make<Tiler>(next, dimensions);
fTileStageCloner =
[tilerStage](SampleProcessorInterface* cloneNext,
- SkArenaAlloc* memory) -> PointProcessorInterface* {
+ SkFallbackAlloc* memory) -> PointProcessorInterface* {
return memory->make<Tiler>(cloneNext, tilerStage);
};
return tilerStage;
SampleProcessorInterface* next,
SkShader::TileMode yMode,
SkISize dimensions,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
switch (yMode) {
case SkShader::kClamp_TileMode: {
SkShader::TileMode yMode,
SkFilterQuality filterQuality,
SkScalar dx,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
switch (xMode) {
case SkShader::kClamp_TileMode:
SkLinearBitmapPipeline::PixelAccessorInterface*
SkLinearBitmapPipeline::chooseSpecificAccessor(
const SkPixmap& srcPixmap,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
if (srcPixmap.info().gammaCloseToSRGB()) {
using Accessor = PixelAccessor<colorType, kSRGB_SkGammaType>;
SkLinearBitmapPipeline::PixelAccessorInterface* SkLinearBitmapPipeline::choosePixelAccessor(
const SkPixmap& srcPixmap,
const SkColor A8TintColor,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
const SkImageInfo& imageInfo = srcPixmap.info();
SkShader::TileMode xTile, SkShader::TileMode yTile,
const SkPixmap& srcPixmap,
const SkColor A8TintColor,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
const SkImageInfo& imageInfo = srcPixmap.info();
SkISize dimensions = imageInfo.dimensions();
Blender* SkLinearBitmapPipeline::chooseBlenderForShading(
SkAlphaType alphaType,
float postAlpha,
- SkArenaAlloc* allocator)
+ SkFallbackAlloc* allocator)
{
if (alphaType == kUnpremul_SkAlphaType) {
return allocator->make<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
SkShader::TileMode xTile, SkShader::TileMode yTile,
SkColor paintColor,
const SkPixmap& srcPixmap,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
SkLinearBitmapPipeline(
const SkLinearBitmapPipeline& pipeline,
const SkPixmap& srcPixmap,
SkBlendMode,
const SkImageInfo& dstInfo,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
static SkLinearBitmapPipeline* ClonePipelineForBlitting(
const SkLinearBitmapPipeline& pipeline,
float finalAlpha,
SkBlendMode,
const SkImageInfo& dstInfo,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
~SkLinearBitmapPipeline();
class PixelAccessorInterface;
using MatrixCloner =
- std::function<PointProcessorInterface* (PointProcessorInterface*, SkArenaAlloc*)>;
+ std::function<PointProcessorInterface* (PointProcessorInterface*, SkFallbackAlloc*)>;
using TilerCloner =
- std::function<PointProcessorInterface* (SampleProcessorInterface*, SkArenaAlloc*)>;
+ std::function<PointProcessorInterface* (SampleProcessorInterface*, SkFallbackAlloc*)>;
PointProcessorInterface* chooseMatrix(
PointProcessorInterface* next,
const SkMatrix& inverse,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
template <typename Tiler>
PointProcessorInterface* createTiler(SampleProcessorInterface* next, SkISize dimensions,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
template <typename XStrategy>
PointProcessorInterface* chooseTilerYMode(
SampleProcessorInterface* next, SkShader::TileMode yMode, SkISize dimensions,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
PointProcessorInterface* chooseTiler(
SampleProcessorInterface* next,
SkShader::TileMode xMode, SkShader::TileMode yMode,
SkFilterQuality filterQuality,
SkScalar dx,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
template <SkColorType colorType>
PixelAccessorInterface* chooseSpecificAccessor(const SkPixmap& srcPixmap,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
PixelAccessorInterface* choosePixelAccessor(
const SkPixmap& srcPixmap,
const SkColor A8TintColor,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
SampleProcessorInterface* chooseSampler(
BlendProcessorInterface* next,
SkShader::TileMode xTile, SkShader::TileMode yTile,
const SkPixmap& srcPixmap,
const SkColor A8TintColor,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
BlendProcessorInterface* chooseBlenderForShading(
SkAlphaType alphaType,
float postAlpha,
- SkArenaAlloc* allocator);
+ SkFallbackAlloc* allocator);
PointProcessorInterface* fFirstStage;
MatrixCloner fMatrixStageCloner;
static int created, destroyed;
struct Foo {
- Foo() : x(-2), y(-3.0f) { created++; }
- Foo(int X, float Y) : x(X), y(Y) { created++; }
+ Foo(int X, float Y) : x(X), y(Y) { created++; }
~Foo() { destroyed++; }
int x;
REPORTER_ASSERT(r, !in_buf(big));
REPORTER_ASSERT(r, !in_buf(smallB));
}
-
-struct WithDtor {
- ~WithDtor() { }
-};
-
-DEF_TEST(ArenaAlloc, r) {
- {
- created = 0;
- destroyed = 0;
-
- SkArenaAlloc arena{nullptr, 0};
- REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
- Foo* foo = arena.make<Foo>(3, 4.0f);
- REPORTER_ASSERT(r, foo->x == 3);
- REPORTER_ASSERT(r, foo->y == 4.0f);
- REPORTER_ASSERT(r, created == 1);
- REPORTER_ASSERT(r, destroyed == 0);
- arena.makeArrayDefault<int>(10);
- int* zeroed = arena.makeArray<int>(10);
- for (int i = 0; i < 10; i++) {
- REPORTER_ASSERT(r, zeroed[i] == 0);
- }
- Foo* fooArray = arena.makeArrayDefault<Foo>(10);
- REPORTER_ASSERT(r, fooArray[3].x == -2);
- REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
- REPORTER_ASSERT(r, created == 11);
- REPORTER_ASSERT(r, destroyed == 0);
- arena.make<typename std::aligned_storage<10,8>::type>();
- }
- REPORTER_ASSERT(r, created == 11);
- REPORTER_ASSERT(r, destroyed == 11);
-
- {
- created = 0;
- destroyed = 0;
- char block[1024];
- SkArenaAlloc arena{block};
-
- REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
- Foo* foo = arena.make<Foo>(3, 4.0f);
- REPORTER_ASSERT(r, foo->x == 3);
- REPORTER_ASSERT(r, foo->y == 4.0f);
- REPORTER_ASSERT(r, created == 1);
- REPORTER_ASSERT(r, destroyed == 0);
- arena.makeArrayDefault<int>(10);
- int* zeroed = arena.makeArray<int>(10);
- for (int i = 0; i < 10; i++) {
- REPORTER_ASSERT(r, zeroed[i] == 0);
- }
- Foo* fooArray = arena.makeArrayDefault<Foo>(10);
- REPORTER_ASSERT(r, fooArray[3].x == -2);
- REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
- REPORTER_ASSERT(r, created == 11);
- REPORTER_ASSERT(r, destroyed == 0);
- arena.make<typename std::aligned_storage<10,8>::type>();
- }
- REPORTER_ASSERT(r, created == 11);
- REPORTER_ASSERT(r, destroyed == 11);
-
- {
- created = 0;
- destroyed = 0;
- std::unique_ptr<char[]> block{new char[1024]};
- SkArenaAlloc arena{block.get(), 1024};
-
- REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
- Foo* foo = arena.make<Foo>(3, 4.0f);
- REPORTER_ASSERT(r, foo->x == 3);
- REPORTER_ASSERT(r, foo->y == 4.0f);
- REPORTER_ASSERT(r, created == 1);
- REPORTER_ASSERT(r, destroyed == 0);
- arena.makeArrayDefault<int>(10);
- int* zeroed = arena.makeArray<int>(10);
- for (int i = 0; i < 10; i++) {
- REPORTER_ASSERT(r, zeroed[i] == 0);
- }
- Foo* fooArray = arena.makeArrayDefault<Foo>(10);
- REPORTER_ASSERT(r, fooArray[3].x == -2);
- REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
- REPORTER_ASSERT(r, created == 11);
- REPORTER_ASSERT(r, destroyed == 0);
- arena.make<typename std::aligned_storage<10,8>::type>();
- }
- REPORTER_ASSERT(r, created == 11);
- REPORTER_ASSERT(r, destroyed == 11);
-
-}