From 5a4d93a72d44cdafb1eb4de63d2963ecc1b31eb2 Mon Sep 17 00:00:00 2001 From: joaquintides Date: Fri, 21 Jul 2023 19:39:43 +0200 Subject: [PATCH] documented [c]visit_(until|while) --- doc/unordered/changes.adoc | 5 ++ doc/unordered/concurrent.adoc | 33 +++++++- doc/unordered/concurrent_flat_map.adoc | 108 +++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 3 deletions(-) diff --git a/doc/unordered/changes.adoc b/doc/unordered/changes.adoc index 5679a9ea..6cf4c767 100644 --- a/doc/unordered/changes.adoc +++ b/doc/unordered/changes.adoc @@ -6,6 +6,11 @@ :github-pr-url: https://github.com/boostorg/unordered/pull :cpp: C++ +== Release 1.84.0 + +* Added `[c]visit_until` and `[c]visit_while` operations to `boost::concurrent_map`, +with serial and parallel variants. + == Release 1.83.0 - Major update * Added `boost::concurrent_flat_map`, a fast, thread-safe hashmap based on open addressing. diff --git a/doc/unordered/concurrent.adoc b/doc/unordered/concurrent.adoc index 3410570a..1d66a53c 100644 --- a/doc/unordered/concurrent.adoc +++ b/doc/unordered/concurrent.adoc @@ -154,7 +154,34 @@ m.visit_all(std::execution::par, [](auto& x) { // run in parallel }); ---- -There is another whole-table visitation operation, `erase_if`: +Traversal can be interrupted midway: + +[source,c++] +---- +// finds the key to a given (unique value) + +int key = 0; +int value = ...; +bool found = m.visit_until([&](const auto& x) { + if(x.second == value) { + key = x.first; + return true; // finish + } + else { + return false; // keep on visiting + } +}); + +if(found) { ... } + +// check if all values are != 0 + +bool all_ok = m.visit_while([&](const auto& x) { + return x.second != 0; +}); +---- + +There is one last whole-table visitation operation, `erase_if`: [source,c++] ---- @@ -163,8 +190,8 @@ m.erase_if([](auto& x) { }); ---- -`erase_if` can also be parallelized. Note that, in order to increase efficiency, -these operations do not block the table during execution: this implies that elements +`visit_until`, `visit_while` and `erase_if` can also be parallelized. Note that, in order to increase efficiency, +whole-table visitation operations do not block the table during execution: this implies that elements may be inserted, modified or erased by other threads during visitation. It is advisable not to assume too much about the exact global state of a `boost::concurrent_flat_map` at any point in your program. diff --git a/doc/unordered/concurrent_flat_map.adoc b/doc/unordered/concurrent_flat_map.adoc index fcdc8662..dd9199b7 100644 --- a/doc/unordered/concurrent_flat_map.adoc +++ b/doc/unordered/concurrent_flat_map.adoc @@ -114,6 +114,26 @@ namespace boost { template void xref:#concurrent_flat_map_parallel_cvisit_all[cvisit_all](ExecutionPolicy&& policy, F f) const; + template bool xref:#concurrent_flat_map_cvisit_until[visit_until](F f); + template bool xref:#concurrent_flat_map_cvisit_until[visit_until](F f) const; + template bool xref:#concurrent_flat_map_cvisit_until[cvisit_until](F f) const; + template + bool xref:#concurrent_flat_map_parallel_cvisit_until[visit_until](ExecutionPolicy&& policy, F f); + template + bool xref:#concurrent_flat_map_parallel_cvisit_until[visit_until](ExecutionPolicy&& policy, F f) const; + template + bool xref:#concurrent_flat_map_parallel_cvisit_until[cvisit_until](ExecutionPolicy&& policy, F f) const; + + template bool xref:#concurrent_flat_map_cvisit_while[visit_while](F f); + template bool xref:#concurrent_flat_map_cvisit_while[visit_while](F f) const; + template bool xref:#concurrent_flat_map_cvisit_while[cvisit_while](F f) const; + template + bool xref:#concurrent_flat_map_parallel_cvisit_while[visit_while](ExecutionPolicy&& policy, F f); + template + bool xref:#concurrent_flat_map_parallel_cvisit_while[visit_while](ExecutionPolicy&& policy, F f) const; + template + bool xref:#concurrent_flat_map_parallel_cvisit_while[cvisit_while](ExecutionPolicy&& policy, F f) const; + // capacity ++[[nodiscard]]++ bool xref:#concurrent_flat_map_empty[empty]() const noexcept; size_type xref:#concurrent_flat_map_size[size]() const noexcept; @@ -720,6 +740,94 @@ Unsequenced execution policies are not allowed. --- +==== [c]visit_until + +```c++ +template bool visit_until(F f); +template bool visit_until(F f) const; +template bool cvisit_until(F f) const; +``` + +Successively invokes `f` with references to each of the elements in the table until `f` returns `true` +or all the elements are visited. +Such references to the elements are const iff `*this` is const. + +[horizontal] +Returns:;; `true` iff `f` ever returns `true`. + +--- + +==== Parallel [c]visit_until + +```c++ +template bool visit_until(ExecutionPolicy&& policy, F f); +template bool visit_until(ExecutionPolicy&& policy, F f) const; +template bool cvisit_until(ExecutionPolicy&& policy, F f) const; +``` + +Invokes `f` with references to each of the elements in the table until `f` returns `true` +or all the elements are visited. +Such references to the elements are const iff `*this` is const. +Execution is parallelized according to the semantics of the execution policy specified. + +[horizontal] +Returns:;; `true` iff `f` ever returns `true`. +Throws:;; Depending on the exception handling mechanism of the execution policy used, may call `std::terminate` if an exception is thrown within `f`. +Notes:;; Only available in compilers supporting C++17 parallel algorithms. + ++ +These overloads only participate in overload resolution if `std::is_execution_policy_v>` is `true`. + ++ +Unsequenced execution policies are not allowed. + ++ +Parallelization implies that execution does not necessary finish as soon as `f` returns `true`, and as a result +`f` may be invoked with further elements for which the return value is also `true`. + +--- + +==== [c]visit_while + +```c++ +template bool visit_while(F f); +template bool visit_while(F f) const; +template bool cvisit_while(F f) const; +``` + +Successively invokes `f` with references to each of the elements in the table until `f` returns `false` +or all the elements are visited. +Such references to the elements are const iff `*this` is const. + +[horizontal] +Returns:;; `false` iff `f` ever returns `false`. + +--- + +==== Parallel [c]visit_while + +```c++ +template bool visit_while(ExecutionPolicy&& policy, F f); +template bool visit_while(ExecutionPolicy&& policy, F f) const; +template bool cvisit_while(ExecutionPolicy&& policy, F f) const; +``` + +Invokes `f` with references to each of the elements in the table until `f` returns `false` +or all the elements are visited. +Such references to the elements are const iff `*this` is const. +Execution is parallelized according to the semantics of the execution policy specified. + +[horizontal] +Returns:;; `false` iff `f` ever returns `false`. +Throws:;; Depending on the exception handling mechanism of the execution policy used, may call `std::terminate` if an exception is thrown within `f`. +Notes:;; Only available in compilers supporting C++17 parallel algorithms. + ++ +These overloads only participate in overload resolution if `std::is_execution_policy_v>` is `true`. + ++ +Unsequenced execution policies are not allowed. + ++ +Parallelization implies that execution does not necessary finish as soon as `f` returns `false`, and as a result +`f` may be invoked with further elements for which the return value is also `false`. + +--- + === Size and Capacity ==== empty