skia2/tests/SkTBlockListTest.cpp

339 lines
12 KiB
C++
Raw Normal View History

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/core/SkTBlockList.h"
#include "tests/Test.h"
namespace {
struct C {
C() : fID(-1) { ++gInstCnt; }
C(int id) : fID(id) { ++gInstCnt; }
C(C&& c) : C(c.fID) {}
C(const C& c) : C(c.fID) {}
C& operator=(C&&) = default;
C& operator=(const C&) = default;
~C() { --gInstCnt; }
int fID;
// Under the hood, SkTBlockList and SkBlockAllocator round up to max_align_t. If 'C' was
// just 4 bytes, that often means the internal blocks can squeeze a few extra instances in. This
// is fine, but makes predicting a little trickier, so make sure C is a bit bigger.
int fPadding[4];
static int gInstCnt;
};
int C::gInstCnt = 0;
Reland "Support moving blocks from one allocator to another" This reverts commit 423dd689df15c2ae00a05fc70d86b558d44b9686. Reason for revert: had missed corner case when tail block was empty Original change's description: > Revert "Support moving blocks from one allocator to another" > > This reverts commit 0f064041bfd939c65ae63b84b3584c97db2736a0. > > Reason for revert: unit test failures on some windows bots > > Original change's description: > > Support moving blocks from one allocator to another > > > > Uses this new capability and the previously implemented reserve() > > feature to implement efficient concatenation of GrTAllocators. > > > > Change-Id: I2aff42eaf75e74e3b595d3069b6a271fa7329465 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303665 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I931f2462ecf6e04d40a671336d0de7d80efd313d > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304604 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com # Not skipping CQ checks because this is a reland. Change-Id: Ia793c2f0e7ab2f3fd437871fa7fb4f56979f9ceb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304739 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-07-21 17:04:42 +00:00
struct D {
int fID;
};
} // namespace
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();
}
};
// 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>
static void check_allocator_helper(SkTBlockList<C, N>* allocator, int cnt, int popCnt,
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;
}
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);
if (cnt > 0) {
REPORTER_ASSERT(reporter, cnt-1 == allocator->back().fID);
}
if (popCnt > 0) {
for (i = 0; i < popCnt; ++i) {
allocator->pop_back();
}
check_allocator_helper(allocator, cnt - popCnt, 0, reporter);
}
}
template<int N>
static void check_iterator_helper(SkTBlockList<C, N>* allocator,
const std::vector<C*>& expected,
skiatest::Reporter* reporter) {
const SkTBlockList<C, N>* cAlloc = allocator;
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
for (i = 0; i < allocator->count(); ++i) {
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>
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) {
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());
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) {
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
}
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
}
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();
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>
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);
}
Reland "Support moving blocks from one allocator to another" This reverts commit 423dd689df15c2ae00a05fc70d86b558d44b9686. Reason for revert: had missed corner case when tail block was empty Original change's description: > Revert "Support moving blocks from one allocator to another" > > This reverts commit 0f064041bfd939c65ae63b84b3584c97db2736a0. > > Reason for revert: unit test failures on some windows bots > > Original change's description: > > Support moving blocks from one allocator to another > > > > Uses this new capability and the previously implemented reserve() > > feature to implement efficient concatenation of GrTAllocators. > > > > Change-Id: I2aff42eaf75e74e3b595d3069b6a271fa7329465 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303665 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I931f2462ecf6e04d40a671336d0de7d80efd313d > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304604 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com # Not skipping CQ checks because this is a reland. Change-Id: Ia793c2f0e7ab2f3fd437871fa7fb4f56979f9ceb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304739 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
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) {
SkTBlockList<C, N1> listA;
SkTBlockList<C, N2> listB;
Reland "Support moving blocks from one allocator to another" This reverts commit 423dd689df15c2ae00a05fc70d86b558d44b9686. Reason for revert: had missed corner case when tail block was empty Original change's description: > Revert "Support moving blocks from one allocator to another" > > This reverts commit 0f064041bfd939c65ae63b84b3584c97db2736a0. > > Reason for revert: unit test failures on some windows bots > > Original change's description: > > Support moving blocks from one allocator to another > > > > Uses this new capability and the previously implemented reserve() > > feature to implement efficient concatenation of GrTAllocators. > > > > Change-Id: I2aff42eaf75e74e3b595d3069b6a271fa7329465 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303665 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I931f2462ecf6e04d40a671336d0de7d80efd313d > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304604 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com # Not skipping CQ checks because this is a reland. Change-Id: Ia793c2f0e7ab2f3fd437871fa7fb4f56979f9ceb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304739 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
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);
// SkTBlockList guarantees the moved list is empty, but clang-tidy doesn't know about it;
// in practice we won't really be using moved lists so this won't pollute our main code base
// with lots of warning disables.
Reland "Support moving blocks from one allocator to another" This reverts commit 423dd689df15c2ae00a05fc70d86b558d44b9686. Reason for revert: had missed corner case when tail block was empty Original change's description: > Revert "Support moving blocks from one allocator to another" > > This reverts commit 0f064041bfd939c65ae63b84b3584c97db2736a0. > > Reason for revert: unit test failures on some windows bots > > Original change's description: > > Support moving blocks from one allocator to another > > > > Uses this new capability and the previously implemented reserve() > > feature to implement efficient concatenation of GrTAllocators. > > > > Change-Id: I2aff42eaf75e74e3b595d3069b6a271fa7329465 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303665 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I931f2462ecf6e04d40a671336d0de7d80efd313d > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304604 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com # Not skipping CQ checks because this is a reland. Change-Id: Ia793c2f0e7ab2f3fd437871fa7fb4f56979f9ceb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304739 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
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.
SkTBlockList<D, N1> listA;
SkTBlockList<D, N2> listB;
Reland "Support moving blocks from one allocator to another" This reverts commit 423dd689df15c2ae00a05fc70d86b558d44b9686. Reason for revert: had missed corner case when tail block was empty Original change's description: > Revert "Support moving blocks from one allocator to another" > > This reverts commit 0f064041bfd939c65ae63b84b3584c97db2736a0. > > Reason for revert: unit test failures on some windows bots > > Original change's description: > > Support moving blocks from one allocator to another > > > > Uses this new capability and the previously implemented reserve() > > feature to implement efficient concatenation of GrTAllocators. > > > > Change-Id: I2aff42eaf75e74e3b595d3069b6a271fa7329465 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303665 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I931f2462ecf6e04d40a671336d0de7d80efd313d > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304604 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com # Not skipping CQ checks because this is a reland. Change-Id: Ia793c2f0e7ab2f3fd437871fa7fb4f56979f9ceb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304739 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
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));
}
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
SkTBlockList<C, N> list(kItemsPerBlock);
size_t initialSize = TBlockListTestAccess::TotalSize(list);
// 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));
}
REPORTER_ASSERT(reporter, initialSize == TBlockListTestAccess::TotalSize(list));
// Reserve room for 2*kItemsPerBlock items
list.reserve(2 * kItemsPerBlock);
REPORTER_ASSERT(reporter, list.count() == N); // count shouldn't change though
size_t reservedSize = TBlockListTestAccess::TotalSize(list);
REPORTER_ASSERT(reporter, reservedSize >= initialSize + 2 * kItemsPerBlock * sizeof(C));
for (int i = 0; i < 2 * kItemsPerBlock; ++i) {
list.push_back(C(i));
}
REPORTER_ASSERT(reporter, reservedSize == TBlockListTestAccess::TotalSize(list));
// 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;
// Because SkTBlockList normally allocates blocks in fixed sizes, and extraReservedCount >
// items-per-block, it will always use that size and not that of the growth policy.
REPORTER_ASSERT(reporter, TBlockListTestAccess::ScratchBlockSize(list) >=
extraReservedCount * sizeof(C));
reservedSize = TBlockListTestAccess::TotalSize(list);
for (int i = 0; i < 2 * kItemsPerBlock; ++i) {
list.push_back(C(i));
}
REPORTER_ASSERT(reporter, reservedSize == TBlockListTestAccess::TotalSize(list));
// If we reserve a count < items-per-block, it will use the fixed size from the growth policy.
list.reserve(2);
REPORTER_ASSERT(reporter, TBlockListTestAccess::ScratchBlockSize(list) >=
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);
}
DEF_TEST(SkTBlockList, reporter) {
// Test combinations of allocators with and without stack storage and with different block sizes
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);
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);
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);
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);
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);
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);
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);
Reland "Support moving blocks from one allocator to another" This reverts commit 423dd689df15c2ae00a05fc70d86b558d44b9686. Reason for revert: had missed corner case when tail block was empty Original change's description: > Revert "Support moving blocks from one allocator to another" > > This reverts commit 0f064041bfd939c65ae63b84b3584c97db2736a0. > > Reason for revert: unit test failures on some windows bots > > Original change's description: > > Support moving blocks from one allocator to another > > > > Uses this new capability and the previously implemented reserve() > > feature to implement efficient concatenation of GrTAllocators. > > > > Change-Id: I2aff42eaf75e74e3b595d3069b6a271fa7329465 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303665 > > Commit-Queue: Michael Ludwig <michaelludwig@google.com> > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com > > Change-Id: I931f2462ecf6e04d40a671336d0de7d80efd313d > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304604 > Reviewed-by: Michael Ludwig <michaelludwig@google.com> > Commit-Queue: Michael Ludwig <michaelludwig@google.com> TBR=robertphillips@google.com,csmartdalton@google.com,michaelludwig@google.com # Not skipping CQ checks because this is a reland. Change-Id: Ia793c2f0e7ab2f3fd437871fa7fb4f56979f9ceb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304739 Auto-Submit: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
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);
}