8#ifndef SkTBlockList_DEFINED
9#define SkTBlockList_DEFINED
24template<
typename T,
typename B>
using ItemFn =
T (*)(
B*,
int);
55template <
typename T,
int StartingItems = 1>
91 return *
new (this->pushItem())
T;
94 return *
new (this->pushItem())
T(t);
97 return *
new (this->pushItem())
T(std::move(t));
100 template <
typename... Args>
102 return *
new (this->pushItem())
T(std::forward<Args>(
args)...);
118 int avail = fAllocator->
currentBlock()->template avail<alignof(T)>() /
sizeof(
T);
120 int reserved = n - avail;
122 fAllocator->template reserve<alignof(T)>(
136 int releaseIndex = Last(block);
137 GetItem(block, releaseIndex).~T();
139 if (releaseIndex == First(block)) {
144 block->
setMetadata(Decrement(block, releaseIndex));
171 for (
const auto*
b :fAllocator->
blocks()) {
172 if (
b->metadata() == 0) {
175 count += (
sizeof(
T) + Last(
b) - First(
b)) /
sizeof(
T);
192 static_assert(StartingItems >= 1);
221 for (
auto*
b : fAllocator->
blocks()) {
222 if (
b->metadata() == 0) {
227 int end = Last(
b) +
sizeof(
T);
228 int index =
start +
i *
sizeof(
T);
230 return GetItem(
b, index);
247 inline static constexpr size_t StartingSize =
248 SkBlockAllocator::Overhead<alignof(T)>() + StartingItems *
sizeof(
T);
251 return *
static_cast<T*
>(block->
ptr(index));
254 return *
static_cast<const T*
>(block->
ptr(index));
257 return b->firstAlignedOffset<
alignof(
T)>();
260 return b->metadata();
263 return index +
sizeof(
T);
266 return index -
sizeof(
T);
271 auto br = fAllocator->template allocate<alignof(T)>(
sizeof(
T));
272 SkASSERT(br.fStart == br.fAlignedOffset ||
273 br.fAlignedOffset == First(fAllocator->
currentBlock()));
274 br.fBlock->setMetadata(br.fAlignedOffset);
276 return br.fBlock->ptr(br.fAlignedOffset);
305template <
typename T,
int SI1>
311 }
else if (other.count() == 1) {
312 this->push_back(other.back());
319 int headItemCount = 0;
323 int headStart = First(headBlock);
324 int headEnd = Last(headBlock) +
sizeof(
T);
325 headItemCount = (headEnd - headStart) /
sizeof(
T);
326 int avail = fAllocator->currentBlock()->template avail<alignof(T)>() /
sizeof(
T);
327 if (headItemCount > avail) {
331 fAllocator->template reserve<alignof(T)>((headItemCount - avail) *
sizeof(
T),
340 auto target =
dst->template allocate<alignof(T)>(n *
sizeof(
T));
342 target.fBlock->setMetadata(
target.fAlignedOffset + (n - 1) *
sizeof(
T));
347 copy(headBlock, headStart, fAllocator.allocator(),
std::min(headItemCount, avail));
349 if (headItemCount > avail) {
351 copy(headBlock, headStart + avail *
sizeof(
T),
352 fAllocator.allocator(), headItemCount - avail);
354 fAllocator->setMetadata(fAllocator->metadata() + headItemCount);
357 for (
int i = headStart;
i < headEnd;
i +=
sizeof(
T)) {
358 T& toMove = GetItem(headBlock,
i);
359 this->push_back(std::move(toMove));
366 other.fAllocator->releaseBlock(headBlock);
370 SkASSERT(other.fAllocator->headBlock()->metadata() == 0 &&
371 fAllocator->metadata() == oldCount + headItemCount);
372 fAllocator->stealHeapBlocks(other.fAllocator.allocator());
373 fAllocator->setMetadata(fAllocator->metadata() +
374 (other.fAllocator->metadata() - headItemCount));
375 other.fAllocator->setMetadata(0);
400 return other.fBlock != fBlock || (
SkToBool(*fBlock) && other.fIndex != fIndex);
405 return Resolve(*fBlock, fIndex);
409 const auto* block = *fBlock;
411 SkASSERT((Forward && Next(block, fIndex) > fIndex) ||
412 (!Forward && Next(block, fIndex) < fIndex));
413 fIndex = Next(block, fIndex);
414 if ((Forward && fIndex > fEndIndex) || (!Forward && fIndex < fEndIndex)) {
423 using BlockItem =
typename BlockIter::Item;
425 Item(BlockItem block) : fBlock(block) {
431 while(*fBlock && (*fBlock)->metadata() == 0) {
435 fIndex = Start(*fBlock);
436 fEndIndex = End(*fBlock);
442 SkASSERT((Forward && fIndex <= fEndIndex) || (!Forward && fIndex >= fEndIndex));
454 BlockIter fBlockIter;
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
SkBlockAllocator::Block Block
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
int(*)(const SkBlockAllocator::Block *, int) NextFn
int(*)(const SkBlockAllocator::Block *) IndexFn
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr bool SkToBool(const T &x)
bool operator!=(const Item &other) const
BlockIndexIterator(BlockIter iter)
bool release(int start, int end)
void setMetadata(int value)
void setMetadata(int value)
void releaseBlock(Block *block)
@ kIgnoreExistingBytes_Flag
@ kIgnoreGrowthPolicy_Flag
const Block * headBlock() const
BlockIter< true, false > blocks()
const Block * currentBlock() const
SkBlockAllocator * allocator()
const T & item(int i) const
SkTBlockList(int itemsPerBlock, SkBlockAllocator::GrowthPolicy policy=SkBlockAllocator::GrowthPolicy::kFixed)
BlockIndexIterator< T &, true, false, &First, &Last, &Increment, &GetItem > Iter
BlockIndexIterator< const T &, false, true, &Last, &First, &Decrement, &GetItem > CRIter
T & emplace_back(Args &&... args)
BlockIndexIterator< const T &, true, true, &First, &Last, &Increment, &GetItem > CIter
SkTBlockList(SkBlockAllocator::GrowthPolicy policy)
void concat(SkTBlockList< T, SI > &&other)
BlockIndexIterator< T &, false, false, &Last, &First, &Decrement, &GetItem > RIter
T & push_back(const T &t)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static float min(float r, float g, float b)
static FunctionPtr Resolve(Thread *thread, Zone *zone, const GrowableArray< const Instance * > &caller_arguments, const Class &receiver_class, const String &name, const Array &descriptor)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network policy