blob: 0f450576d9243a4bb2f224c72dd6e7b094524551 [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkFixedAlloc_DEFINED
#define SkFixedAlloc_DEFINED
#include "SkTFitsIn.h"
#include "SkTypes.h"
#include <new>
#include <type_traits>
#include <utility>
#include <vector>
// Before GCC 5, is_trivially_copyable had a pre-standard name.
#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20150801)
namespace std {
template <typename T>
using is_trivially_copyable = has_trivial_copy_constructor<T>;
}
#endif
// SkFixedAlloc allocates POD objects out of a fixed-size buffer.
class SkFixedAlloc {
public:
SkFixedAlloc(void* ptr, size_t len);
~SkFixedAlloc() { this->reset(); }
// Allocates space suitable for a T. If we can't, returns nullptr.
template <typename T>
void* alloc() {
static_assert(std::is_standard_layout <T>::value
&& std::is_trivially_copyable<T>::value, "");
return this->alloc(sizeof(T), alignof(T));
}
template <typename T, typename... Args>
T* make(Args&&... args) {
if (auto ptr = this->alloc<T>()) {
return new (ptr) T(std::forward<Args>(args)...);
}
return nullptr;
}
template <typename T>
T* copy(const T& src) { return this->make<T>(src); }
// Frees the space of the last object allocated.
void undo();
// Frees all space in the buffer.
void reset();
private:
void* alloc(size_t, size_t);
char* fBuffer;
size_t fUsed, fLimit;
};
class SkFallbackAlloc {
public:
explicit SkFallbackAlloc(SkFixedAlloc*);
~SkFallbackAlloc() { this->reset(); }
template <typename T>
void* alloc() {
// Once we go heap we never go back to fixed. This keeps undo() working.
if (fHeapAllocs.empty()) {
if (void* ptr = fFixedAlloc->alloc<T>()) {
return ptr;
}
}
void* ptr = sk_malloc_throw(sizeof(T));
fHeapAllocs.push_back(ptr);
return ptr;
}
template <typename T, typename... Args>
T* make(Args&&... args) { return new (this->alloc<T>()) T(std::forward<Args>(args)...); }
template <typename T>
T* copy(const T& src) { return this->make<T>(src); }
// Frees the last object allocated, including any space it used in the SkFixedAlloc.
void undo();
// Frees all objects and all space in the SkFixedAlloc.
void reset();
private:
SkFixedAlloc* fFixedAlloc;
std::vector<void*> fHeapAllocs;
};
#endif//SkFixedAlloc_DEFINED