2014-09-05 13:13:43 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2014 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
#include "src/core/SkTBlockList.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "tests/Test.h"
|
2014-09-05 13:13:43 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct C {
|
|
|
|
C() : fID(-1) { ++gInstCnt; }
|
|
|
|
C(int id) : fID(id) { ++gInstCnt; }
|
2020-07-16 18:20:49 +00:00
|
|
|
C(C&& c) : C(c.fID) {}
|
2020-07-17 12:39:46 +00:00
|
|
|
C(const C& c) : C(c.fID) {}
|
|
|
|
|
2020-03-30 21:53:53 +00:00
|
|
|
C& operator=(C&&) = default;
|
2020-07-17 12:39:46 +00:00
|
|
|
C& operator=(const C&) = default;
|
|
|
|
|
2014-09-05 13:13:43 +00:00
|
|
|
~C() { --gInstCnt; }
|
2020-07-17 12:39:46 +00:00
|
|
|
|
2014-09-05 13:13:43 +00:00
|
|
|
int fID;
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
// Under the hood, SkTBlockList and SkBlockAllocator round up to max_align_t. If 'C' was
|
2020-07-22 20:36:49 +00:00
|
|
|
// just 4 bytes, that often means the internal blocks can squeeze a few extra instances in. This
|
2020-07-20 20:17:14 +00:00
|
|
|
// is fine, but makes predicting a little trickier, so make sure C is a bit bigger.
|
|
|
|
int fPadding[4];
|
|
|
|
|
2014-09-05 13:13:43 +00:00
|
|
|
static int gInstCnt;
|
|
|
|
};
|
|
|
|
int C::gInstCnt = 0;
|
2020-07-21 17:04:42 +00:00
|
|
|
|
|
|
|
struct D {
|
|
|
|
int fID;
|
|
|
|
};
|
|
|
|
|
2020-08-06 18:11:56 +00:00
|
|
|
} // namespace
|
2014-09-05 13:13:43 +00:00
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
class TBlockListTestAccess {
|
|
|
|
public:
|
|
|
|
template<int N>
|
|
|
|
static size_t ScratchBlockSize(SkTBlockList<C, N>& list) {
|
|
|
|
return (size_t) list.fAllocator->scratchBlockSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int N>
|
|
|
|
static size_t TotalSize(SkTBlockList<C, N>& list) {
|
|
|
|
return list.fAllocator->totalSize();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-05 13:13:43 +00:00
|
|
|
// Checks that the allocator has the correct count, etc and that the element IDs are correct.
|
|
|
|
// Then pops popCnt items and checks again.
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
template<int N>
|
2021-08-24 15:49:55 +00:00
|
|
|
static void check_allocator_helper(SkTBlockList<C, N>* allocator, int cnt, int popCnt,
|
2014-09-05 13:13:43 +00:00
|
|
|
skiatest::Reporter* reporter) {
|
|
|
|
REPORTER_ASSERT(reporter, (0 == cnt) == allocator->empty());
|
|
|
|
REPORTER_ASSERT(reporter, cnt == allocator->count());
|
|
|
|
REPORTER_ASSERT(reporter, cnt == C::gInstCnt);
|
|
|
|
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
int i = 0;
|
|
|
|
for (const C& c : allocator->items()) {
|
|
|
|
REPORTER_ASSERT(reporter, i == c.fID);
|
|
|
|
REPORTER_ASSERT(reporter, allocator->item(i).fID == i);
|
|
|
|
++i;
|
2014-09-05 13:13:43 +00:00
|
|
|
}
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
REPORTER_ASSERT(reporter, i == cnt);
|
|
|
|
|
2014-09-05 13:13:43 +00:00
|
|
|
if (cnt > 0) {
|
|
|
|
REPORTER_ASSERT(reporter, cnt-1 == allocator->back().fID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (popCnt > 0) {
|
2021-08-12 14:48:09 +00:00
|
|
|
for (i = 0; i < popCnt; ++i) {
|
2014-09-05 13:13:43 +00:00
|
|
|
allocator->pop_back();
|
|
|
|
}
|
|
|
|
check_allocator_helper(allocator, cnt - popCnt, 0, reporter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-15 16:36:44 +00:00
|
|
|
template<int N>
|
2021-08-24 15:49:55 +00:00
|
|
|
static void check_iterator_helper(SkTBlockList<C, N>* allocator,
|
2020-07-22 20:36:49 +00:00
|
|
|
const std::vector<C*>& expected,
|
2020-07-15 16:36:44 +00:00
|
|
|
skiatest::Reporter* reporter) {
|
2021-08-24 15:49:55 +00:00
|
|
|
const SkTBlockList<C, N>* cAlloc = allocator;
|
2020-07-15 16:36:44 +00:00
|
|
|
REPORTER_ASSERT(reporter, (size_t) allocator->count() == expected.size());
|
|
|
|
// Forward+const
|
|
|
|
int i = 0;
|
|
|
|
for (const C& c : cAlloc->items()) {
|
|
|
|
REPORTER_ASSERT(reporter, (uintptr_t) &c == (uintptr_t) expected[i]);
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, (size_t) i == expected.size());
|
|
|
|
|
|
|
|
// Forward+non-const
|
|
|
|
i = 0;
|
|
|
|
for (C& c : allocator->items()) {
|
|
|
|
REPORTER_ASSERT(reporter, (uintptr_t) &c == (uintptr_t) expected[i]);
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, (size_t) i == expected.size());
|
|
|
|
|
|
|
|
// Reverse+const
|
|
|
|
i = (int) expected.size() - 1;
|
|
|
|
for (const C& c : cAlloc->ritems()) {
|
|
|
|
REPORTER_ASSERT(reporter, (uintptr_t) &c == (uintptr_t) expected[i]);
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, i == -1);
|
|
|
|
|
|
|
|
// Reverse+non-const
|
|
|
|
i = (int) expected.size() - 1;
|
|
|
|
for (C& c : allocator->ritems()) {
|
|
|
|
REPORTER_ASSERT(reporter, (uintptr_t) &c == (uintptr_t) expected[i]);
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, i == -1);
|
|
|
|
|
|
|
|
// Also test random access
|
2021-08-12 14:48:09 +00:00
|
|
|
for (i = 0; i < allocator->count(); ++i) {
|
2020-07-15 16:36:44 +00:00
|
|
|
REPORTER_ASSERT(reporter, (uintptr_t) &allocator->item(i) == (uintptr_t) expected[i]);
|
|
|
|
REPORTER_ASSERT(reporter, (uintptr_t) &cAlloc->item(i) == (uintptr_t) expected[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
// Adds cnt items to the allocator, tests the cnts and iterators, pops popCnt items and checks
|
|
|
|
// again. Finally it resets the allocator and checks again.
|
|
|
|
template<int N>
|
2021-08-24 15:49:55 +00:00
|
|
|
static void check_allocator(SkTBlockList<C, N>* allocator, int cnt, int popCnt,
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
skiatest::Reporter* reporter) {
|
2020-07-17 12:39:46 +00:00
|
|
|
enum ItemInitializer : int {
|
|
|
|
kCopyCtor,
|
|
|
|
kMoveCtor,
|
|
|
|
kCopyAssign,
|
|
|
|
kMoveAssign,
|
|
|
|
kEmplace,
|
|
|
|
};
|
|
|
|
static constexpr int kInitCount = (int) kEmplace + 1;
|
|
|
|
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
SkASSERT(allocator);
|
|
|
|
SkASSERT(allocator->empty());
|
2020-07-15 16:36:44 +00:00
|
|
|
std::vector<C*> items;
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
for (int i = 0; i < cnt; ++i) {
|
2020-07-17 12:39:46 +00:00
|
|
|
switch((ItemInitializer) (i % kInitCount)) {
|
|
|
|
case kCopyCtor:
|
|
|
|
allocator->push_back(C(i));
|
|
|
|
break;
|
|
|
|
case kMoveCtor:
|
|
|
|
allocator->push_back(std::move(C(i)));
|
|
|
|
break;
|
|
|
|
case kCopyAssign:
|
|
|
|
allocator->push_back() = C(i);
|
|
|
|
break;
|
|
|
|
case kMoveAssign:
|
|
|
|
allocator->push_back() = std::move(C(i));
|
|
|
|
break;
|
|
|
|
case kEmplace:
|
|
|
|
allocator->emplace_back(i);
|
|
|
|
break;
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
}
|
2020-07-15 16:36:44 +00:00
|
|
|
items.push_back(&allocator->back());
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
}
|
2020-07-15 16:36:44 +00:00
|
|
|
check_iterator_helper(allocator, items, reporter);
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
check_allocator_helper(allocator, cnt, popCnt, reporter);
|
|
|
|
allocator->reset();
|
2020-07-15 16:36:44 +00:00
|
|
|
check_iterator_helper(allocator, {}, reporter);
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
check_allocator_helper(allocator, 0, 0, reporter);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int N>
|
2021-08-24 15:49:55 +00:00
|
|
|
static void run_allocator_test(SkTBlockList<C, N>* allocator, skiatest::Reporter* reporter) {
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
check_allocator(allocator, 0, 0, reporter);
|
|
|
|
check_allocator(allocator, 1, 1, reporter);
|
|
|
|
check_allocator(allocator, 2, 2, reporter);
|
|
|
|
check_allocator(allocator, 10, 1, reporter);
|
|
|
|
check_allocator(allocator, 10, 5, reporter);
|
|
|
|
check_allocator(allocator, 10, 10, reporter);
|
|
|
|
check_allocator(allocator, 100, 10, reporter);
|
|
|
|
}
|
2014-09-05 13:13:43 +00:00
|
|
|
|
2020-07-21 17:04:42 +00:00
|
|
|
template<int N1, int N2>
|
|
|
|
static void run_concat_test(skiatest::Reporter* reporter, int aCount, int bCount) {
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C, N1> listA;
|
|
|
|
SkTBlockList<C, N2> listB;
|
2020-07-21 17:04:42 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < aCount; ++i) {
|
|
|
|
listA.emplace_back(i);
|
|
|
|
}
|
|
|
|
for (int i = 0; i < bCount; ++i) {
|
|
|
|
listB.emplace_back(aCount + i);
|
|
|
|
}
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, listA.count() == aCount && listB.count() == bCount);
|
|
|
|
REPORTER_ASSERT(reporter, C::gInstCnt == aCount + bCount);
|
|
|
|
|
|
|
|
// Concatenate B into A and verify.
|
|
|
|
listA.concat(std::move(listB));
|
|
|
|
REPORTER_ASSERT(reporter, listA.count() == aCount + bCount);
|
2021-08-24 15:49:55 +00:00
|
|
|
// SkTBlockList guarantees the moved list is empty, but clang-tidy doesn't know about it;
|
2020-07-22 20:36:49 +00:00
|
|
|
// in practice we won't really be using moved lists so this won't pollute our main code base
|
|
|
|
// with lots of warning disables.
|
2020-07-21 17:04:42 +00:00
|
|
|
REPORTER_ASSERT(reporter, listB.count() == 0); // NOLINT(bugprone-use-after-move)
|
|
|
|
REPORTER_ASSERT(reporter, C::gInstCnt == aCount + bCount);
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
for (const C& item : listA.items()) {
|
|
|
|
// By construction of A and B originally, the concatenated id sequence is continuous
|
|
|
|
REPORTER_ASSERT(reporter, i == item.fID);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, i == (aCount + bCount));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int N1, int N2>
|
|
|
|
static void run_concat_trivial_test(skiatest::Reporter* reporter, int aCount, int bCount) {
|
|
|
|
static_assert(std::is_trivially_copyable<D>::value);
|
|
|
|
|
|
|
|
// This is similar to run_concat_test(), except since D is trivial we can't verify the instant
|
|
|
|
// counts that are tracked via ctor/dtor.
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<D, N1> listA;
|
|
|
|
SkTBlockList<D, N2> listB;
|
2020-07-21 17:04:42 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < aCount; ++i) {
|
|
|
|
listA.push_back({i});
|
|
|
|
}
|
|
|
|
for (int i = 0; i < bCount; ++i) {
|
|
|
|
listB.push_back({aCount + i});
|
|
|
|
}
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, listA.count() == aCount && listB.count() == bCount);
|
|
|
|
// Concatenate B into A and verify.
|
|
|
|
listA.concat(std::move(listB));
|
|
|
|
REPORTER_ASSERT(reporter, listA.count() == aCount + bCount);
|
|
|
|
REPORTER_ASSERT(reporter, listB.count() == 0); // NOLINT(bugprone-use-after-move): see above
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
for (const D& item : listA.items()) {
|
|
|
|
// By construction of A and B originally, the concatenated id sequence is continuous
|
|
|
|
REPORTER_ASSERT(reporter, i == item.fID);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, i == (aCount + bCount));
|
|
|
|
}
|
2020-07-20 20:17:14 +00:00
|
|
|
|
|
|
|
template<int N>
|
|
|
|
static void run_reserve_test(skiatest::Reporter* reporter) {
|
|
|
|
constexpr int kItemsPerBlock = N + 4; // Make this a number > 1, even if N starting items == 1
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C, N> list(kItemsPerBlock);
|
|
|
|
size_t initialSize = TBlockListTestAccess::TotalSize(list);
|
2020-07-20 20:17:14 +00:00
|
|
|
// Should be able to add N instances of T w/o changing size from initialSize
|
|
|
|
for (int i = 0; i < N; ++i) {
|
|
|
|
list.push_back(C(i));
|
|
|
|
}
|
2021-08-24 15:49:55 +00:00
|
|
|
REPORTER_ASSERT(reporter, initialSize == TBlockListTestAccess::TotalSize(list));
|
2020-07-20 20:17:14 +00:00
|
|
|
|
|
|
|
// Reserve room for 2*kItemsPerBlock items
|
|
|
|
list.reserve(2 * kItemsPerBlock);
|
|
|
|
REPORTER_ASSERT(reporter, list.count() == N); // count shouldn't change though
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
size_t reservedSize = TBlockListTestAccess::TotalSize(list);
|
2020-07-20 20:17:14 +00:00
|
|
|
REPORTER_ASSERT(reporter, reservedSize >= initialSize + 2 * kItemsPerBlock * sizeof(C));
|
|
|
|
for (int i = 0; i < 2 * kItemsPerBlock; ++i) {
|
|
|
|
list.push_back(C(i));
|
|
|
|
}
|
2021-08-24 15:49:55 +00:00
|
|
|
REPORTER_ASSERT(reporter, reservedSize == TBlockListTestAccess::TotalSize(list));
|
2020-07-20 20:17:14 +00:00
|
|
|
|
|
|
|
// Make the next block partially fully (N > 0 but < kItemsPerBlock)
|
|
|
|
for (int i = 0; i < N; ++i) {
|
|
|
|
list.push_back(C(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reserve room again for 2*kItemsPerBlock, but reserve should automatically take account of the
|
|
|
|
// (kItemsPerBlock-N) that are still available in the active block
|
|
|
|
list.reserve(2 * kItemsPerBlock);
|
|
|
|
int extraReservedCount = kItemsPerBlock + N;
|
2021-08-24 15:49:55 +00:00
|
|
|
// Because SkTBlockList normally allocates blocks in fixed sizes, and extraReservedCount >
|
2020-07-20 20:17:14 +00:00
|
|
|
// items-per-block, it will always use that size and not that of the growth policy.
|
2021-08-24 15:49:55 +00:00
|
|
|
REPORTER_ASSERT(reporter, TBlockListTestAccess::ScratchBlockSize(list) >=
|
2020-07-20 20:17:14 +00:00
|
|
|
extraReservedCount * sizeof(C));
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
reservedSize = TBlockListTestAccess::TotalSize(list);
|
2020-07-20 20:17:14 +00:00
|
|
|
for (int i = 0; i < 2 * kItemsPerBlock; ++i) {
|
|
|
|
list.push_back(C(i));
|
|
|
|
}
|
2021-08-24 15:49:55 +00:00
|
|
|
REPORTER_ASSERT(reporter, reservedSize == TBlockListTestAccess::TotalSize(list));
|
2020-07-20 20:17:14 +00:00
|
|
|
|
|
|
|
// If we reserve a count < items-per-block, it will use the fixed size from the growth policy.
|
|
|
|
list.reserve(2);
|
2021-08-24 15:49:55 +00:00
|
|
|
REPORTER_ASSERT(reporter, TBlockListTestAccess::ScratchBlockSize(list) >=
|
2020-07-20 20:17:14 +00:00
|
|
|
kItemsPerBlock * sizeof(C));
|
|
|
|
|
|
|
|
// Ensure the reservations didn't initialize any more D's than anticipated
|
|
|
|
int expectedInstanceCount = 2 * (N + 2 * kItemsPerBlock);
|
|
|
|
REPORTER_ASSERT(reporter, expectedInstanceCount == C::gInstCnt);
|
|
|
|
|
|
|
|
list.reset();
|
|
|
|
REPORTER_ASSERT(reporter, 0 == C::gInstCnt);
|
|
|
|
}
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
DEF_TEST(SkTBlockList, reporter) {
|
2020-07-17 12:39:46 +00:00
|
|
|
// Test combinations of allocators with and without stack storage and with different block sizes
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C> a1(1);
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
run_allocator_test(&a1, reporter);
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C> a2(2);
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
run_allocator_test(&a2, reporter);
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C> a5(5);
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
run_allocator_test(&a5, reporter);
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C, 1> sa1;
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
run_allocator_test(&sa1, reporter);
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C, 3> sa3;
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
run_allocator_test(&sa3, reporter);
|
|
|
|
|
2021-08-24 15:49:55 +00:00
|
|
|
SkTBlockList<C, 4> sa4;
|
Implement GrTAllocator in terms of GrBlockAllocator
Previously, the GrAllocator header defined three types: GrAllocator,
GrTAllocator, and GrSTAllocator. GrAllocator was generic, and would
manage the blocks of memory (fixed size to hold N * sizeof(item)). It
stored an SkTArray of pointers to each block. GrTAllocator wrapped
the GrAllocator to add template support for a specific T. GrSTAllocator
extended GrTAllocator to include a template arg for inline storage.
In this CL, GrAllocator is no longer defined, and its memory functionality
is replaced with the use of GrBlockAllocator. For the most part, the
implementation of GrTAllocator on top of GrBlockAllocator remains the
same, although there is explicit array to the block pointers so indexing
is slightly different. GrSTAllocator is also removed entirely, so that
GrTAllocator's template includes initial storage size.
The iteration over the allocated items
is updated to wrap GrBlockAllocator's block iterator, and then iterate
by index within each block. Documentation on GrAllocator already recommended
using the iterator instead of random access, and these changes further
reinforce it. It turns out that many of the use cases of GrAllocator
were written to use random access, so many of the files outside of
GrAllocator.h have just been updated to use the new for-range iteration
instead of a random access for loop.
Change-Id: I28b0bc277c323fd7035d4a8442ae67f058b2b64c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272058
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
2020-03-24 16:29:39 +00:00
|
|
|
run_allocator_test(&sa4, reporter);
|
2020-07-20 20:17:14 +00:00
|
|
|
|
|
|
|
run_reserve_test<1>(reporter);
|
|
|
|
run_reserve_test<2>(reporter);
|
|
|
|
run_reserve_test<3>(reporter);
|
|
|
|
run_reserve_test<4>(reporter);
|
|
|
|
run_reserve_test<5>(reporter);
|
2020-07-21 17:04:42 +00:00
|
|
|
|
|
|
|
run_concat_test<1, 1>(reporter, 10, 10);
|
|
|
|
run_concat_test<5, 1>(reporter, 50, 10);
|
|
|
|
run_concat_test<1, 5>(reporter, 10, 50);
|
|
|
|
run_concat_test<5, 5>(reporter, 100, 100);
|
|
|
|
|
|
|
|
run_concat_trivial_test<1, 1>(reporter, 10, 10);
|
|
|
|
run_concat_trivial_test<5, 1>(reporter, 50, 10);
|
|
|
|
run_concat_trivial_test<1, 5>(reporter, 10, 50);
|
|
|
|
run_concat_trivial_test<5, 5>(reporter, 100, 100);
|
2014-09-05 13:13:43 +00:00
|
|
|
}
|