<?xml version="1.0" encoding="UTF-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
  <file original="NoName" source-language="en" datatype="plaintext" target-language="en">
    <body>
      <trans-unit xml:space="preserve" approved="no" id="5748d8033336c3ec" weblate-flags="read-only, safe-html, strict-same">
        <source>﻿[#concurrent] = Concurrent Containers</source>
        <target state="translated">﻿[#concurrent] = Concurrent Containers</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">1</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="ef65965422bc8357" weblate-flags="read-only, safe-html, strict-same">
        <source>:idprefix: concurrent_</source>
        <target state="translated">:idprefix: concurrent_</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">4</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="015a34750d9fc7ef" weblate-flags="read-only, safe-html, strict-same">
        <source>Boost.Unordered provides `boost::concurrent_node_set`, `boost::concurrent_node_map`, `boost::concurrent_flat_set` and `boost::concurrent_flat_map`, hash tables that allow concurrent write/read access from different threads without having to implement any synchronzation mechanism on the user's side.</source>
        <target state="translated">Boost.Unordered provides `boost::concurrent_node_set`, `boost::concurrent_node_map`, `boost::concurrent_flat_set` and `boost::concurrent_flat_map`, hash tables that allow concurrent write/read access from different threads without having to implement any synchronzation mechanism on the user's side.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">6</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="3312aa74822aad64" weblate-flags="read-only, safe-html, strict-same">
        <source>In the example above, threads access `m` without synchronization, just as we'd do in a single-threaded scenario. In an ideal setting, if a given workload is distributed among _N_ threads, execution is _N_ times faster than with one thread —this limit is never attained in practice due to synchronization overheads and _contention_ (one thread waiting for another to leave a locked portion of the map), but Boost.Unordered concurrent containers are designed to perform with very little overhead and typically achieve _linear scaling_ (that is, performance is proportional to the number of threads up to the number of logical cores in the CPU).</source>
        <target state="translated">In the example above, threads access `m` without synchronization, just as we'd do in a single-threaded scenario. In an ideal setting, if a given workload is distributed among _N_ threads, execution is _N_ times faster than with one thread —this limit is never attained in practice due to synchronization overheads and _contention_ (one thread waiting for another to leave a locked portion of the map), but Boost.Unordered concurrent containers are designed to perform with very little overhead and typically achieve _linear scaling_ (that is, performance is proportional to the number of threads up to the number of logical cores in the CPU).</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">36</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="d407f63bca85d422" weblate-flags="read-only, safe-html, strict-same">
        <source>Visitation-based API</source>
        <target state="translated">Visitation-based API</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">45</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="d6bb7c58e3cd13d7" weblate-flags="read-only, safe-html, strict-same">
        <source>The first thing a new user of Boost.Unordered concurrent containers will notice is that these classes _do not provide iterators_ (which makes them technically not https://en.cppreference.com/w/cpp/named_req/Container[Containers^] in the C++ standard sense). The reason for this is that iterators are inherently thread-unsafe. Consider this hypothetical code:</source>
        <target state="translated">The first thing a new user of Boost.Unordered concurrent containers will notice is that these classes _do not provide iterators_ (which makes them technically not https://en.cppreference.com/w/cpp/named_req/Container[Containers^] in the C++ standard sense). The reason for this is that iterators are inherently thread-unsafe. Consider this hypothetical code:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">47</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="7b3be7282595ae29" weblate-flags="read-only, safe-html, strict-same">
        <source>In a multithreaded scenario, the iterator `it` may be invalid at point B if some other thread issues an `m.erase(k)` operation between A and B. There are designs that can remedy this by making iterators lock the element they point to, but this approach lends itself to high contention and can easily produce deadlocks in a program. `operator[]` has similar concurrency issues, and is not provided by `boost::concurrent_flat_map`/`boost::concurrent_node_map` either. Instead, element access is done through so-called _visitation functions_:</source>
        <target state="translated">In a multithreaded scenario, the iterator `it` may be invalid at point B if some other thread issues an `m.erase(k)` operation between A and B. There are designs that can remedy this by making iterators lock the element they point to, but this approach lends itself to high contention and can easily produce deadlocks in a program. `operator[]` has similar concurrency issues, and is not provided by `boost::concurrent_flat_map`/`boost::concurrent_node_map` either. Instead, element access is done through so-called _visitation functions_:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">61</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="a1c158a917969669" weblate-flags="read-only, safe-html, strict-same">
        <source>The visitation function passed by the user (in this case, a lambda function) is executed internally by Boost.Unordered in a thread-safe manner, so it can access the element without worrying about other threads interfering in the process.</source>
        <target state="translated">The visitation function passed by the user (in this case, a lambda function) is executed internally by Boost.Unordered in a thread-safe manner, so it can access the element without worrying about other threads interfering in the process.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">76</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="3e749f5138fb2d08" weblate-flags="read-only, safe-html, strict-same">
        <source>On the other hand, a visitation function can _not_ access the container itself:</source>
        <target state="translated">On the other hand, a visitation function can _not_ access the container itself:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">81</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="159bb30b475802e1" weblate-flags="read-only, safe-html, strict-same">
        <source>Access to a different container is allowed, though:</source>
        <target state="translated">Access to a different container is allowed, though:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">90</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="d24414cb07746306" weblate-flags="read-only, safe-html, strict-same">
        <source>But, in general, visitation functions should be as lightweight as possible to reduce contention and increase parallelization. In some cases, moving heavy work outside of visitation may be beneficial:</source>
        <target state="translated">But, in general, visitation functions should be as lightweight as possible to reduce contention and increase parallelization. In some cases, moving heavy work outside of visitation may be beneficial:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">101</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="6c5ab3d27f0b0535" weblate-flags="read-only, safe-html, strict-same">
        <source>Visitation is prominent in the API provided by concurrent containers, and many classical operations have visitation-enabled variations:</source>
        <target state="translated">Visitation is prominent in the API provided by concurrent containers, and many classical operations have visitation-enabled variations:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">116</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="05cc089b290bbaab" weblate-flags="read-only, safe-html, strict-same">
        <source>Note that in this last example the visitation function could actually _modify_ the element: as a general rule, operations on a concurrent map `m` will grant visitation functions const/non-const access to  the element depending on whether `m` is const/non-const. Const access can be always be explicitly requested by using `cvisit` overloads (for instance, `insert_or_cvisit`) and may result in higher parallelization. For concurrent sets, on the other hand, visitation is always const access.</source>
        <target state="translated">Note that in this last example the visitation function could actually _modify_ the element: as a general rule, operations on a concurrent map `m` will grant visitation functions const/non-const access to  the element depending on whether `m` is const/non-const. Const access can be always be explicitly requested by using `cvisit` overloads (for instance, `insert_or_cvisit`) and may result in higher parallelization. For concurrent sets, on the other hand, visitation is always const access.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">128</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="0a00a91fd5461505" weblate-flags="read-only, safe-html, strict-same">
        <source>Although expected to be used much less frequently, concurrent containers also provide insertion operations where an element can be visited right after element creation (in addition to the usual visitation when an equivalent element already exists):</source>
        <target state="translated">Although expected to be used much less frequently, concurrent containers also provide insertion operations where an element can be visited right after element creation (in addition to the usual visitation when an equivalent element already exists):</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">136</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="063d002fc6fa404e" weblate-flags="read-only, safe-html, strict-same">
        <source>Consult the references of `xref:reference/concurrent_node_set.adoc#concurrent_node_set[boost::concurrent_node_set]`, `xref:reference/concurrent_node_map.adoc#concurrent_node_map[boost::concurrent_node_map]`, `xref:reference/concurrent_flat_set.adoc#concurrent_flat_set[boost::concurrent_flat_set]` and `xref:reference/concurrent_flat_map.adoc#concurrent_flat_map[boost::concurrent_flat_map]` for the complete list of visitation-enabled operations.</source>
        <target state="translated">Consult the references of `xref:reference/concurrent_node_set.adoc#concurrent_node_set[boost::concurrent_node_set]`, `xref:reference/concurrent_node_map.adoc#concurrent_node_map[boost::concurrent_node_map]`, `xref:reference/concurrent_flat_set.adoc#concurrent_flat_set[boost::concurrent_flat_set]` and `xref:reference/concurrent_flat_map.adoc#concurrent_flat_map[boost::concurrent_flat_map]` for the complete list of visitation-enabled operations.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">152</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="b0da8bb01671afb1" weblate-flags="read-only, safe-html, strict-same">
        <source>Whole-Table Visitation</source>
        <target state="translated">Whole-Table Visitation</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">159</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="12caabb34023fa34" weblate-flags="read-only, safe-html, strict-same">
        <source>In the absence of iterators, `visit_all` is provided as an alternative way to process all the elements in the container:</source>
        <target state="translated">In the absence of iterators, `visit_all` is provided as an alternative way to process all the elements in the container:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">161</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="575d6905b3e95b37" weblate-flags="read-only, safe-html, strict-same">
        <source>In C++17 compilers implementing standard parallel algorithms, whole-table visitation can be parallelized:</source>
        <target state="translated">In C++17 compilers implementing standard parallel algorithms, whole-table visitation can be parallelized:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">171</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="2f1b979ee7d721d6" weblate-flags="read-only, safe-html, strict-same">
        <source>Traversal can be interrupted midway:</source>
        <target state="translated">Traversal can be interrupted midway:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">181</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="4893867b9a9bf22b" weblate-flags="read-only, safe-html, strict-same">
        <source>There is one last whole-table visitation operation, `erase_if`:</source>
        <target state="translated">There is one last whole-table visitation operation, `erase_if`:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">202</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="3b19f5cd189f6590" weblate-flags="read-only, safe-html, strict-same">
        <source>`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 concurrent container at any point in your program.</source>
        <target state="translated">`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 concurrent container at any point in your program.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">211</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="ad452cf8cd06f25f" weblate-flags="read-only, safe-html, strict-same">
        <source>Bulk visitation</source>
        <target state="translated">Bulk visitation</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">217</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="4e731b0b563c7c34" weblate-flags="read-only, safe-html, strict-same">
        <source>Suppose you have an `std::array` of keys you want to look up for in a concurrent map:</source>
        <target state="translated">Suppose you have an `std::array` of keys you want to look up for in a concurrent map:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">219</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="1d5db2915d76d0b5" weblate-flags="read-only, safe-html, strict-same">
        <source>_Bulk visitation_ allows us to pass all the keys in one operation:</source>
        <target state="translated">_Bulk visitation_ allows us to pass all the keys in one operation:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">230</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="bf12663799d6fd90" weblate-flags="read-only, safe-html, strict-same">
        <source>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.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>
        <target state="translated">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.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:</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">237</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="598a25af4eace3ed" weblate-flags="read-only, safe-html, strict-same">
        <source>There's a latency/throughput tradeoff here: it will take longer for incoming keys to be processed (since they are buffered), but the number of processed keys per second is higher. `bulk_visit_size` is the recommended chunk size —smaller buffers may yield worse performance.</source>
        <target state="translated">There's a latency/throughput tradeoff here: it will take longer for incoming keys to be processed (since they are buffered), but the number of processed keys per second is higher. `bulk_visit_size` is the recommended chunk size —smaller buffers may yield worse performance.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">261</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="7fc360c3443bf6b9" weblate-flags="read-only, safe-html, strict-same">
        <source>Blocking Operations</source>
        <target state="translated">Blocking Operations</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">266</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="7f692b8a44b0e1f3" weblate-flags="read-only, safe-html, strict-same">
        <source>Concurrent containers can be copied, assigned, cleared and merged just like any other Boost.Unordered container. Unlike most other operations, these are _blocking_, that is, all other threads are prevented from accesing the tables involved while a copy, assignment, clear or merge operation is in progress. Blocking is taken care of automatically by the library and the user need not take any special precaution, but overall performance may be affected.</source>
        <target state="translated">Concurrent containers can be copied, assigned, cleared and merged just like any other Boost.Unordered container. Unlike most other operations, these are _blocking_, that is, all other threads are prevented from accesing the tables involved while a copy, assignment, clear or merge operation is in progress. Blocking is taken care of automatically by the library and the user need not take any special precaution, but overall performance may be affected.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">268</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="e0c220daf5c2fd80" weblate-flags="read-only, safe-html, strict-same">
        <source>Another blocking operation is _rehashing_, which happens explicitly via `rehash`/`reserve` or during insertion when the table's load hits `max_load()`. As with non-concurrent containers, reserving space in advance of bulk insertions will generally speed up the process.</source>
        <target state="translated">Another blocking operation is _rehashing_, which happens explicitly via `rehash`/`reserve` or during insertion when the table's load hits `max_load()`. As with non-concurrent containers, reserving space in advance of bulk insertions will generally speed up the process.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">274</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="1d29d8d5b2a28764" weblate-flags="read-only, safe-html, strict-same">
        <source>Interoperability with non-concurrent containers</source>
        <target state="translated">Interoperability with non-concurrent containers</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">278</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="f59ec4a086bdf68d" weblate-flags="read-only, safe-html, strict-same">
        <source>As open-addressing and concurrent containers are based on the same internal data structure, they can be efficiently move-constructed from their non-concurrent counterpart, and vice versa.</source>
        <target state="translated">As open-addressing and concurrent containers are based on the same internal data structure, they can be efficiently move-constructed from their non-concurrent counterpart, and vice versa.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">280</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="3e1e694b01366ef0" weblate-flags="read-only, safe-html, strict-same">
        <source>^|`boost::concurrent_node_set` ^|`boost::unordered_node_set`</source>
        <target state="translated">^|`boost::concurrent_node_set` ^|`boost::unordered_node_set`</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">286</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="92d09d7a3e2723dc" weblate-flags="read-only, safe-html, strict-same">
        <source>^|`boost::concurrent_node_map` ^|`boost::unordered_node_map`</source>
        <target state="translated">^|`boost::concurrent_node_map` ^|`boost::unordered_node_map`</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">289</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="9dc40a5d76914097" weblate-flags="read-only, safe-html, strict-same">
        <source>^|`boost::concurrent_flat_set` ^|`boost::unordered_flat_set`</source>
        <target state="translated">^|`boost::concurrent_flat_set` ^|`boost::unordered_flat_set`</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">292</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="d3a86a4b9007df60" weblate-flags="read-only, safe-html, strict-same">
        <source>^|`boost::concurrent_flat_map` ^|`boost::unordered_flat_map`</source>
        <target state="translated">^|`boost::concurrent_flat_map` ^|`boost::unordered_flat_map`</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">295</context>
        </context-group>
      </trans-unit>
      <trans-unit xml:space="preserve" approved="no" id="71c9d2623879650b" weblate-flags="read-only, safe-html, strict-same">
        <source>This interoperability comes handy in multistage scenarios where parts of the data processing happen in parallel whereas other steps are non-concurrent (or non-modifying). In the following example, we want to construct a histogram from a huge input vector of words: the population phase can be done in parallel with `boost::concurrent_flat_map` and results then transferred to the final container.</source>
        <target state="translated">This interoperability comes handy in multistage scenarios where parts of the data processing happen in parallel whereas other steps are non-concurrent (or non-modifying). In the following example, we want to construct a histogram from a huge input vector of words: the population phase can be done in parallel with `boost::concurrent_flat_map` and results then transferred to the final container.</target>
        <context-group name="" purpose="location">
          <context context-type="sourcefile"></context>
          <context context-type="linenumber">300</context>
        </context-group>
      </trans-unit>
    </body>
  </file>
</xliff>
