Skip to content

Commit

Permalink
pw_containers: Add IntrusiveMap and IntrusiveMultiMap
Browse files Browse the repository at this point in the history
This CL adds intrusive, ordered maps backed by an AA tree
implementation. These can be used for associative dictionaries or for
sorted lists, among other uses.

Change-Id: I81194bcdbff70a807f52547e99a04649c5b61635
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/216828
Lint: Lint 🤖 <[email protected]>
Reviewed-by: Wyatt Hepler <[email protected]>
Commit-Queue: Aaron Green <[email protected]>
  • Loading branch information
nopsledder authored and CQ Bot Account committed Sep 19, 2024
1 parent e8ab2b0 commit 8a3250d
Show file tree
Hide file tree
Showing 15 changed files with 3,664 additions and 10 deletions.
2 changes: 2 additions & 0 deletions docs/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ _doxygen_input_files = [ # keep-sorted: start
"$dir_pw_containers/public/pw_containers/inline_var_len_entry_queue.h",
"$dir_pw_containers/public/pw_containers/intrusive_forward_list.h",
"$dir_pw_containers/public/pw_containers/intrusive_list.h",
"$dir_pw_containers/public/pw_containers/intrusive_map.h",
"$dir_pw_containers/public/pw_containers/intrusive_multimap.h",
"$dir_pw_crypto/public/pw_crypto/ecdsa.h",
"$dir_pw_crypto/public/pw_crypto/sha256.h",
"$dir_pw_digital_io/public/pw_digital_io/digital_io.h",
Expand Down
66 changes: 59 additions & 7 deletions pw_containers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ label_flag(
# Libraries

cc_library(
# This group is deprecated. Prefer to depend on individual features rather
# than on this collection.
name = "pw_containers",
deps = [
":algorithm",
":flat_map",
":inline_deque",
":inline_queue",
":intrusive_forward_list",
":intrusive_list",
":vector",
],
Expand Down Expand Up @@ -107,6 +108,39 @@ cc_library(
deps = [":intrusive_forward_list"],
)

cc_library(
name = "intrusive_map_common",
srcs = [
"aa_tree.cc",
"aa_tree_item.cc",
],
hdrs = [
"public/pw_containers/internal/aa_tree.h",
"public/pw_containers/internal/aa_tree_item.h",
"public/pw_containers/internal/aa_tree_iterator.h",
],
includes = ["public"],
deps = [
":intrusive",
"//pw_assert",
"//pw_bytes:packed_ptr",
],
)

cc_library(
name = "intrusive_map",
hdrs = ["public/pw_containers/intrusive_map.h"],
includes = ["public"],
deps = [":intrusive_map_common"],
)

cc_library(
name = "intrusive_multimap",
hdrs = ["public/pw_containers/intrusive_multimap.h"],
includes = ["public"],
deps = [":intrusive_map_common"],
)

cc_library(
name = "iterator",
hdrs = ["public/pw_containers/iterator.h"],
Expand Down Expand Up @@ -324,9 +358,7 @@ pw_cc_test(

pw_cc_test(
name = "intrusive_forward_list_test",
srcs = [
"intrusive_forward_list_test.cc",
],
srcs = ["intrusive_forward_list_test.cc"],
deps = [
":intrusive_forward_list",
":vector",
Expand All @@ -337,13 +369,33 @@ pw_cc_test(

pw_cc_test(
name = "intrusive_list_test",
srcs = [
"intrusive_list_test.cc",
],
srcs = ["intrusive_list_test.cc"],
deps = [
":intrusive_list",
":vector",
"//pw_compilation_testing:negative_compilation_testing",
"//pw_unit_test",
],
)

pw_cc_test(
name = "intrusive_map_test",
srcs = ["intrusive_map_test.cc"],
deps = [
":intrusive_map",
":intrusive_multimap",
"//pw_compilation_testing:negative_compilation_testing",
"//pw_span",
],
)

pw_cc_test(
name = "intrusive_multimap_test",
srcs = ["intrusive_multimap_test.cc"],
deps = [
":intrusive_map",
":intrusive_multimap",
"//pw_compilation_testing:negative_compilation_testing",
"//pw_span",
],
)
53 changes: 52 additions & 1 deletion pw_containers/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ group("pw_containers") {
":flat_map",
":inline_deque",
":inline_queue",
":intrusive_forward_list",
":intrusive_list",
":vector",
]
Expand Down Expand Up @@ -185,6 +184,36 @@ pw_source_set("legacy_intrusive_list") {
public_deps = [ ":intrusive_forward_list" ]
}

pw_source_set("intrusive_map_common") {
public_configs = [ ":public_include_path" ]
public = [
"public/pw_containers/internal/aa_tree.h",
"public/pw_containers/internal/aa_tree_item.h",
"public/pw_containers/internal/aa_tree_iterator.h",
]
public_deps = [
":intrusive",
"$dir_pw_bytes:packed_ptr",
dir_pw_assert,
]
sources = [
"aa_tree.cc",
"aa_tree_item.cc",
]
}

pw_source_set("intrusive_map") {
public_configs = [ ":public_include_path" ]
public = [ "public/pw_containers/intrusive_map.h" ]
public_deps = [ ":intrusive_map_common" ]
}

pw_source_set("intrusive_multimap") {
public_configs = [ ":public_include_path" ]
public = [ "public/pw_containers/intrusive_multimap.h" ]
public_deps = [ ":intrusive_map_common" ]
}

pw_test_group("tests") {
tests = [
":algorithm_test",
Expand All @@ -194,6 +223,8 @@ pw_test_group("tests") {
":inline_queue_test",
":intrusive_forward_list_test",
":intrusive_list_test",
":intrusive_map_test",
":intrusive_multimap_test",
":raw_storage_test",
":to_array_test",
":inline_var_len_entry_queue_test",
Expand Down Expand Up @@ -346,6 +377,26 @@ pw_test("intrusive_list_test") {
configs = [ "$dir_pw_build:conversion_warnings" ]
}

pw_test("intrusive_map_test") {
sources = [ "intrusive_map_test.cc" ]
deps = [
":intrusive_map",
":intrusive_multimap",
dir_pw_span,
]
negative_compilation_tests = true
}

pw_test("intrusive_multimap_test") {
sources = [ "intrusive_multimap_test.cc" ]
deps = [
":intrusive_map",
":intrusive_multimap",
dir_pw_span,
]
negative_compilation_tests = true
}

pw_doc_group("docs") {
sources = [ "docs.rst" ]
report_deps = [ ":intrusive_list_size_report" ]
Expand Down
61 changes: 61 additions & 0 deletions pw_containers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pw_add_library(pw_containers INTERFACE
pw_containers.inline_deque
pw_containers.inline_queue
pw_containers.intrusive_list
pw_containers.intrusive_map
pw_containers.vector
)

Expand Down Expand Up @@ -198,6 +199,40 @@ pw_add_library(pw_containers.legacy_intrusive_list INTERFACE
pw_containers.intrusive_forward_list
)

pw_add_library(pw_containers.intrusive_map_common STATIC
HEADERS
public/pw_containers/internal/aa_tree.h
public/pw_containers/internal/aa_tree_item.h
public/pw_containers/internal/aa_tree_iterator.h
PUBLIC_INCLUDES
public
PUBLIC_DEPS
pw_assert
pw_bytes.packed_ptr
pw_containers.intrusive
SOURCES
aa_tree.cc
aa_tree_item.cc
)

pw_add_library(pw_containers.intrusive_map INTERFACE
HEADERS
public/pw_containers/intrusive_map.h
PUBLIC_INCLUDES
public
PUBLIC_DEPS
pw_containers.intrusive_map_common
)

pw_add_library(pw_containers.intrusive_multimap INTERFACE
HEADERS
public/pw_containers/intrusive_multimap.h
PUBLIC_INCLUDES
public
PUBLIC_DEPS
pw_containers.intrusive_map_common
)

pw_add_test(pw_containers.algorithm_test
SOURCES
algorithm_test.cc
Expand Down Expand Up @@ -342,3 +377,29 @@ pw_add_test(pw_containers.intrusive_list_test
modules
pw_containers
)

pw_add_test(pw_containers.intrusive_map_test
SOURCES
intrusive_map_test.cc
PRIVATE_DEPS
pw_compilation_testing._pigweed_only_negative_compilation
pw_containers.intrusive_map
pw_containers.intrusive_multimap
pw_span
GROUPS
modules
pw_containers
)

pw_add_test(pw_containers.intrusive_multimap_test
SOURCES
intrusive_multimap_test.cc
PRIVATE_DEPS
pw_compilation_testing._pigweed_only_negative_compilation
pw_containers.intrusive_map
pw_containers.intrusive_multimap
pw_span
GROUPS
modules
pw_containers
)
59 changes: 59 additions & 0 deletions pw_containers/aa_tree.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_containers/internal/aa_tree.h"

namespace pw::containers::internal {

void GenericAATree::SetRoot(AATreeItem* item) {
if (item != nullptr) {
item->parent_.set(nullptr);
}
root_ = item;
}

size_t GenericAATree::size() const {
return empty() ? 0 : root_->GetTreeSize();
}

void GenericAATree::clear() {
if (root_ != nullptr) {
root_->Clear();
SetRoot(nullptr);
}
}

GenericAATree::iterator GenericAATree::erase(AATreeItem& item) {
if (item.GetRoot() != root_) {
return iterator(&root_);
}
AATreeItem* next = item.GetSuccessor();
SetRoot(item.Unmap());
return iterator(&root_, next);
}

GenericAATree::iterator GenericAATree::erase(AATreeItem& first,
AATreeItem& last) {
iterator iter(&root_, &first);
while (&(*iter) != &last) {
iter = erase(*iter);
}
return iter;
}

void GenericAATree::swap(GenericAATree& other) {
std::swap(root_, other.root_);
}

} // namespace pw::containers::internal
Loading

0 comments on commit 8a3250d

Please sign in to comment.