Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2022-09-18 20:44:37 +0300
committerJacques Lucke <jacques@blender.org>2022-09-18 20:44:37 +0300
commit3da0b9e1b9073269e866326504e6d679b229e49b (patch)
tree1faf25bd3cfbf0646a3b1eca49343dca635fdc42
parentd696514283857bfc771d2b38dfd0710c6a5d1046 (diff)
-rw-r--r--source/blender/blenlib/BLI_chunk_list.hh83
-rw-r--r--source/blender/blenlib/tests/BLI_chunk_list_test.cc29
2 files changed, 72 insertions, 40 deletions
diff --git a/source/blender/blenlib/BLI_chunk_list.hh b/source/blender/blenlib/BLI_chunk_list.hh
index 963e7af90e8..535eb9d1258 100644
--- a/source/blender/blenlib/BLI_chunk_list.hh
+++ b/source/blender/blenlib/BLI_chunk_list.hh
@@ -257,53 +257,56 @@ class ChunkList {
{
AllocInfo *other_alloc_info = other.alloc_info_;
+ auto reset_other_active = [&]() {
+ other.active_begin_ = other.inline_buffer_;
+ other.active_end_ = other.active_begin_;
+ other.active_capacity_end_ = other.active_begin_ + OtherInlineBufferCapacity;
+ };
+
if (other_alloc_info == nullptr) {
/* Handle case when the other list is fully inline. */
this->extend_move({other.active_begin_, other.active_end_ - other.active_begin_});
+ reset_other_active();
+ return;
}
- else {
- /* Make sure all chunks are up to date. */
- RawChunk &other_active_chunk = other_alloc_info->raw_chunks[other_alloc_info->active];
- other_active_chunk.end_if_inactive = other.active_end_;
- for (const int64_t other_chunk_index : other_alloc_info->raw_chunks.index_range()) {
- const RawChunk &other_chunk = other_alloc_info->raw_chunks[other_chunk_index];
- if (other_chunk.allocation == nullptr) {
- /* This chunk is inline. */
- this->extend_move({other_chunk.begin, other_chunk.end_if_inactive - other_chunk.begin});
- }
- else if (alloc_info_ == nullptr) {
- alloc_info_ = other_alloc_info;
- other.alloc_info_ = nullptr;
- RawChunk &first_chunk = alloc_info_->raw_chunks[0];
- BLI_assert(first_chunk.allocation == nullptr);
- first_chunk.begin = active_begin_;
- first_chunk.capacity_end = active_capacity_end_;
- first_chunk.end_if_inactive = active_end_;
- break;
- }
- else {
- alloc_info_->raw_chunks.append(other_chunk);
- if (other_chunk.begin < other_chunk.end_if_inactive) {
- alloc_info_->active = alloc_info_->raw_chunks.size() - 1;
- }
- }
- }
- if (alloc_info_ != nullptr) {
- const RawChunk &active_chunk = alloc_info_->raw_chunks[alloc_info_->active];
- active_begin_ = active_chunk.begin;
- active_end_ = active_chunk.end_if_inactive;
- active_capacity_end_ = active_chunk.capacity_end;
- }
- if (other.alloc_info_ != nullptr) {
- other.alloc_info_->raw_chunks.resize(1);
- }
+ /* Make sure all chunks are up to date. */
+ other_alloc_info->raw_chunks[other_alloc_info->active].end_if_inactive = other.active_end_;
+
+ /* Always move first chunk. */
+ RawChunk &other_inline_chunk = other_alloc_info->raw_chunks[0];
+ this->extend_move(
+ {other_inline_chunk.begin, other_inline_chunk.end_if_inactive - other_inline_chunk.begin});
+
+ auto update_self_active = [&]() {
+ RawChunk &active_chunk = alloc_info_->raw_chunks[alloc_info_->active];
+ active_begin_ = active_chunk.begin;
+ active_end_ = active_chunk.end_if_inactive;
+ active_capacity_end_ = active_chunk.capacity_end;
+ };
+
+ /* Try to steal info block. */
+ if (alloc_info_ == nullptr) {
+ alloc_info_ = other_alloc_info;
+ other.alloc_info_ = nullptr;
+ alloc_info_->raw_chunks[0] = {active_begin_, active_end_, active_capacity_end_, nullptr};
+ reset_other_active();
+ update_self_active();
+ return;
}
- /* Reset the other list. */
- other.active_begin_ = other.inline_buffer_;
- other.active_end_ = other.active_begin_;
- other.active_capacity_end_ = other.active_begin_ + OtherInlineBufferCapacity;
+ alloc_info_->raw_chunks[alloc_info_->active].end_if_inactive = active_end_;
+
+ alloc_info_->raw_chunks.extend(other_alloc_info->raw_chunks.as_span().drop_front(1));
+ alloc_info_->active += other_alloc_info->active;
+ other_alloc_info->raw_chunks.resize(1);
+ other_alloc_info->raw_chunks[0] = {other.inline_buffer_,
+ other.inline_buffer_,
+ other.inline_buffer_ + OtherInlineBufferCapacity,
+ nullptr};
+ other_alloc_info->active = 0;
+ reset_other_active();
+ update_self_active();
}
void extend_move(const MutableSpan<T> values)
diff --git a/source/blender/blenlib/tests/BLI_chunk_list_test.cc b/source/blender/blenlib/tests/BLI_chunk_list_test.cc
index 7aadf680ba7..de677e5644a 100644
--- a/source/blender/blenlib/tests/BLI_chunk_list_test.cc
+++ b/source/blender/blenlib/tests/BLI_chunk_list_test.cc
@@ -65,4 +65,33 @@ TEST(chunk_list, Stack)
EXPECT_EQ(list.size(), 0);
}
+TEST(chunk_list, ExtendOther)
+{
+ const std::array self_sizes = {0, 2, 5, 10, 50, 300};
+ const std::array other_sizes = self_sizes;
+
+ for (const int self_size : self_sizes) {
+ for (const int other_size : other_sizes) {
+ ChunkList<int> self;
+ for (const int i : IndexRange(self_size)) {
+ self.append(i);
+ }
+ ChunkList<int> other;
+ for (const int i : IndexRange(other_size)) {
+ other.append(i);
+ }
+ self.extend(std::move(other));
+ EXPECT_EQ(self.size(), self_size + other_size);
+ EXPECT_EQ(other.size(), 0);
+
+ for (const int i : IndexRange(other_size)) {
+ EXPECT_EQ(self.pop_last(), other_size - i - 1);
+ }
+ for (const int i : IndexRange(self_size)) {
+ EXPECT_EQ(self.pop_last(), self_size - i - 1);
+ }
+ }
+ }
+}
+
} // namespace blender::tests