Skip to content

Commit

Permalink
fix xrefs and image paths
Browse files Browse the repository at this point in the history
  • Loading branch information
cmazakas committed Jan 3, 2025
1 parent 6f432c0 commit db31da1
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 212 deletions.
263 changes: 131 additions & 132 deletions doc/modules/ROOT/pages/benchmarks.adoc

Large diffs are not rendered by default.

17 changes: 7 additions & 10 deletions doc/modules/ROOT/pages/buckets.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[#buckets]
:idprefix: buckets_
:imagesdir: ../diagrams

= Basics of Hash Tables

Expand Down Expand Up @@ -49,15 +48,15 @@ open-addressing containers offer a very limited API for accessing buckets.
2+^h| *All containers*
h|*Method* h|*Description*

|`size_type bucket_count() const`
|`size_type bucket_count() const`
|The number of buckets.

2+^h| *Closed-addressing containers only*
h|*Method* h|*Description*

|`size_type max_bucket_count() const`
|`size_type max_bucket_count() const`
|An upper bound on the number of buckets.
|`size_type bucket_size(size_type n) const`
|`size_type bucket_size(size_type n) const`
|The number of elements in bucket `n`.

|`size_type bucket(key_type const& k) const`
Expand Down Expand Up @@ -112,13 +111,13 @@ or close to the hint - unless your hint is unreasonably small or large.
2+^h| *All containers*
h|*Method* h|*Description*

|`X(size_type n)`
|`X(size_type n)`
|Construct an empty container with at least `n` buckets (`X` is the container type).

|`X(InputIterator i, InputIterator j, size_type n)`
|`X(InputIterator i, InputIterator j, size_type n)`
|Construct an empty container with at least `n` buckets and insert elements from the range `[i, j)` (`X` is the container type).

|`float load_factor() const`
|`float load_factor() const`
|The average number of elements per bucket.

|`float max_load_factor() const`
Expand All @@ -139,12 +138,10 @@ h|*Method* h|*Description*

|===

A note on `max_load` for open-addressing and concurrent containers: the maximum load will be
A note on `max_load` for open-addressing and concurrent containers: the maximum load will be
(`max_load_factor() * bucket_count()`) right after `rehash` or on container creation, but may
slightly decrease when erasing elements in high-load situations. For instance, if we
have a <<unordered_flat_map,`boost::unordered_flat_map`>> with `size()` almost
at `max_load()` level and then erase 1,000 elements, `max_load()` may decrease by around a
few dozen elements. This is done internally by Boost.Unordered in order
to keep its performance stable, and must be taken into account when planning for rehash-free insertions.


4 changes: 1 addition & 3 deletions doc/modules/ROOT/pages/changes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ when the returned proxy is not used.

This is major change which has been converted to use Boost.Move's move
emulation, and be more compliant with the {cpp}11 standard. See the
xref:unordered.adoc#compliance[compliance section] for details.
xref:compliance.adoc[compliance section] for details.

The container now meets {cpp}11's complexity requirements, but to do so
uses a little more memory. This means that `quick_erase` and
Expand Down Expand Up @@ -456,5 +456,3 @@ many of the suggestions from the review.

Initial review version, for the review conducted from 7th December 2007 to
16th December 2007.


10 changes: 5 additions & 5 deletions doc/modules/ROOT/pages/compliance.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ are only available on {cpp}17 (or later) compilers.
=== Piecewise Pair Emplacement

In accordance with the standard specification,
`boost::unordered_[multi]map::emplace` supports piecewise pair construction:
`boost::unordered_[multi]map::emplace` supports piecewise pair construction:

[source,c++]
----
Expand Down Expand Up @@ -66,7 +66,7 @@ radically different from that imposed by the standard (closed addressing).

Open-addressing containers provided by Boost.Unordered only work with reasonably
compliant C++11 (or later) compilers. Language-level features such as move semantics
and variadic template parameters are then not emulated.
and variadic template parameters are then not emulated.
The containers are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^]
and support https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[fancy pointers^].

Expand Down Expand Up @@ -103,7 +103,7 @@ except those implying iterators.

In a non-concurrent unordered container, iterators serve two main purposes:

* Access to an element previously located via lookup.
* Access to an element previously located via lookup.
* Container traversal.

In place of iterators, Boost.Unordered concurrent containers use _internal visitation_
Expand Down Expand Up @@ -136,7 +136,7 @@ template<class F> size_t visit_all(F f);
of which there are parallelized versions in C++17 compilers with parallel
algorithm support. In general, the interface of concurrent containers
is derived from that of their non-concurrent counterparts by a fairly straightforward
process of replacing iterators with visitation where applicable. If for
process of replacing iterators with visitation where applicable. If for
regular maps `iterator` and `const_iterator` provide mutable and const access to elements,
respectively, here visitation is granted mutable or const access depending on
the constness of the member function used (there are also `*cvisit` overloads for
Expand All @@ -145,6 +145,6 @@ explicit const visitation); In the case of `boost::concurrent_flat_set`, visitat
One notable operation not provided by `boost::concurrent_flat_map`/`boost::concurrent_node_map`
is `operator[]`/`at`, which can be
replaced, if in a more convoluted manner, by
xref:#concurrent_flat_map_try_emplace_or_cvisit[`try_emplace_or_visit`].
`xref:reference/concurrent_flat_map.adoc#concurrent_flat_map_try_emplace_or_cvisit[try_emplace_or_visit]`.

//-
24 changes: 12 additions & 12 deletions doc/modules/ROOT/pages/concurrent.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ On the other hand, a visitation function can _not_ access the container itself:

[source,c++]
----
m.visit(k, [&](const auto& x) {
m.visit(k, [&](const auto& x) {
some_function(x, m.size()); // forbidden: m can't be accessed inside visitation
});
----
Expand All @@ -105,7 +105,7 @@ outside of visitation may be beneficial:
[source,c++]
----
std::optional<value_type> o;
bool found = m.visit(k, [&](const auto& x) {
bool found = m.visit(k, [&](const auto& x) {
o = x;
});
if (found) {
Expand All @@ -118,7 +118,7 @@ many classical operations have visitation-enabled variations:

[source,c++]
----
m.insert_or_visit(x, [](auto& y) {
m.insert_or_visit(x, [](auto& y) {
// if insertion failed because of an equivalent element y,
// do something with it, for instance:
++y.second; // increment the mapped part of the element
Expand All @@ -141,19 +141,19 @@ element already exists):
[source,c++]
----
m.insert_and_cvisit(x,
[](const auto& y) {
std::cout<< "(" << y.first << ", " << y.second <<") inserted\n";
[](const auto& y) {
std::cout<< "(" << y.first << ", " << y.second <<") inserted\n";
},
[](const auto& y) {
std::cout<< "(" << y.first << ", " << y.second << ") already exists\n";
[](const auto& y) {
std::cout<< "(" << y.first << ", " << y.second << ") already exists\n";
});
----

Consult the references of
xref:#concurrent_node_set[`boost::concurrent_node_set`],
xref:#concurrent_flat_map[`boost::concurrent_node_map`],
xref:#concurrent_flat_set[`boost::concurrent_flat_set`] and
xref:#concurrent_flat_map[`boost::concurrent_flat_map`]
`xref:reference/concurrent_node_set#concurrent_node_set[boost::concurrent_node_set]`,
`xref:reference/concurrent_node_map#concurrent_flat_map[boost::concurrent_node_map]`,
`xref:reference/concurrent_flat_set#concurrent_flat_set[boost::concurrent_flat_set]` and
`xref:reference/concurrent_flat_map#concurrent_flat_map[boost::concurrent_flat_map]`
for the complete list of visitation-enabled operations.

== Whole-Table Visitation
Expand Down Expand Up @@ -237,7 +237,7 @@ m.visit(keys.begin(), keys.end(), [](auto& x) { ++x.second; });
This functionality is not provided for mere syntactic convenience, though: by processing all the
keys at once, some internal optimizations can be applied that increase
performance over the regular, one-at-a-time case (consult the
xref:#benchmarks_boostconcurrent_flat_map[benchmarks]). In fact, it may be beneficial
xref:benchmarks.adoc#benchmarks_boostconcurrent_flatnode_map[benchmarks]). In fact, it may be beneficial
to buffer incoming keys so that they can be bulk visited in chunks:

[source,c++]
Expand Down
6 changes: 3 additions & 3 deletions doc/modules/ROOT/pages/debuggability.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ You can load the pretty-printers externally from the non-embedded Python script.

=== Visualization structure

The visualizations mirror the standard unordered containers. The map containers display an association from key to mapped value. The set containers display an association from index to value. An iterator is either displayed with its item, or as an end iterator. Here is what may be shown for an example `boost::unordered_map`, an example `boost::unordered_set`, and their respective begin and end iterators.
The visualizations mirror the standard unordered containers. The map containers display an association from key to mapped value. The set containers display an association from index to value. An iterator is either displayed with its item, or as an end iterator. Here is what may be shown for an example `boost::unordered_map`, an example `boost::unordered_set`, and their respective begin and end iterators.

```plaintext
(gdb) print example_unordered_map
Expand All @@ -74,11 +74,11 @@ The other containers are identical other than replacing "`boost::unordered_{map|

Both the SIMD and the non-SIMD implementations are viewable through the GDB pretty-printers.

For open-addressing containers where xref:#hash_quality_container_statistics[container statistics] are enabled, you can obtain these statistics by calling `get_stats()` on the container, from within GDB. This is overridden in GDB as an link:https://sourceware.org/gdb/current/onlinedocs/gdb.html/Xmethod-API.html[xmethod], so it will not invoke any C++ synchronization code. See the following printout as an example for the expected format.
For open-addressing containers where xref:hash_quality.adoc#hash_quality_container_statistics[container statistics] are enabled, you can obtain these statistics by calling `get_stats()` on the container, from within GDB. This is overridden in GDB as an link:https://sourceware.org/gdb/current/onlinedocs/gdb.html/Xmethod-API.html[xmethod], so it will not invoke any C++ synchronization code. See the following printout as an example for the expected format.

```plaintext
(gdb) print example_flat_map.get_stats()
$1 = [stats] = {[insertion] = {[count] = 5, [probe_length] = {avg = 1.0, var = 0.0, dev = 0.0}},
$1 = [stats] = {[insertion] = {[count] = 5, [probe_length] = {avg = 1.0, var = 0.0, dev = 0.0}},
[successful_lookup] = {[count] = 0, [probe_length] = {avg = 0.0, var = 0.0, dev = 0.0},
[num_comparisons] = {avg = 0.0, var = 0.0, dev = 0.0}}, [unsuccessful_lookup] = {[count] = 5,
[probe_length] = {avg = 1.0, var = 0.0, dev = 0.0},
Expand Down
16 changes: 8 additions & 8 deletions doc/modules/ROOT/pages/hash_equality.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ elements are stored, the unordered associative containers use an equality
predicate and a hash function. For example, <<unordered_map,boost::unordered_map>>
is declared as:

```
```cpp
template <
class Key, class Mapped,
class Hash = boost::hash<Key>,
Expand All @@ -22,7 +22,7 @@ The hash function comes first as you might want to change the hash function
but not the equality predicate. For example, if you wanted to use the
https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash[FNV-1a hash^] you could write:

```
```cpp
boost::unordered_map<std::string, int, hash::fnv_1a>
dictionary;
```
Expand All @@ -31,7 +31,7 @@ There is an link:../../examples/fnv1.hpp[implementation of FNV-1a^] in the examp

If you wish to use a different equality function, you will also need to use a matching hash function. For example, to implement a case insensitive dictionary you need to define a case insensitive equality predicate and hash function:

```
```cpp
struct iequal_to
{
bool operator()(std::string const& x,
Expand Down Expand Up @@ -60,7 +60,7 @@ struct ihash
```

Which you can then use in a case insensitive dictionary:
```
```cpp
boost::unordered_map<std::string, int, ihash, iequal_to>
idictionary;
```
Expand All @@ -80,7 +80,7 @@ equality predicate (e.g. `boost::function`) then you can get into trouble.

Similarly, a custom hash function can be used for custom types:

```
```cpp
struct point {
int x;
int y;
Expand Down Expand Up @@ -108,7 +108,7 @@ boost::unordered_multiset<point, point_hash> points;
Since the default hash function is link:../../../container_hash/index.html[Boost.Hash^],
we can extend it to support the type so that the hash function doesn't need to be explicitly given:

```
```cpp
struct point {
int x;
int y;
Expand Down Expand Up @@ -140,10 +140,10 @@ you'll need to explicitly use Boost.Hash.
|===
|Method |Description

|`hasher hash_function() const`
|`hasher hash_function() const`
|Returns the container's hash function.

|`key_equal key_eq() const`
|`key_equal key_eq() const`
|Returns the container's key equality function..

|===
10 changes: 5 additions & 5 deletions doc/modules/ROOT/pages/hash_quality.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct my_string_hash_function
----

By setting the
xref:#hash_traits_hash_is_avalanching[hash_is_avalanching] trait, we inform Boost.Unordered
`xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]` trait, we inform Boost.Unordered
that `my_string_hash_function` is of sufficient quality to be used directly without
any post-mixing safety net. This comes at the risk of degraded performance in the
cases where the hash function is not as well-behaved as we've declared.
Expand Down Expand Up @@ -75,7 +75,7 @@ The `stats` object provides the following information:

[source,subs=+quotes]
----
stats
stats
.insertion // *Insertion operations*
.count // Number of operations
.probe_length // Probe length per operation
Expand All @@ -101,20 +101,20 @@ stats
.num_comparisons // Elements compared per operation
.average
.variance
.deviation
.deviation
----

Statistics for three internal operations are maintained: insertions (without considering
the previous lookup to determine that the key is not present yet), successful lookups,
and unsuccessful lookups (including those issued internally when inserting elements).
_Probe length_ is the number of
xref:#structures_open_addressing_containers[bucket groups] accessed per operation.
xref:structures.adoc#structures_open_addressing_containers[bucket groups] accessed per operation.
If the hash function behaves properly:

* Average probe lengths should be close to 1.0.
* The average number of comparisons per successful lookup should be close to 1.0 (that is,
just the element found is checked).
* The average number of comparisons per unsuccessful lookup should be close to 0.0.
* The average number of comparisons per unsuccessful lookup should be close to 0.0.

An link:../../benchmark/string_stats.cpp[example^] is provided that displays container
statistics for `boost::hash<std::string>`, an implementation of the
Expand Down
8 changes: 4 additions & 4 deletions doc/modules/ROOT/pages/intro.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ boost::unordered_multimap
^|

^.^h|*Open addressing*
^m| boost::unordered_node_set +
^m| boost::unordered_node_set +
boost::unordered_node_map
^m| boost::unordered_flat_set +
boost::unordered_flat_map
Expand All @@ -56,7 +56,7 @@ in the market within the technical constraints imposed by the required standard
* **Open-addressing containers** rely on much faster data structures and algorithms
(more than 2 times faster in typical scenarios) while slightly diverging from the standard
interface to accommodate the implementation.
There are two variants: **flat** (the fastest) and **node-based**, which
There are two variants: **flat** (the fastest) and **node-based**, which
provide pointer stability under rehashing at the expense of being slower.
* Finally, **concurrent containers** are designed and implemented to be used in high-performance
multithreaded scenarios. Their interface is radically different from that of regular C++ containers.
Expand All @@ -66,14 +66,14 @@ All sets and maps in Boost.Unordered are instantiatied similarly as
`std::unordered_set` and `std::unordered_map`, respectively:

[source,c++]
----
----
namespace boost {
template <
class Key,
class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<Key> >
class unordered_set;
class unordered_set;
// same for unordered_multiset, unordered_flat_set, unordered_node_set,
// concurrent_flat_set and concurrent_node_set
Expand Down
9 changes: 4 additions & 5 deletions doc/modules/ROOT/pages/rationale.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Since release 1.80.0, prime numbers are chosen for the number of buckets in
tandem with sophisticated modulo arithmetic. This removes the need for "mixing"
the result of the user's hash function as was used for release 1.79.0.

== Open-addresing Containers
== Open-addresing Containers

The C++ standard specification of unordered associative containers impose
severe limitations on permissible implementations, the most important being
Expand Down Expand Up @@ -129,15 +129,14 @@ concurrent scenarios.
* Open-addressing layouts are eminently suitable for concurrent access and modification
with minimal locking. In particular, the metadata array can be used for implementations of
lookup that are lock-free up to the last step of actual element comparison.
* Layout compatibility with Boost.Unordered flat containers allows for
xref:#concurrent_interoperability_with_non_concurrent_containers[fast transfer]
* Layout compatibility with Boost.Unordered flat containers allows for
xref:concurrent.adoc#concurrent_interoperability_with_non_concurrent_containers[fast transfer]
of all elements between a concurrent container and its non-concurrent counterpart,
and vice versa.

=== Hash Function and Platform Interoperability

Concurrent containers make the same decisions and provide the same guarantees
as Boost.Unordered open-addressing containers with regards to
as Boost.Unordered open-addressing containers with regards to
xref:#rationale_hash_function[hash function defaults] and
xref:#rationale_platform_interoperability[platform interoperability].

Loading

0 comments on commit db31da1

Please sign in to comment.