Full Code of rayon-rs/rayon for AI

main a6b82fca094b cached
218 files
1.3 MB
355.2k tokens
3282 symbols
1 requests
Download .txt
Showing preview only (1,375K chars total). Download the full file or copy to clipboard to get everything.
Repository: rayon-rs/rayon
Branch: main
Commit: a6b82fca094b
Files: 218
Total size: 1.3 MB

Directory structure:
gitextract_j0otbdne/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── ci.yaml
│       ├── main.yaml
│       └── pr.yaml
├── .gitignore
├── Cargo.toml
├── FAQ.md
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── RELEASES.md
├── ci/
│   ├── alt-core/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       └── lib.rs
│   ├── highlander/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   └── highlander.sh
├── rayon-core/
│   ├── Cargo.toml
│   ├── LICENSE-APACHE
│   ├── LICENSE-MIT
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── broadcast/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── compile_fail/
│   │   │   ├── mod.rs
│   │   │   ├── quicksort_race1.rs
│   │   │   ├── quicksort_race2.rs
│   │   │   ├── quicksort_race3.rs
│   │   │   ├── rc_return.rs
│   │   │   ├── rc_upvar.rs
│   │   │   └── scope_join_bad.rs
│   │   ├── job.rs
│   │   ├── join/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── latch.rs
│   │   ├── lib.rs
│   │   ├── private.rs
│   │   ├── registry.rs
│   │   ├── scope/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── sleep/
│   │   │   ├── README.md
│   │   │   ├── counters.rs
│   │   │   └── mod.rs
│   │   ├── spawn/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── test.rs
│   │   ├── thread_pool/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   └── unwind.rs
│   └── tests/
│       ├── double_init_fail.rs
│       ├── init_zero_threads.rs
│       ├── scope_join.rs
│       ├── scoped_threadpool.rs
│       ├── simple_panic.rs
│       ├── stack_overflow_crash.rs
│       └── use_current_thread.rs
├── rayon-demo/
│   ├── Cargo.toml
│   ├── data/
│   │   ├── README.md
│   │   └── tsp/
│   │       ├── README.md
│   │       ├── dj10.tsp
│   │       ├── dj15.tsp
│   │       └── dj38.tsp
│   ├── examples/
│   │   ├── README.md
│   │   └── cpu_monitor.rs
│   └── src/
│       ├── cpu_time/
│       │   ├── mod.rs
│       │   ├── unix.rs
│       │   └── win.rs
│       ├── factorial/
│       │   └── mod.rs
│       ├── fibonacci/
│       │   └── mod.rs
│       ├── find/
│       │   └── mod.rs
│       ├── join_microbench.rs
│       ├── lib.rs
│       ├── life/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── main.rs
│       ├── map_collect.rs
│       ├── matmul/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── mergesort/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── nbody/
│       │   ├── bench.rs
│       │   ├── mod.rs
│       │   ├── nbody.rs
│       │   └── visualize.rs
│       ├── noop/
│       │   └── mod.rs
│       ├── pythagoras/
│       │   └── mod.rs
│       ├── quicksort/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── sieve/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── sort.rs
│       ├── str_split.rs
│       ├── tree.rs
│       ├── tsp/
│       │   ├── bench.rs
│       │   ├── graph.rs
│       │   ├── mod.rs
│       │   ├── parser.rs
│       │   ├── solver.rs
│       │   ├── step.rs
│       │   ├── tour.rs
│       │   └── weight.rs
│       └── vec_collect.rs
├── src/
│   ├── array.rs
│   ├── collections/
│   │   ├── binary_heap.rs
│   │   ├── btree_map.rs
│   │   ├── btree_set.rs
│   │   ├── hash_map.rs
│   │   ├── hash_set.rs
│   │   ├── linked_list.rs
│   │   ├── mod.rs
│   │   └── vec_deque.rs
│   ├── compile_fail/
│   │   ├── cannot_collect_filtermap_data.rs
│   │   ├── cannot_zip_filtered_data.rs
│   │   ├── cell_par_iter.rs
│   │   ├── mod.rs
│   │   ├── must_use.rs
│   │   ├── no_send_par_iter.rs
│   │   └── rc_par_iter.rs
│   ├── delegate.rs
│   ├── iter/
│   │   ├── blocks.rs
│   │   ├── chain.rs
│   │   ├── chunks.rs
│   │   ├── cloned.rs
│   │   ├── collect/
│   │   │   ├── consumer.rs
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── copied.rs
│   │   ├── empty.rs
│   │   ├── enumerate.rs
│   │   ├── extend.rs
│   │   ├── filter.rs
│   │   ├── filter_map.rs
│   │   ├── find.rs
│   │   ├── find_first_last/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── flat_map.rs
│   │   ├── flat_map_iter.rs
│   │   ├── flatten.rs
│   │   ├── flatten_iter.rs
│   │   ├── fold.rs
│   │   ├── fold_chunks.rs
│   │   ├── fold_chunks_with.rs
│   │   ├── for_each.rs
│   │   ├── from_par_iter.rs
│   │   ├── inspect.rs
│   │   ├── interleave.rs
│   │   ├── interleave_shortest.rs
│   │   ├── intersperse.rs
│   │   ├── len.rs
│   │   ├── map.rs
│   │   ├── map_with.rs
│   │   ├── mod.rs
│   │   ├── multizip.rs
│   │   ├── noop.rs
│   │   ├── once.rs
│   │   ├── panic_fuse.rs
│   │   ├── par_bridge.rs
│   │   ├── plumbing/
│   │   │   ├── README.md
│   │   │   └── mod.rs
│   │   ├── positions.rs
│   │   ├── product.rs
│   │   ├── reduce.rs
│   │   ├── repeat.rs
│   │   ├── rev.rs
│   │   ├── skip.rs
│   │   ├── skip_any.rs
│   │   ├── skip_any_while.rs
│   │   ├── splitter.rs
│   │   ├── step_by.rs
│   │   ├── sum.rs
│   │   ├── take.rs
│   │   ├── take_any.rs
│   │   ├── take_any_while.rs
│   │   ├── test.rs
│   │   ├── try_fold.rs
│   │   ├── try_reduce.rs
│   │   ├── try_reduce_with.rs
│   │   ├── unzip.rs
│   │   ├── update.rs
│   │   ├── walk_tree.rs
│   │   ├── while_some.rs
│   │   ├── zip.rs
│   │   └── zip_eq.rs
│   ├── lib.rs
│   ├── math.rs
│   ├── option.rs
│   ├── par_either.rs
│   ├── prelude.rs
│   ├── private.rs
│   ├── range.rs
│   ├── range_inclusive.rs
│   ├── result.rs
│   ├── slice/
│   │   ├── chunk_by.rs
│   │   ├── chunks.rs
│   │   ├── mod.rs
│   │   ├── rchunks.rs
│   │   ├── sort.rs
│   │   └── test.rs
│   ├── split_producer.rs
│   ├── str.rs
│   ├── string.rs
│   └── vec.rs
└── tests/
    ├── chars.rs
    ├── clones.rs
    ├── collect.rs
    ├── cross-pool.rs
    ├── debug.rs
    ├── drain_vec.rs
    ├── intersperse.rs
    ├── issue671-unzip.rs
    ├── issue671.rs
    ├── iter_panic.rs
    ├── named-threads.rs
    ├── octillion.rs
    ├── par_bridge_recursion.rs
    ├── producer_split_at.rs
    ├── sort-panic-safe.rs
    └── str.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: cargo
    directory: /
    schedule:
      interval: monthly
    open-pull-requests-limit: 10
    update-types: major
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: monthly


================================================
FILE: .github/workflows/ci.yaml
================================================
name: CI
on: merge_group

jobs:

  check:
    name: Check (1.80.0)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@1.80.0
      - run: cp ci/compat-Cargo.lock ./Cargo.lock
      - run: cargo check --verbose --locked

  test:
    name: Test
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        rust: [stable, beta, nightly]
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}
      - run: cargo build --verbose
      - run: cargo test --verbose --package rayon
      - run: cargo test --verbose --package rayon-core
      - run: ./ci/highlander.sh

  # rayon-demo has huge dependencies, so limit its testing.
  # build on stable, test on nightly (because of #[bench])
  demo:
    name: Demo
    runs-on: ubuntu-latest
    strategy:
      matrix:
        rust: [stable, nightly]
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}
      - run: cargo build --verbose --package rayon-demo
      - run: cargo test --verbose --package rayon-demo
        if: matrix.rust == 'nightly'

  i686:
    name: Test (ubuntu-latest, stable-i686)
    runs-on: ubuntu-latest
    steps:
      - run: |
          sudo apt-get update
          sudo apt-get install gcc-multilib
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: i686-unknown-linux-gnu
      - run: cargo build --verbose --target i686-unknown-linux-gnu
      - run: cargo test --verbose --target i686-unknown-linux-gnu --package rayon
      - run: cargo test --verbose --target i686-unknown-linux-gnu --package rayon-core

  # wasm32-unknown-unknown builds, and even has the runtime fallback for
  # unsupported threading, but we don't have an environment to execute in.
  wasm:
    name: WebAssembly (standalone)
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - toolchain: stable
          - toolchain: nightly
            cargoflags: --features web_spin_lock
            rustflags: -C target-feature=+atomics,+bulk-memory,+mutable-globals
    env:
      RUSTFLAGS: ${{ matrix.rustflags }}
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.toolchain }}
          targets: wasm32-unknown-unknown
      - run: cargo build --verbose --target wasm32-unknown-unknown ${{ matrix.cargoflags }}

  # wasm32-wasip1 can test the fallback by running in wasmtime.
  wasi:
    name: WebAssembly (WASI)
    runs-on: ubuntu-latest
    env:
      CARGO_TARGET_WASM32_WASIP1_RUNNER: /home/runner/.wasmtime/bin/wasmtime
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: wasm32-wasip1
      - run: curl https://wasmtime.dev/install.sh -sSf | bash -s -- --version v35.0.0
      - run: cargo build --verbose --target wasm32-wasip1
      - run: cargo test --verbose --target wasm32-wasip1 --package rayon
      - run: cargo test --verbose --target wasm32-wasip1 --package rayon-core

  fmt:
    name: Format
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@1.80.0
        with:
          components: rustfmt
      - run: cargo fmt --all --check

  # One job that "summarizes" the success state of this pipeline. This can then be added to branch
  # protection, rather than having to add each job separately.
  success:
    name: Success
    runs-on: ubuntu-latest
    needs: [check, test, demo, i686, wasm, wasi, fmt]
    # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency
    # failed" as success. So we have to do some contortions to ensure the job fails if any of its
    # dependencies fails.
    if: always() # make sure this is never "skipped"
    steps:
      # Manually check the status of all dependencies. `if: failure()` does not work.
      - name: check if any dependency failed
        run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'


================================================
FILE: .github/workflows/main.yaml
================================================
name: main
on:
  push:
    branches:
      - main
  schedule:
    - cron: '0 0 * * 0' # 00:00 Sunday

jobs:

  test:
    name: Test (stable)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          profile: minimal
          override: true
      - run: cargo build --verbose
      - run: cargo test --verbose --package rayon
      - run: cargo test --verbose --package rayon-core
      - run: ./ci/highlander.sh


================================================
FILE: .github/workflows/pr.yaml
================================================
name: PR
on: pull_request

# Using 16MB stacks for deep test/debug recursion
env:
  RUST_MIN_STACK: 16777216

jobs:

  check:
    name: Check (1.80.0)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@1.80.0
      - run: cp ci/compat-Cargo.lock ./Cargo.lock
      - run: cargo check --verbose --locked

  test:
    name: Test (stable)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@stable
      - run: cargo build --verbose
      - run: cargo test --verbose --package rayon
      - run: cargo test --verbose --package rayon-core
      - run: ./ci/highlander.sh

  fmt:
    name: Format
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@1.80.0
        with:
          components: rustfmt
      - run: cargo fmt --all --check

  # One job that "summarizes" the success state of this pipeline. This can then be added to branch
  # protection, rather than having to add each job separately.
  success:
    name: Success
    runs-on: ubuntu-latest
    needs: [check, test, fmt]
    # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency
    # failed" as success. So we have to do some contortions to ensure the job fails if any of its
    # dependencies fails.
    if: always() # make sure this is never "skipped"
    steps:
      # Manually check the status of all dependencies. `if: failure()` does not work.
      - name: check if any dependency failed
        run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'


================================================
FILE: .gitignore
================================================
Cargo.lock
target
*~
TAGS
*.bk
.idea

================================================
FILE: Cargo.toml
================================================
[package]
name = "rayon"
version = "1.11.0"
description = "Simple work-stealing parallelism for Rust"
documentation = "https://docs.rs/rayon/"
exclude = ["/ci/*", "/.github/*"]

categories.workspace = true
edition.workspace = true
keywords.workspace = true
license.workspace = true
readme.workspace = true
repository.workspace = true
rust-version.workspace = true

[features]
# This feature switches to a spin-lock implementation on the browser's
# main thread to avoid the forbidden `atomics.wait`.
#
# Only useful on the `wasm32-unknown-unknown` target.
web_spin_lock = ["dep:wasm_sync", "rayon-core/web_spin_lock"]

[dependencies]
# These are both public dependencies!
rayon-core = { version = "1.13.0", path = "rayon-core" }
either.workspace = true

wasm_sync = { workspace = true, optional = true }

[dev-dependencies]
rand.workspace = true
rand_xorshift.workspace = true


[workspace]
members = ["rayon-demo", "rayon-core"]
exclude = ["ci"]

[workspace.package]
readme = "README.md"
rust-version = "1.80"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rayon-rs/rayon"
keywords = ["parallel", "thread", "concurrency", "join", "performance"]
categories = ["concurrency"]

# Some dependencies may not be their latest version, in order to support older rustc.
[workspace.dependencies]
crossbeam-deque = "0.8.1"
crossbeam-utils = "0.8.0"
either = { version = "1", default-features = false }
libc = "0.2"
rand = "0.9"
rand_xorshift = "0.4"
scoped-tls = "1.0"
wasm_sync = "0.1.0"


================================================
FILE: FAQ.md
================================================
# Rayon FAQ

This file is for general questions that don't fit into the README or crate docs.

## How many threads will Rayon spawn?

By default, Rayon uses the same number of threads as the number of CPUs
available. Note that on systems with hyperthreading enabled this equals the
number of logical cores and not the physical ones.

If you want to alter the number of threads spawned, you can set the
environmental variable `RAYON_NUM_THREADS` to the desired number of threads or
use the
[`ThreadPoolBuilder::build_global` function](https://docs.rs/rayon/*/rayon/struct.ThreadPoolBuilder.html#method.build_global)
method.

## How does Rayon balance work between threads?

Behind the scenes, Rayon uses a technique called **work stealing** to try and
dynamically ascertain how much parallelism is available and exploit it. The idea
is very simple: we always have a pool of worker threads available, waiting for
some work to do. When you call `join` the first time, we shift over into that
pool of threads. But if you call `join(a, b)` from a worker thread W, then W
will place `b` into its work queue, advertising that this is work that other
worker threads might help out with. W will then start executing `a`.

While W is busy with `a`, other threads might come along and take `b` from its
queue. That is called *stealing* `b`. Once `a` is done, W checks whether `b` was
stolen by another thread and, if not, executes `b` itself. If W runs out of jobs
in its own queue, it will look through the other threads' queues and try to
steal work from them.

This technique is not new. It was first introduced by the [Cilk project][cilk],
done at MIT in the late nineties. The name Rayon is an homage to that work.

[cilk]: http://supertech.csail.mit.edu/cilk/

## What should I do if I use `Rc`, `Cell`, `RefCell` or other non-Send-and-Sync types?

There are a number of non-threadsafe types in the Rust standard library, and if
your code is using them, you will not be able to combine it with Rayon.
Similarly, even if you don't have such types, but you try to have multiple
closures mutating the same state, you will get compilation errors; for example,
this function won't work, because both closures access `slice`:

```rust
/// Increment all values in slice.
fn increment_all(slice: &mut [i32]) {
    rayon::join(|| process(slice), || process(slice));
}
```

The correct way to resolve such errors will depend on the case. Some cases are
easy: for example, uses of [`Rc`] can typically be replaced with [`Arc`], which
is basically equivalent, but thread-safe.

Code that uses `Cell` or `RefCell`, however, can be somewhat more complicated.
If you can refactor your code to avoid those types, that is often the best way
forward, but otherwise, you can try to replace those types with their threadsafe
equivalents:

- `Cell` -- replacement: `AtomicUsize`, `AtomicBool`, etc
- `RefCell` -- replacement: `RwLock`, or perhaps `Mutex`

However, you have to be wary! The parallel versions of these types have
different atomicity guarantees. For example, with a `Cell`, you can increment a
counter like so:

```rust
let value = counter.get();
counter.set(value + 1);
```

But when you use the equivalent `AtomicUsize` methods, you are actually
introducing a potential race condition (not a data race, technically, but it can
be an awfully fine distinction):

```rust
let value = tscounter.load(Ordering::SeqCst);
tscounter.store(value + 1, Ordering::SeqCst);
```

You can already see that the `AtomicUsize` API is a bit more complex, as it
requires you to specify an
[ordering](https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html). (I
won't go into the details on ordering here, but suffice to say that if you don't
know what an ordering is, and probably even if you do, you should use
`Ordering::SeqCst`.) The danger in this parallel version of the counter is that
other threads might be running at the same time and they could cause our counter
to get out of sync. For example, if we have two threads, then they might both
execute the "load" before either has a chance to execute the "store":

```
Thread 1                                          Thread 2
let value = tscounter.load(Ordering::SeqCst);
// value = X                                      let value = tscounter.load(Ordering::SeqCst);
                                                  // value = X
tscounter.store(value+1);                         tscounter.store(value+1);
// tscounter = X+1                                // tscounter = X+1
```

Now even though we've had two increments, we'll only increase the counter by
one! Even though we've got no data race, this is still probably not the result
we wanted. The problem here is that the `Cell` API doesn't make clear the scope
of a "transaction" -- that is, the set of reads/writes that should occur
atomically. In this case, we probably wanted the get/set to occur together.

In fact, when using the `Atomic` types, you very rarely want a plain `load` or
plain `store`. You probably want the more complex operations. A counter, for
example, would use `fetch_add` to atomically load and increment the value in one
step. Compare-and-swap is another popular building block.

A similar problem can arise when converting `RefCell` to `RwLock`, but it is
somewhat less likely, because the `RefCell` API does in fact have a notion of a
transaction: the scope of the handle returned by `borrow` or `borrow_mut`. So if
you convert each call to `borrow` to `read` (and `borrow_mut` to `write`),
things will mostly work fine in a parallel setting, but there can still be
changes in behavior. Consider using a `handle: RefCell<Vec<i32>>` like:

```rust
let len = handle.borrow().len();
for i in 0 .. len {
    let data = handle.borrow()[i];
    println!("{}", data);
}
```

In sequential code, we know that this loop is safe. But if we convert this to
parallel code with an `RwLock`, we do not: this is because another thread could
come along and do `handle.write().unwrap().pop()`, and thus change the length of
the vector. In fact, even in *sequential* code, using very small borrow sections
like this is an anti-pattern: you ought to be enclosing the entire transaction
together, like so:

```rust
let vec = handle.borrow();
let len = vec.len();
for i in 0 .. len {
    let data = vec[i];
    println!("{}", data);
}
```

Or, even better, using an iterator instead of indexing:

```rust
let vec = handle.borrow();
for data in vec {
    println!("{}", data);
}
```

There are several reasons to prefer one borrow over many. The most obvious is
that it is more efficient, since each borrow has to perform some safety checks.
But it's also more reliable: suppose we modified the loop above to not just
print things out, but also call into a helper function:

```rust
let vec = handle.borrow();
for data in vec {
    helper(...);
}
```

And now suppose, independently, this helper fn evolved and had to pop something
off of the vector:

```rust
fn helper(...) {
    handle.borrow_mut().pop();
}
```

Under the old model, where we did lots of small borrows, this would yield
precisely the same error that we saw in parallel land using an `RwLock`: the
length would be out of sync and our indexing would fail (note that in neither
case would there be an actual *data race* and hence there would never be
undefined behavior). But now that we use a single borrow, we'll see a borrow
error instead, which is much easier to diagnose, since it occurs at the point of
the `borrow_mut`, rather than downstream. Similarly, if we move to an `RwLock`,
we'll find that the code either deadlocks (if the write is on the same thread as
the read) or, if the write is on another thread, works just fine. Both of these
are preferable to random failures in my experience.

## But wait, isn't Rust supposed to free me from this kind of thinking?

You might think that Rust is supposed to mean that you don't have to think about
atomicity at all. In fact, if you avoid interior mutability (`Cell` and
`RefCell` in a sequential setting, or `AtomicUsize`, `RwLock`, `Mutex`, et al.
in parallel code), then this is true: the type system will basically guarantee
that you don't have to think about atomicity at all. But often there are times
when you WANT threads to interleave in the ways I showed above.

Consider for example when you are conducting a search in parallel, say to find
the shortest route. To avoid fruitless search, you might want to keep a cell
with the shortest route you've found thus far. This way, when you are searching
down some path that's already longer than this shortest route, you can just stop
and avoid wasted effort. In sequential land, you might model this "best result"
as a shared value like `Rc<Cell<usize>>` (here the `usize` represents the length
of best path found so far); in parallel land, you'd use a `Arc<AtomicUsize>`.

```rust
fn search(path: &Path, cost_so_far: usize, best_cost: &AtomicUsize) {
    if cost_so_far >= best_cost.load(Ordering::SeqCst) {
        return;
    }
    // Using `fetch_min` to avoid a race condition, in case it changed since `load`.
    best_cost.fetch_min(..., Ordering::SeqCst);
}
```

Now in this case, we really WANT to see results from other threads interjected
into our execution!


================================================
FILE: LICENSE-APACHE
================================================
                              Apache License
                        Version 2.0, January 2004
                     http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

   "License" shall mean the terms and conditions for use, reproduction,
   and distribution as defined by Sections 1 through 9 of this document.

   "Licensor" shall mean the copyright owner or entity authorized by
   the copyright owner that is granting the License.

   "Legal Entity" shall mean the union of the acting entity and all
   other entities that control, are controlled by, or are under common
   control with that entity. For the purposes of this definition,
   "control" means (i) the power, direct or indirect, to cause the
   direction or management of such entity, whether by contract or
   otherwise, or (ii) ownership of fifty percent (50%) or more of the
   outstanding shares, or (iii) beneficial ownership of such entity.

   "You" (or "Your") shall mean an individual or Legal Entity
   exercising permissions granted by this License.

   "Source" form shall mean the preferred form for making modifications,
   including but not limited to software source code, documentation
   source, and configuration files.

   "Object" form shall mean any form resulting from mechanical
   transformation or translation of a Source form, including but
   not limited to compiled object code, generated documentation,
   and conversions to other media types.

   "Work" shall mean the work of authorship, whether in Source or
   Object form, made available under the License, as indicated by a
   copyright notice that is included in or attached to the work
   (an example is provided in the Appendix below).

   "Derivative Works" shall mean any work, whether in Source or Object
   form, that is based on (or derived from) the Work and for which the
   editorial revisions, annotations, elaborations, or other modifications
   represent, as a whole, an original work of authorship. For the purposes
   of this License, Derivative Works shall not include works that remain
   separable from, or merely link (or bind by name) to the interfaces of,
   the Work and Derivative Works thereof.

   "Contribution" shall mean any work of authorship, including
   the original version of the Work and any modifications or additions
   to that Work or Derivative Works thereof, that is intentionally
   submitted to Licensor for inclusion in the Work by the copyright owner
   or by an individual or Legal Entity authorized to submit on behalf of
   the copyright owner. For the purposes of this definition, "submitted"
   means any form of electronic, verbal, or written communication sent
   to the Licensor or its representatives, including but not limited to
   communication on electronic mailing lists, source code control systems,
   and issue tracking systems that are managed by, or on behalf of, the
   Licensor for the purpose of discussing and improving the Work, but
   excluding communication that is conspicuously marked or otherwise
   designated in writing by the copyright owner as "Not a Contribution."

   "Contributor" shall mean Licensor and any individual or Legal Entity
   on behalf of whom a Contribution has been received by Licensor and
   subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   copyright license to reproduce, prepare Derivative Works of,
   publicly display, publicly perform, sublicense, and distribute the
   Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   (except as stated in this section) patent license to make, have made,
   use, offer to sell, sell, import, and otherwise transfer the Work,
   where such license applies only to those patent claims licensable
   by such Contributor that are necessarily infringed by their
   Contribution(s) alone or by combination of their Contribution(s)
   with the Work to which such Contribution(s) was submitted. If You
   institute patent litigation against any entity (including a
   cross-claim or counterclaim in a lawsuit) alleging that the Work
   or a Contribution incorporated within the Work constitutes direct
   or contributory patent infringement, then any patent licenses
   granted to You under this License for that Work shall terminate
   as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
   Work or Derivative Works thereof in any medium, with or without
   modifications, and in Source or Object form, provided that You
   meet the following conditions:

   (a) You must give any other recipients of the Work or
       Derivative Works a copy of this License; and

   (b) You must cause any modified files to carry prominent notices
       stating that You changed the files; and

   (c) You must retain, in the Source form of any Derivative Works
       that You distribute, all copyright, patent, trademark, and
       attribution notices from the Source form of the Work,
       excluding those notices that do not pertain to any part of
       the Derivative Works; and

   (d) If the Work includes a "NOTICE" text file as part of its
       distribution, then any Derivative Works that You distribute must
       include a readable copy of the attribution notices contained
       within such NOTICE file, excluding those notices that do not
       pertain to any part of the Derivative Works, in at least one
       of the following places: within a NOTICE text file distributed
       as part of the Derivative Works; within the Source form or
       documentation, if provided along with the Derivative Works; or,
       within a display generated by the Derivative Works, if and
       wherever such third-party notices normally appear. The contents
       of the NOTICE file are for informational purposes only and
       do not modify the License. You may add Your own attribution
       notices within Derivative Works that You distribute, alongside
       or as an addendum to the NOTICE text from the Work, provided
       that such additional attribution notices cannot be construed
       as modifying the License.

   You may add Your own copyright statement to Your modifications and
   may provide additional or different license terms and conditions
   for use, reproduction, or distribution of Your modifications, or
   for any such Derivative Works as a whole, provided Your use,
   reproduction, and distribution of the Work otherwise complies with
   the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
   names, trademarks, service marks, or product names of the Licensor,
   except as required for reasonable and customary use in describing the
   origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
   agreed to in writing, Licensor provides the Work (and each
   Contributor provides its Contributions) on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied, including, without limitation, any warranties or conditions
   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
   PARTICULAR PURPOSE. You are solely responsible for determining the
   appropriateness of using or redistributing the Work and assume any
   risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
   whether in tort (including negligence), contract, or otherwise,
   unless required by applicable law (such as deliberate and grossly
   negligent acts) or agreed to in writing, shall any Contributor be
   liable to You for damages, including any direct, indirect, special,
   incidental, or consequential damages of any character arising as a
   result of this License or out of the use or inability to use the
   Work (including but not limited to damages for loss of goodwill,
   work stoppage, computer failure or malfunction, or any and all
   other commercial damages or losses), even if such Contributor
   has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
   the Work or Derivative Works thereof, You may choose to offer,
   and charge a fee for, acceptance of support, warranty, indemnity,
   or other liability obligations and/or rights consistent with this
   License. However, in accepting such obligations, You may act only
   on Your own behalf and on Your sole responsibility, not on behalf
   of any other Contributor, and only if You agree to indemnify,
   defend, and hold each Contributor harmless for any liability
   incurred by, or claims asserted against, such Contributor by reason
   of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

   To apply the Apache License to your work, attach the following
   boilerplate notice, with the fields enclosed by brackets "[]"
   replaced with your own identifying information. (Don't include
   the brackets!)  The text should be enclosed in the appropriate
   comment syntax for the file format. We also recommend that a
   file or class name and description of purpose be included on the
   same "printed page" as the copyright notice for easier
   identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

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

	http://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.


================================================
FILE: LICENSE-MIT
================================================
Copyright (c) 2010 The Rust Project Developers

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# Rayon

[![Rayon crate](https://img.shields.io/crates/v/rayon.svg)](https://crates.io/crates/rayon)
[![Rayon documentation](https://docs.rs/rayon/badge.svg)](https://docs.rs/rayon)
![minimum rustc 1.80](https://img.shields.io/badge/rustc-1.80+-red.svg)
[![build status](https://github.com/rayon-rs/rayon/workflows/main/badge.svg)](https://github.com/rayon-rs/rayon/actions)

Rayon is a data-parallelism library for Rust. It is extremely
lightweight and makes it easy to convert a sequential computation into
a parallel one. It also guarantees data-race freedom. (You may also
enjoy [this blog post][blog] about Rayon, which gives more background
and details about how it works, or [this video][video], from the Rust
Belt Rust conference.) Rayon is
[available on crates.io](https://crates.io/crates/rayon), and
[API documentation is available on docs.rs](https://docs.rs/rayon).

[blog]: https://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/
[video]: https://www.youtube.com/watch?v=gof_OEv71Aw

## Parallel iterators and more

Rayon makes it drop-dead simple to convert sequential iterators into
parallel ones: usually, you just change your `foo.iter()` call into
`foo.par_iter()`, and Rayon does the rest:

```rust
use rayon::prelude::*;
fn sum_of_squares(input: &[i32]) -> i32 {
    input.par_iter() // <-- just change that!
         .map(|&i| i * i)
         .sum()
}
```

[Parallel iterators] take care of deciding how to divide your data
into tasks; it will dynamically adapt for maximum performance. If you
need more flexibility than that, Rayon also offers the [join] and
[scope] functions, which let you create parallel tasks on your own.
For even more control, you can create [custom thread pools] rather than
using Rayon's default, global thread pool.

[Parallel iterators]: https://docs.rs/rayon/*/rayon/iter/index.html
[join]: https://docs.rs/rayon/*/rayon/fn.join.html
[scope]: https://docs.rs/rayon/*/rayon/fn.scope.html
[custom thread pools]: https://docs.rs/rayon/*/rayon/struct.ThreadPool.html

## No data races

You may have heard that parallel execution can produce all kinds of
crazy bugs. Well, rest easy. Rayon's APIs all guarantee **data-race
freedom**, which generally rules out most parallel bugs (though not
all). In other words, **if your code compiles**, it typically does the
same thing it did before.

For the most, parallel iterators in particular are guaranteed to
produce the same results as their sequential counterparts. One caveat:
If your iterator has side effects (for example, sending methods to
other threads through a [Rust channel] or writing to disk), those side
effects may occur in a different order. Note also that, in some cases,
parallel iterators offer alternative versions of the sequential
iterator methods that can have higher performance.

[Rust channel]: https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html

## Using Rayon

[Rayon is available on crates.io](https://crates.io/crates/rayon). The
recommended way to use it is to add a line into your Cargo.toml such
as:

```toml
[dependencies]
rayon = "1.11"
```

To use the parallel iterator APIs, a number of traits have to be in
scope. The easiest way to bring those things into scope is to use the
[Rayon prelude](https://docs.rs/rayon/*/rayon/prelude/index.html). In
each module where you would like to use the parallel iterator APIs,
just add:

```rust
use rayon::prelude::*;
```

Rayon currently requires `rustc 1.80.0` or greater.

### Usage with WebAssembly

By default, when building to WebAssembly, Rayon will treat it as any
other platform without multithreading support and will fall back to
sequential iteration. This allows existing code to compile and run
successfully with no changes necessary, but it will run slower as it
will only use a single CPU core.

You can build Rayon-based projects with proper multithreading support
for the Web, but you'll need an adapter and some project configuration
to account for differences between WebAssembly threads and threads on
the other platforms.

Check out the
[wasm-bindgen-rayon](https://github.com/RReverser/wasm-bindgen-rayon)
docs for more details.

## Contribution

Rayon is an open source project! If you'd like to contribute to Rayon,
check out
[the list of "help wanted" issues](https://github.com/rayon-rs/rayon/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).
These are all (or should be) issues that are suitable for getting
started, and they generally include a detailed set of instructions for
what to do. Please ask questions if anything is unclear! Also, check
out the
[Guide to Development](https://github.com/rayon-rs/rayon/wiki/Guide-to-Development)
page on the wiki. Note that all code submitted in PRs to Rayon is
assumed to
[be licensed under Rayon's dual MIT/Apache 2.0 licensing](https://github.com/rayon-rs/rayon/blob/main/README.md#license).

## Quick demo

To see Rayon in action, check out the `rayon-demo` directory, which
includes a number of demos of code using Rayon. For example, run this
command to get a visualization of an N-body simulation. To see the
effect of using Rayon, press `s` to run sequentially and `p` to run in
parallel.

```text
> cd rayon-demo
> cargo run --release -- nbody visualize
```

For more information on demos, try:

```text
> cd rayon-demo
> cargo run --release -- --help
```

## Other questions?

See [the Rayon FAQ][faq].

[faq]: https://github.com/rayon-rs/rayon/blob/main/FAQ.md

## License

Rayon is distributed under the terms of both the MIT license and the
Apache License (Version 2.0). See [LICENSE-APACHE](LICENSE-APACHE) and
[LICENSE-MIT](LICENSE-MIT) for details. Opening a pull request is
assumed to signal agreement with these licensing terms.


================================================
FILE: RELEASES.md
================================================
# Release rayon 1.11.0 / rayon-core 1.13.0 (2025-08-12)

- The minimum supported `rustc` is now 1.80.
- `iter::repeatn` has been renamed to `iter::repeat_n` to match the name
  stabilized in the standard library. The old name still exists as a deprecated
  function for compatibility.
- Fixed a bug in `in_place_scope` when the default global registry uses the
  current thread, like on WebAssembly without threading support.
- `binary_heap::Iter` no longer requires a temporary allocation.
- Relaxed trait bounds on many of the public structs.
- Implemented `IntoParallelIterator for Box<[T]>` and its references.
- Implemented `FromParallelIterator<_> for Box<str>` via `String`.

# Release rayon 1.10.0 (2024-03-23)

- The new methods `ParallelSlice::par_chunk_by` and
  `ParallelSliceMut::par_chunk_by_mut` work like the slice methods `chunk_by`
  and `chunk_by_mut` added in Rust 1.77.

# Release rayon 1.9.0 (2024-02-27)

- The new methods `IndexedParallelIterator::by_exponential_blocks` and
  `by_uniform_blocks` allow processing items in smaller groups at a time.
- The new `iter::walk_tree`, `walk_tree_prefix`, and `walk_tree_postfix`
  functions enable custom parallel iteration over tree-like structures.
- The new method `ParallelIterator::collect_vec_list` returns items as a linked
  list of vectors, which is an efficient mode of parallel collection used by
  many of the internal implementations of `collect`.
- The new methods `ParallelSliceMut::par_split_inclusive_mut`,
  `ParallelSlice::par_split_inclusive`, and
  `ParallelString::par_split_inclusive` all work like a normal split but
  keeping the separator as part of the left slice.
- The new `ParallelString::par_split_ascii_whitespace` splits only on ASCII
  whitespace, which is faster than including Unicode multi-byte whitespace.
- `OsString` now implements `FromParallelIterator<_>` and `ParallelExtend<_>`
  for a few item types similar to the standard `FromIterator` and `Extend`.
- The internal `Pattern` trait for string methods is now implemented for
  `[char; N]` and `&[char; N]`, matching any of the given characters.

# Release rayon 1.8.1 / rayon-core 1.12.1 (2024-01-17)

- The new `"web_spin_lock"` crate feature makes mutexes spin on the main
  browser thread in WebAssembly, rather than suffer an error about forbidden
  `atomics.wait` if they were to block in that context. Thanks @RReverser!

# Release rayon 1.8.0 / rayon-core 1.12.0 (2023-09-20)

- The minimum supported `rustc` is now 1.63.
- Added `ThreadPoolBuilder::use_current_thread` to use the builder thread as
  part of the new thread pool. That thread does not run the pool's main loop,
  but it may participate in work-stealing if it yields to rayon in some way.
- Implemented `FromParallelIterator<T>` for `Box<[T]>`, `Rc<[T]>`, and
  `Arc<[T]>`, as well as `FromParallelIterator<Box<str>>` and
  `ParallelExtend<Box<str>>` for `String`.
- `ThreadPoolBuilder::build_scoped` now uses `std::thread::scope`.
- The default number of threads is now determined using
  `std::thread::available_parallelism` instead of the `num_cpus` crate.
- The internal logging facility has been removed, reducing bloat for all users.
- Many smaller performance tweaks and documentation updates.

# Release rayon 1.7.0 / rayon-core 1.11.0 (2023-03-03)

- The minimum supported `rustc` is now 1.59.
- Added a fallback when threading is unsupported.
- The new `ParallelIterator::take_any` and `skip_any` methods work like
  unordered `IndexedParallelIterator::take` and `skip`, counting items in
  whatever order they are visited in parallel.
- The new `ParallelIterator::take_any_while` and `skip_any_while` methods work
  like unordered `Iterator::take_while` and `skip_while`, which previously had
  no parallel equivalent. The "while" condition may be satisfied from anywhere
  in the parallel iterator, affecting all future items regardless of position.
- The new `yield_now` and `yield_local` functions will cooperatively yield
  execution to Rayon, either trying to execute pending work from the entire
  pool or from just the local deques of the current thread, respectively.

# Release rayon-core 1.10.2 (2023-01-22)

- Fixed miri-reported UB for SharedReadOnly tags protected by a call.

# Release rayon 1.6.1 (2022-12-09)

- Simplified `par_bridge` to only pull one item at a time from the iterator,
  without batching. Threads that are waiting for iterator items will now block
  appropriately rather than spinning CPU. (Thanks @njaard!)
- Added protection against recursion in `par_bridge`, so iterators that also
  invoke rayon will not cause mutex recursion deadlocks.

# Release rayon-core 1.10.1 (2022-11-18)

- Fixed a race condition with threads going to sleep while a broadcast starts.

# Release rayon 1.6.0 / rayon-core 1.10.0 (2022-11-18)

- The minimum supported `rustc` is now 1.56.
- The new `IndexedParallelIterator::fold_chunks` and `fold_chunks_with` methods
  work like `ParallelIterator::fold` and `fold_with` with fixed-size chunks of
  items. This may be useful for predictable batching performance, without the
  allocation overhead of `IndexedParallelIterator::chunks`.
- New "broadcast" methods run a given function on all threads in the pool.
  These run at a sort of reduced priority after each thread has exhausted their
  local work queue, but before they attempt work-stealing from other threads.
  - The global `broadcast` function and `ThreadPool::broadcast` method will
    block until completion, returning a `Vec` of all return values.
  - The global `spawn_broadcast` function and methods on `ThreadPool`, `Scope`,
    and `ScopeFifo` will run detached, without blocking the current thread.
- Panicking methods now use `#[track_caller]` to report the caller's location.
- Fixed a truncated length in `vec::Drain` when given an empty range.

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @idanmuze
- @JoeyBF
- @JustForFun88
- @kianmeng
- @kornelski
- @ritchie46
- @ryanrussell
- @steffahn
- @TheIronBorn
- @willcrozi

# Release rayon 1.5.3 (2022-05-13)

- The new `ParallelSliceMut::par_sort_by_cached_key` is a stable sort that caches
  the keys for each item -- a parallel version of `slice::sort_by_cached_key`.

# Release rayon-core 1.9.3 (2022-05-13)

- Fixed a use-after-free race in job notification.

# Release rayon 1.5.2 / rayon-core 1.9.2 (2022-04-13)

- The new `ParallelSlice::par_rchunks()` and `par_rchunks_exact()` iterate
  slice chunks in reverse, aligned the against the end of the slice if the
  length is not a perfect multiple of the chunk size. The new
  `ParallelSliceMut::par_rchunks_mut()` and `par_rchunks_exact_mut()` are the
  same for mutable slices.
- The `ParallelIterator::try_*` methods now support `std::ops::ControlFlow` and
  `std::task::Poll` items, mirroring the unstable `Try` implementations in the
  standard library.
- The `ParallelString` pattern-based methods now support `&[char]` patterns,
  which match when any character in that slice is found in the string.
- A soft limit is now enforced on the number of threads allowed in a single
  thread pool, respecting internal bit limits that already existed. The current
  maximum is publicly available from the new function `max_num_threads()`.
- Fixed several Stacked Borrow and provenance issues found by `cargo miri`.

## Contributors

Thanks to all of the contributors for this release!

- @atouchet
- @bluss
- @cuviper
- @fzyzcjy
- @nyanzebra
- @paolobarbolini
- @RReverser
- @saethlin

# Release rayon 1.5.1 / rayon-core 1.9.1 (2021-05-18)

- The new `in_place_scope` and `in_place_scope_fifo` are variations of `scope`
  and `scope_fifo`, running the initial non-`Send` callback directly on the
  current thread, rather than moving execution to the thread pool.
- With Rust 1.51 or later, arrays now implement `IntoParallelIterator`.
- New implementations of `FromParallelIterator` make it possible to `collect`
  complicated nestings of items.
  - `FromParallelIterator<(A, B)> for (FromA, FromB)` works like `unzip`.
  - `FromParallelIterator<Either<L, R>> for (A, B)` works like `partition_map`.
- Type inference now works better with parallel `Range` and `RangeInclusive`.
- The implementation of `FromParallelIterator` and `ParallelExtend` for
  `Vec<T>` now uses `MaybeUninit<T>` internally to avoid creating any
  references to uninitialized data.
- `ParallelBridge` fixed a bug with threads missing available work.

## Contributors

Thanks to all of the contributors for this release!

- @atouchet
- @cuviper
- @Hywan
- @iRaiko
- @Qwaz
- @rocallahan

# Release rayon 1.5.0 / rayon-core 1.9.0 (2020-10-21)

- Update crossbeam dependencies.
- The minimum supported `rustc` is now 1.36.

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @mbrubeck
- @mrksu

# Release rayon 1.4.1 (2020-09-29)

- The new `flat_map_iter` and `flatten_iter` methods can be used to flatten
  sequential iterators, which may perform better in cases that don't need the
  nested parallelism of `flat_map` and `flatten`.
- The new `par_drain` method is a parallel version of the standard `drain` for
  collections, removing items while keeping the original capacity. Collections
  that implement this through `ParallelDrainRange` support draining items from
  arbitrary index ranges, while `ParallelDrainFull` always drains everything.
- The new `positions` method finds all items that match the given predicate and
  returns their indices in a new iterator.

# Release rayon-core 1.8.1 (2020-09-17)

- Fixed an overflow panic on high-contention workloads, for a counter that was
  meant to simply wrap. This panic only occurred with debug assertions enabled,
  and was much more likely on 32-bit targets.

# Release rayon 1.4.0 / rayon-core 1.8.0 (2020-08-24)

- Implemented a new thread scheduler, [RFC 5], which uses targeted wakeups for
  new work and for notifications of completed stolen work, reducing wasteful
  CPU usage in idle threads.
- Implemented `IntoParallelIterator for Range<char>` and `RangeInclusive<char>`
  with the same iteration semantics as Rust 1.45.
- Relaxed the lifetime requirements of the initial `scope` closure.

[RFC 5]: https://github.com/rayon-rs/rfcs/pull/5

## Contributors

Thanks to all of the contributors for this release!

- @CAD97
- @cuviper
- @kmaork
- @nikomatsakis
- @SuperFluffy


# Release rayon 1.3.1 / rayon-core 1.7.1 (2020-06-15)

- Fixed a use-after-free race in calls blocked between two rayon thread pools.
- Collecting to an indexed `Vec` now drops any partial writes while unwinding,
  rather than just leaking them. If dropping also panics, Rust will abort.
  - Note: the old leaking behavior is considered _safe_, just not ideal.
- The new `IndexedParallelIterator::step_by()` adapts an iterator to step
  through items by the given count, like `Iterator::step_by()`.
- The new `ParallelSlice::par_chunks_exact()` and mutable equivalent
  `ParallelSliceMut::par_chunks_exact_mut()` ensure that the chunks always have
  the exact length requested, leaving any remainder separate, like the slice
  methods `chunks_exact()` and `chunks_exact_mut()`.

## Contributors

Thanks to all of the contributors for this release!

- @adrian5
- @bluss
- @cuviper
- @FlyingCanoe
- @GuillaumeGomez
- @matthiasbeyer
- @picoHz
- @zesterer


# Release rayon 1.3.0 / rayon-core 1.7.0 (2019-12-21)

- Tuples up to length 12 now implement `IntoParallelIterator`, creating a
  `MultiZip` iterator that produces items as similarly-shaped tuples.
- The `--cfg=rayon_unstable` supporting code for `rayon-futures` is removed.
- The minimum supported `rustc` is now 1.31.

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @c410-f3r
- @silwol


# Release rayon-futures 0.1.1 (2019-12-21)

- `Send` bounds have been added for the `Item` and `Error` associated types on
  all generic `F: Future` interfaces. While technically a breaking change, this
  is a soundness fix, so we are not increasing the semantic version for this.
- This crate is now deprecated, and the `--cfg=rayon_unstable` supporting code
  will be removed in `rayon-core 1.7.0`. This only supported the now-obsolete
  `Future` from `futures 0.1`, while support for `std::future::Future` is
  expected to come directly in `rayon-core` -- although that is not ready yet.

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @kornelski
- @jClaireCodesStuff
- @jwass
- @seanchen1991


# Release rayon 1.2.1 / rayon-core 1.6.1 (2019-11-20)

- Update crossbeam dependencies.
- Add top-level doc links for the iterator traits.
- Document that the iterator traits are not object safe.

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @dnaka91
- @matklad
- @nikomatsakis
- @Qqwy
- @vorner


# Release rayon 1.2.0 / rayon-core 1.6.0 (2019-08-30)

- The new `ParallelIterator::copied()` converts an iterator of references into
  copied values, like `Iterator::copied()`.
- `ParallelExtend` is now implemented for the unit `()`.
- Internal updates were made to improve test determinism, reduce closure type
  sizes, reduce task allocations, and update dependencies.
- The minimum supported `rustc` is now 1.28.

## Contributors

Thanks to all of the contributors for this release!

- @Aaron1011
- @cuviper
- @ralfbiedert


# Release rayon 1.1.0 / rayon-core 1.5.0 (2019-06-12)

- FIFO spawns are now supported using the new `spawn_fifo()` and `scope_fifo()`
  global functions, and their corresponding `ThreadPool` methods.
  - Normally when tasks are queued on a thread, the most recent is processed
    first (LIFO) while other threads will steal the oldest (FIFO). With FIFO
    spawns, those tasks are processed locally in FIFO order too.
  - Regular spawns and other tasks like `join` are not affected.
  - The `breadth_first` configuration flag, which globally approximated this
    effect, is now deprecated.
  - For more design details, please see [RFC 1].
- `ThreadPoolBuilder` can now take a custom `spawn_handler` to control how
  threads will be created in the pool.
  - `ThreadPoolBuilder::build_scoped()` uses this to create a scoped thread
    pool, where the threads are able to use non-static data.
  - This may also be used to support threading in exotic environments, like
    WebAssembly, which don't support the normal `std::thread`.
- `ParallelIterator` has 3 new methods: `find_map_any()`, `find_map_first()`,
  and `find_map_last()`, like `Iterator::find_map()` with ordering constraints.
- The new `ParallelIterator::panic_fuse()` makes a parallel iterator halt as soon
  as possible if any of its threads panic. Otherwise, the panic state is not
  usually noticed until the iterator joins its parallel tasks back together.
- `IntoParallelIterator` is now implemented for integral `RangeInclusive`.
- Several internal `Folder`s now have optimized `consume_iter` implementations.
- `rayon_core::current_thread_index()` is now re-exported in `rayon`.
- The minimum `rustc` is now 1.26, following the update policy defined in [RFC 3].

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @didroe
- @GuillaumeGomez
- @huonw
- @janriemer
- @kornelski
- @nikomatsakis
- @seanchen1991
- @yegeun542

[RFC 1]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0001-scope-scheduling.md
[RFC 3]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0003-minimum-rustc.md


# Release rayon 1.0.3 (2018-11-02)

- `ParallelExtend` is now implemented for tuple pairs, enabling nested
  `unzip()` and `partition_map()` operations.  For instance, `(A, (B, C))`
  items can be unzipped into `(Vec<A>, (Vec<B>, Vec<C>))`.
  - `ParallelExtend<(A, B)>` works like `unzip()`.
  - `ParallelExtend<Either<A, B>>` works like `partition_map()`.
- `ParallelIterator` now has a method `map_init()` which calls an `init`
  function for a value to pair with items, like `map_with()` but dynamically
  constructed.  That value type has no constraints, not even `Send` or `Sync`.
  - The new `for_each_init()` is a variant of this for simple iteration.
  - The new `try_for_each_init()` is a variant for fallible iteration.

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @dan-zheng
- @dholbert
- @ignatenkobrain
- @mdonoughe


# Release rayon 1.0.2 / rayon-core 1.4.1 (2018-07-17)

- The `ParallelBridge` trait with method `par_bridge()` makes it possible to
  use any `Send`able `Iterator` in parallel!
  - This trait has been added to `rayon::prelude`.
  - It automatically implements internal synchronization and queueing to
    spread the `Item`s across the thread pool.  Iteration order is not
    preserved by this adaptor.
  - "Native" Rayon iterators like `par_iter()` should still be preferred when
    possible for better efficiency.
- `ParallelString` now has additional methods for parity with `std` string
  iterators: `par_char_indices()`, `par_bytes()`, `par_encode_utf16()`,
  `par_matches()`, and `par_match_indices()`.
- `ParallelIterator` now has fallible methods `try_fold()`, `try_reduce()`,
  and `try_for_each`, plus `*_with()` variants of each, for automatically
  short-circuiting iterators on `None` or `Err` values.  These are inspired by
  `Iterator::try_fold()` and `try_for_each()` that were stabilized in Rust 1.27.
- `Range<i128>` and `Range<u128>` are now supported with Rust 1.26 and later.
- Small improvements have been made to the documentation.
- `rayon-core` now only depends on `rand` for testing.
- Rayon tests now work on stable Rust.

## Contributors

Thanks to all of the contributors for this release!

- @AndyGauge
- @cuviper
- @ignatenkobrain
- @LukasKalbertodt
- @MajorBreakfast
- @nikomatsakis
- @paulkernfeld
- @QuietMisdreavus


# Release rayon 1.0.1 (2018-03-16)

- Added more documentation for `rayon::iter::split()`.
- Corrected links and typos in documentation.

## Contributors

Thanks to all of the contributors for this release!

- @cuviper
- @HadrienG2
- @matthiasbeyer
- @nikomatsakis


# Release rayon 1.0.0 / rayon-core 1.4.0 (2018-02-15)

- `ParallelIterator` added the `update` method which applies a function to
  mutable references, inspired by `itertools`.
- `IndexedParallelIterator` added the `chunks` method which yields vectors of
  consecutive items from the base iterator, inspired by `itertools`.
- `String` now implements `FromParallelIterator<Cow<str>>` and
  `ParallelExtend<Cow<str>>`, inspired by `std`.
- `()` now implements `FromParallelIterator<()>`, inspired by `std`.
- The new `ThreadPoolBuilder` replaces and deprecates `Configuration`.
  - Errors from initialization now have the concrete `ThreadPoolBuildError`
    type, rather than `Box<Error>`, and this type implements `Send` and `Sync`.
  - `ThreadPool::new` is deprecated in favor of `ThreadPoolBuilder::build`.
  - `initialize` is deprecated in favor of `ThreadPoolBuilder::build_global`.
- Examples have been added to most of the parallel iterator methods.
- A lot of the documentation has been reorganized and extended.

## Breaking changes

- Rayon now requires rustc 1.13 or greater.
- `IndexedParallelIterator::len` and `ParallelIterator::opt_len` now operate on
  `&self` instead of `&mut self`.
- `IndexedParallelIterator::collect_into` is now `collect_into_vec`.
- `IndexedParallelIterator::unzip_into` is now `unzip_into_vecs`.
- Rayon no longer exports the deprecated `Configuration` and `initialize` from
  rayon-core.

## Contributors

Thanks to all of the contributors for this release!

- @Bilkow
- @cuviper
- @Enet4
- @ignatenkobrain
- @iwillspeak
- @jeehoonkang
- @jwass
- @Kerollmops
- @KodrAus
- @kornelski
- @MaloJaffre
- @nikomatsakis
- @obv-mikhail
- @oddg
- @phimuemue
- @stjepang
- @tmccombs
- bors[bot]


# Release rayon 0.9.0 / rayon-core 1.3.0 / rayon-futures 0.1.0 (2017-11-09)

- `Configuration` now has a `build` method.
- `ParallelIterator` added `flatten` and `intersperse`, both inspired by
  itertools.
- `IndexedParallelIterator` added `interleave`, `interleave_shortest`, and
  `zip_eq`, all inspired by itertools.
- The new functions `iter::empty` and `once` create parallel iterators of
  exactly zero or one item, like their `std` counterparts.
- The new functions `iter::repeat` and `repeatn` create parallel iterators
  repeating an item indefinitely or `n` times, respectively.
- The new function `join_context` works like `join`, with an added `FnContext`
  parameter that indicates whether the job was stolen.
- `Either` (used by `ParallelIterator::partition_map`) is now re-exported from
  the `either` crate, instead of defining our own type.
  - `Either` also now implements `ParallelIterator`, `IndexedParallelIterator`,
    and `ParallelExtend` when both of its `Left` and `Right` types do.
- All public types now implement `Debug`.
- Many of the parallel iterators now implement `Clone` where possible.
- Much of the documentation has been extended. (but still could use more help!)
- All rayon crates have improved metadata.
- Rayon was evaluated in the Libz Blitz, leading to many of these improvements.
- Rayon pull requests are now guarded by bors-ng.

## Futures

The `spawn_future()` method has been refactored into its own `rayon-futures`
crate, now through a `ScopeFutureExt` trait for `ThreadPool` and `Scope`.  The
supporting `rayon-core` APIs are still gated by `--cfg rayon_unstable`.

## Breaking changes

- Two breaking changes have been made to `rayon-core`, but since they're fixing
  soundness bugs, we are considering these _minor_ changes for semver.
  - `Scope::spawn` now requires `Send` for the closure.
  - `ThreadPool::install` now requires `Send` for the return value.
- The `iter::internal` module has been renamed to `iter::plumbing`, to hopefully
  indicate that while these are low-level details, they're not really internal
  or private to rayon.  The contents of that module are needed for third-parties
  to implement new parallel iterators, and we'll treat them with normal semver
  stability guarantees.
- The function `rayon::iter::split` is no longer re-exported as `rayon::split`.

## Contributors

Thanks to all of the contributors for this release!

- @AndyGauge
- @ChristopherDavenport
- @chrisvittal
- @cuviper
- @dns2utf8
- @dtolnay
- @frewsxcv
- @gsquire
- @Hittherhod
- @jdr023
- @laumann
- @leodasvacas
- @lvillani
- @MajorBreakfast
- @mamuleanu
- @marmistrz
- @mbrubeck
- @mgattozzi
- @nikomatsakis
- @smt923
- @stjepang
- @tmccombs
- @vishalsodani
- bors[bot]


# Release rayon 0.8.2 (2017-06-28)

- `ParallelSliceMut` now has six parallel sorting methods with the same
  variations as the standard library.
  - `par_sort`, `par_sort_by`, and `par_sort_by_key` perform stable sorts in
    parallel, using the default order, a custom comparator, or a key extraction
    function, respectively.
  - `par_sort_unstable`, `par_sort_unstable_by`, and `par_sort_unstable_by_key`
    perform unstable sorts with the same comparison options.
  - Thanks to @stjepang!


# Release rayon 0.8.1 / rayon-core 1.2.0 (2017-06-14)

- The following core APIs are being stabilized:
  - `rayon::spawn()` -- spawns a task into the Rayon thread pool; as it
    is contained in the global scope (rather than a user-created
    scope), the task cannot capture anything from the current stack
    frame.
  - `ThreadPool::join()`, `ThreadPool::spawn()`, `ThreadPool::scope()`
    -- convenience APIs for launching new work within a thread pool.
- The various iterator adapters are now tagged with `#[must_use]`
- Parallel iterators now offer a `for_each_with` adapter, similar to
  `map_with`.
- We are adopting a new approach to handling the remaining unstable
  APIs (which primarily pertain to futures integration). As awlays,
  unstable APIs are intended for experimentation, but do not come with
  any promise of compatibility (in other words, we might change them
  in arbitrary ways in any release). Previously, we designated such
  APIs using a Cargo feature "unstable". Now, we are using a regular
  `#[cfg]` flag. This means that to see the unstable APIs, you must do
  `RUSTFLAGS='--cfg rayon_unstable' cargo build`. This is
  intentionally inconvenient; in particular, if you are a library,
  then your clients must also modify their environment, signaling
  their agreement to instability.


# Release rayon 0.8.0 / rayon-core 1.1.0 (2017-06-13)

## Rayon 0.8.0

- Added the `map_with` and `fold_with` combinators, which help for
  passing along state (like channels) that cannot be shared between
  threads but which can be cloned on each thread split.
- Added the `while_some` combinator, which helps for writing short-circuiting iterators.
- Added support for "short-circuiting" collection: e.g., collecting
  from an iterator producing `Option<T>` or `Result<T, E>` into a
  `Option<Collection<T>>` or `Result<Collection<T>, E>`.
- Support `FromParallelIterator` for `Cow`.
- Removed the deprecated weight APIs.
- Simplified the parallel iterator trait hierarchy by removing the
  `BoundedParallelIterator` and `ExactParallelIterator` traits,
  which were not serving much purpose.
- Improved documentation.
- Added some missing `Send` impls.
- Fixed some small bugs.

## Rayon-core 1.1.0

- We now have more documentation.
- Renamed the (unstable) methods `spawn_async` and
  `spawn_future_async` -- which spawn tasks that cannot hold
  references -- to simply `spawn` and `spawn_future`, respectively.
- We are now using the coco library for our deque.
- Individual thread pools can now be configured in "breadth-first"
  mode, which causes them to execute spawned tasks in the reverse
  order that they used to.  In some specific scenarios, this can be a
  win (though it is not generally the right choice).
- Added top-level functions:
  - `current_thread_index`, for querying the index of the current worker thread within
    its thread pool (previously available as `thread_pool.current_thread_index()`);
  - `current_thread_has_pending_tasks`, for querying whether the
    current worker that has an empty task deque or not. This can be
    useful when deciding whether to spawn a task.
- The environment variables for controlling Rayon are now
  `RAYON_NUM_THREADS` and `RAYON_LOG`. The older variables (e.g.,
  `RAYON_RS_NUM_CPUS` are still supported but deprecated).

## Rayon-demo

- Added a new game-of-life benchmark.

## Contributors

Thanks to the following contributors:

- @ChristopherDavenport
- @SuperFluffy
- @antoinewdg
- @crazymykl
- @cuviper
- @glandium
- @julian-seward1
- @leodasvacas
- @leshow
- @lilianmoraru
- @mschmo
- @nikomatsakis
- @stjepang


# Release rayon 0.7.1 / rayon-core 1.0.2 (2017-05-30)

This release is a targeted performance fix for #343, an issue where
rayon threads could sometimes enter into a spin loop where they would
be unable to make progress until they are pre-empted.


# Release rayon 0.7 / rayon-core 1.0 (2017-04-06)

This release marks the first step towards Rayon 1.0. **For best
performance, it is important that all Rayon users update to at least
Rayon 0.7.** This is because, as of Rayon 0.7, we have taken steps to
ensure that, no matter how many versions of rayon are actively in use,
there will only be a single global scheduler. This is achieved via the
`rayon-core` crate, which is being released at version 1.0, and which
encapsulates the core schedule APIs like `join()`. (Note: the
`rayon-core` crate is, to some degree, an implementation detail, and
not intended to be imported directly; it's entire API surface is
mirrored through the rayon crate.)

We have also done a lot of work reorganizing the API for Rayon 0.7 in
preparation for 1.0. The names of iterator types have been changed and
reorganized (but few users are expected to be naming those types
explicitly anyhow). In addition, a number of parallel iterator methods
have been adjusted to match those in the standard iterator traits more
closely. See the "Breaking Changes" section below for
details.

Finally, Rayon 0.7 includes a number of new features and new parallel
iterator methods. **As of this release, Rayon's parallel iterators
have officially reached parity with sequential iterators** -- that is,
every sequential iterator method that makes any sense in parallel is
supported in some capacity.

### New features and methods

- The internal `Producer` trait now features `fold_with`, which enables
  better performance for some parallel iterators.
- Strings now support `par_split()` and `par_split_whitespace()`.
- The `Configuration` API is expanded and simplified:
    - `num_threads(0)` no longer triggers an error
    - you can now supply a closure to name the Rayon threads that get created
      by using `Configuration::thread_name`.
    - you can now inject code when Rayon threads start up and finish
    - you can now set a custom panic handler to handle panics in various odd situations
- Threadpools are now able to more gracefully put threads to sleep when not needed.
- Parallel iterators now support `find_first()`, `find_last()`, `position_first()`,
  and `position_last()`.
- Parallel iterators now support `rev()`, which primarily affects subsequent calls
  to `enumerate()`.
- The `scope()` API is now considered stable (and part of `rayon-core`).
- There is now a useful `rayon::split` function for creating custom
  Rayon parallel iterators.
- Parallel iterators now allow you to customize the min/max number of
  items to be processed in a given thread. This mechanism replaces the
  older `weight` mechanism, which is deprecated.
- `sum()` and friends now use the standard `Sum` traits

### Breaking changes

In the move towards 1.0, there have been a number of minor breaking changes:

- Configuration setters like `Configuration::set_num_threads()` lost the `set_` prefix,
  and hence become something like `Configuration::num_threads()`.
- `Configuration` getters are removed
- Iterator types have been shuffled around and exposed more consistently:
    - combinator types live in `rayon::iter`, e.g. `rayon::iter::Filter`
    - iterators over various types live in a module named after their type,
      e.g. `rayon::slice::Windows`
- When doing a `sum()` or `product()`, type annotations are needed for the result
  since it is now possible to have the resulting sum be of a type other than the value
  you are iterating over (this mirrors sequential iterators).

### Experimental features

Experimental features require the use of the `unstable` feature. Their
APIs may change or disappear entirely in future releases (even minor
releases) and hence they should be avoided for production code.

- We now have (unstable) support for futures integration. You can use
  `Scope::spawn_future` or `rayon::spawn_future_async()`.
- There is now a `rayon::spawn_async()` function for using the Rayon
  thread pool to run tasks that do not have references to the stack.

### Contributors

Thanks to the following people for their contributions to this release:

- @Aaronepower
- @ChristopherDavenport
- @bluss
- @cuviper
- @froydnj
- @gaurikholkar
- @hniksic
- @leodasvacas
- @leshow
- @martinhath
- @mbrubeck
- @nikomatsakis
- @pegomes
- @schuster
- @torkleyy


# Release 0.6 (2016-12-21)

This release includes a lot of progress towards the goal of parity
with the sequential iterator API, though there are still a few methods
that are not yet complete. If you'd like to help with that effort,
[check out the milestone](https://github.com/rayon-rs/rayon/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Parity+with+the+%60Iterator%60+trait%22)
to see the remaining issues.

**Announcement:** @cuviper has been added as a collaborator to the
Rayon repository for all of his outstanding work on Rayon, which
includes both internal refactoring and helping to shape the public
API. Thanks @cuviper! Keep it up.

- We now support `collect()` and not just `collect_with()`.
  You can use `collect()` to build a number of collections,
  including vectors, maps, and sets. Moreover, when building a vector
  with `collect()`, you are no longer limited to exact parallel iterators.
  Thanks @nikomatsakis, @cuviper!
- We now support `skip()` and `take()` on parallel iterators.
  Thanks @martinhath!
- **Breaking change:** We now match the sequential APIs for `min()` and `max()`.
  We also support `min_by_key()` and `max_by_key()`. Thanks @tapeinosyne!
- **Breaking change:** The `mul()` method is now renamed to `product()`,
  to match sequential iterators. Thanks @jonathandturner!
- We now support parallel iterator over ranges on `u64` values. Thanks @cuviper!
- We now offer a `par_chars()` method on strings for iterating over characters
  in parallel. Thanks @cuviper!
- We now have new demos: a traveling salesman problem solver as well as matrix
  multiplication. Thanks @nikomatsakis, @edre!
- We are now documenting our minimum rustc requirement (currently
  v1.12.0).  We will attempt to maintain compatibility with rustc
  stable v1.12.0 as long as it remains convenient, but if new features
  are stabilized or added that would be helpful to Rayon, or there are
  bug fixes that we need, we will bump to the most recent rustc. Thanks @cuviper!
- The `reduce()` functionality now has better inlining.
  Thanks @bluss!
- The `join()` function now has some documentation. Thanks @gsquire!
- The project source has now been fully run through rustfmt.
  Thanks @ChristopherDavenport!
- Exposed helper methods for accessing the current thread index.
  Thanks @bholley!


# Release 0.5 (2016-11-04)

- **Breaking change:** The `reduce` method has been vastly
  simplified, and `reduce_with_identity` has been deprecated.
- **Breaking change:** The `fold` method has been changed. It used to
  always reduce the values, but now instead it is a combinator that
  returns a parallel iterator which can itself be reduced. See the
  docs for more information.
- The following parallel iterator combinators are now available (thanks @cuviper!):
  - `find_any()`: similar to `find` on a sequential iterator,
    but doesn't necessarily return the *first* matching item
  - `position_any()`: similar to `position` on a sequential iterator,
    but doesn't necessarily return the index of *first* matching item
  - `any()`, `all()`: just like their sequential counterparts
- The `count()` combinator is now available for parallel iterators.
- We now build with older versions of rustc again (thanks @durango!),
  as we removed a stray semicolon from `thread_local!`.
- Various improvements to the (unstable) `scope()` API implementation.


# Release 0.4.3 (2016-10-25)

- Parallel iterators now offer an adaptive weight scheme,
  which means that explicit weights should no longer
  be necessary in most cases! Thanks @cuviper!
  - We are considering removing weights or changing the weight mechanism
    before 1.0. Examples of scenarios where you still need weights even
    with this adaptive mechanism would be great. Join the discussion
    at <https://github.com/rayon-rs/rayon/issues/111>.
- New (unstable) scoped threads API, see `rayon::scope` for details.
  - You will need to supply the [cargo feature] `unstable`.
- The various demos and benchmarks have been consolidated into one
  program, `rayon-demo`.
- Optimizations in Rayon's inner workings. Thanks @emilio!
- Update `num_cpus` to 1.0. Thanks @jamwt!
- Various internal cleanup in the implementation and typo fixes.
  Thanks @cuviper, @Eh2406, and @spacejam!

[cargo feature]: https://doc.rust-lang.org/cargo/reference/features.html#the-features-section


# Release 0.4.2 (2016-09-15)

- Updated crates.io metadata.


# Release 0.4.1 (2016-09-14)

- New `chain` combinator for parallel iterators.
- `Option`, `Result`, as well as many more collection types now have
  parallel iterators.
- New mergesort demo.
- Misc fixes.

Thanks to @cuviper, @edre, @jdanford, @frewsxcv for their contributions!


# Release 0.4 (2016-05-16)

- Make use of latest versions of catch-panic and various fixes to panic propagation.
- Add new prime sieve demo.
- Add `cloned()` and `inspect()` combinators.
- Misc fixes for Rust RFC 1214.

Thanks to @areilb1, @Amanieu, @SharplEr, and @cuviper for their contributions!


# Release 0.3 (2016-02-23)

- Expanded `par_iter` APIs now available:
  - `into_par_iter` is now supported on vectors (taking ownership of the elements)
- Panic handling is much improved:
  - if you use the Nightly feature, experimental panic recovery is available
  - otherwise, panics propagate out and poision the workpool
- New `Configuration` object to control number of threads and other details
- New demos and benchmarks
  - try `cargo run --release -- visualize` in `demo/nbody` :)
    - Note: a nightly compiler is required for this demo due to the
      use of the `+=` syntax

Thanks to @bjz, @cuviper, @Amanieu, and @willi-kappler for their contributions!


# Release 0.2 and earlier

No release notes were being kept at this time.


================================================
FILE: ci/alt-core/Cargo.toml
================================================
[package]
edition = "2018"
name = "alt-core"
version = "0.0.0"
authors = ["Josh Stone <cuviper@gmail.com>"]
links = "rayon-core"
build = "build.rs"
publish = false

[dependencies]


================================================
FILE: ci/alt-core/build.rs
================================================
fn main() {}


================================================
FILE: ci/alt-core/src/lib.rs
================================================


================================================
FILE: ci/highlander/Cargo.toml
================================================
[package]
authors = ["Josh Stone <cuviper@gmail.com>"]
edition = "2018"
name = "highlander"
description = "There Can Be Only One"
version = "0.0.0"
publish = false

[dependencies]

[dependencies.alt-core]
optional = false
path = "../alt-core"

[dependencies.rayon-core]
optional = false
path = "../../rayon-core"


================================================
FILE: ci/highlander/src/main.rs
================================================
fn main() {}


================================================
FILE: ci/highlander.sh
================================================
#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

echo "INFO: There Can Be Only One!" >&2

if cargo build --manifest-path "$DIR/highlander/Cargo.toml"; then
    echo "ERROR: we built with multiple rayon-core!" >&2
    exit 1
fi

echo "PASS: using multiple rayon-core failed." >&2


================================================
FILE: rayon-core/Cargo.toml
================================================
[package]
name = "rayon-core"
version = "1.13.0"
description = "Core APIs for Rayon"
documentation = "https://docs.rs/rayon-core/"
links = "rayon-core"
build = "build.rs"

categories.workspace = true
edition.workspace = true
keywords.workspace = true
license.workspace = true
readme.workspace = true
repository.workspace = true
rust-version.workspace = true

[features]
# This feature switches to a spin-lock implementation on the browser's
# main thread to avoid the forbidden `atomics.wait`.
#
# Only useful on the `wasm32-unknown-unknown` target.
web_spin_lock = ["dep:wasm_sync"]

[dependencies]
crossbeam-deque.workspace = true
crossbeam-utils.workspace = true
wasm_sync = { workspace = true, optional = true }

[dev-dependencies]
rand.workspace = true
rand_xorshift.workspace = true
scoped-tls.workspace = true

[target.'cfg(unix)'.dev-dependencies]
libc.workspace = true


================================================
FILE: rayon-core/LICENSE-APACHE
================================================
                              Apache License
                        Version 2.0, January 2004
                     http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

   "License" shall mean the terms and conditions for use, reproduction,
   and distribution as defined by Sections 1 through 9 of this document.

   "Licensor" shall mean the copyright owner or entity authorized by
   the copyright owner that is granting the License.

   "Legal Entity" shall mean the union of the acting entity and all
   other entities that control, are controlled by, or are under common
   control with that entity. For the purposes of this definition,
   "control" means (i) the power, direct or indirect, to cause the
   direction or management of such entity, whether by contract or
   otherwise, or (ii) ownership of fifty percent (50%) or more of the
   outstanding shares, or (iii) beneficial ownership of such entity.

   "You" (or "Your") shall mean an individual or Legal Entity
   exercising permissions granted by this License.

   "Source" form shall mean the preferred form for making modifications,
   including but not limited to software source code, documentation
   source, and configuration files.

   "Object" form shall mean any form resulting from mechanical
   transformation or translation of a Source form, including but
   not limited to compiled object code, generated documentation,
   and conversions to other media types.

   "Work" shall mean the work of authorship, whether in Source or
   Object form, made available under the License, as indicated by a
   copyright notice that is included in or attached to the work
   (an example is provided in the Appendix below).

   "Derivative Works" shall mean any work, whether in Source or Object
   form, that is based on (or derived from) the Work and for which the
   editorial revisions, annotations, elaborations, or other modifications
   represent, as a whole, an original work of authorship. For the purposes
   of this License, Derivative Works shall not include works that remain
   separable from, or merely link (or bind by name) to the interfaces of,
   the Work and Derivative Works thereof.

   "Contribution" shall mean any work of authorship, including
   the original version of the Work and any modifications or additions
   to that Work or Derivative Works thereof, that is intentionally
   submitted to Licensor for inclusion in the Work by the copyright owner
   or by an individual or Legal Entity authorized to submit on behalf of
   the copyright owner. For the purposes of this definition, "submitted"
   means any form of electronic, verbal, or written communication sent
   to the Licensor or its representatives, including but not limited to
   communication on electronic mailing lists, source code control systems,
   and issue tracking systems that are managed by, or on behalf of, the
   Licensor for the purpose of discussing and improving the Work, but
   excluding communication that is conspicuously marked or otherwise
   designated in writing by the copyright owner as "Not a Contribution."

   "Contributor" shall mean Licensor and any individual or Legal Entity
   on behalf of whom a Contribution has been received by Licensor and
   subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   copyright license to reproduce, prepare Derivative Works of,
   publicly display, publicly perform, sublicense, and distribute the
   Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   (except as stated in this section) patent license to make, have made,
   use, offer to sell, sell, import, and otherwise transfer the Work,
   where such license applies only to those patent claims licensable
   by such Contributor that are necessarily infringed by their
   Contribution(s) alone or by combination of their Contribution(s)
   with the Work to which such Contribution(s) was submitted. If You
   institute patent litigation against any entity (including a
   cross-claim or counterclaim in a lawsuit) alleging that the Work
   or a Contribution incorporated within the Work constitutes direct
   or contributory patent infringement, then any patent licenses
   granted to You under this License for that Work shall terminate
   as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
   Work or Derivative Works thereof in any medium, with or without
   modifications, and in Source or Object form, provided that You
   meet the following conditions:

   (a) You must give any other recipients of the Work or
       Derivative Works a copy of this License; and

   (b) You must cause any modified files to carry prominent notices
       stating that You changed the files; and

   (c) You must retain, in the Source form of any Derivative Works
       that You distribute, all copyright, patent, trademark, and
       attribution notices from the Source form of the Work,
       excluding those notices that do not pertain to any part of
       the Derivative Works; and

   (d) If the Work includes a "NOTICE" text file as part of its
       distribution, then any Derivative Works that You distribute must
       include a readable copy of the attribution notices contained
       within such NOTICE file, excluding those notices that do not
       pertain to any part of the Derivative Works, in at least one
       of the following places: within a NOTICE text file distributed
       as part of the Derivative Works; within the Source form or
       documentation, if provided along with the Derivative Works; or,
       within a display generated by the Derivative Works, if and
       wherever such third-party notices normally appear. The contents
       of the NOTICE file are for informational purposes only and
       do not modify the License. You may add Your own attribution
       notices within Derivative Works that You distribute, alongside
       or as an addendum to the NOTICE text from the Work, provided
       that such additional attribution notices cannot be construed
       as modifying the License.

   You may add Your own copyright statement to Your modifications and
   may provide additional or different license terms and conditions
   for use, reproduction, or distribution of Your modifications, or
   for any such Derivative Works as a whole, provided Your use,
   reproduction, and distribution of the Work otherwise complies with
   the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
   names, trademarks, service marks, or product names of the Licensor,
   except as required for reasonable and customary use in describing the
   origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
   agreed to in writing, Licensor provides the Work (and each
   Contributor provides its Contributions) on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied, including, without limitation, any warranties or conditions
   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
   PARTICULAR PURPOSE. You are solely responsible for determining the
   appropriateness of using or redistributing the Work and assume any
   risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
   whether in tort (including negligence), contract, or otherwise,
   unless required by applicable law (such as deliberate and grossly
   negligent acts) or agreed to in writing, shall any Contributor be
   liable to You for damages, including any direct, indirect, special,
   incidental, or consequential damages of any character arising as a
   result of this License or out of the use or inability to use the
   Work (including but not limited to damages for loss of goodwill,
   work stoppage, computer failure or malfunction, or any and all
   other commercial damages or losses), even if such Contributor
   has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
   the Work or Derivative Works thereof, You may choose to offer,
   and charge a fee for, acceptance of support, warranty, indemnity,
   or other liability obligations and/or rights consistent with this
   License. However, in accepting such obligations, You may act only
   on Your own behalf and on Your sole responsibility, not on behalf
   of any other Contributor, and only if You agree to indemnify,
   defend, and hold each Contributor harmless for any liability
   incurred by, or claims asserted against, such Contributor by reason
   of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

   To apply the Apache License to your work, attach the following
   boilerplate notice, with the fields enclosed by brackets "[]"
   replaced with your own identifying information. (Don't include
   the brackets!)  The text should be enclosed in the appropriate
   comment syntax for the file format. We also recommend that a
   file or class name and description of purpose be included on the
   same "printed page" as the copyright notice for easier
   identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

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

	http://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.


================================================
FILE: rayon-core/LICENSE-MIT
================================================
Copyright (c) 2010 The Rust Project Developers

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.


================================================
FILE: rayon-core/README.md
================================================
Rayon-core represents the "core, stable" APIs of Rayon: join, scope, and so forth, as well as the ability to create custom thread pools with ThreadPool.

Maybe worth mentioning: users are not necessarily intended to directly access rayon-core; all its APIs are mirrored in the rayon crate. To that end, the examples in the docs use rayon::join and so forth rather than rayon_core::join.

rayon-core aims to never, or almost never, have a breaking change to its API, because each revision of rayon-core also houses the global thread pool (and hence if you have two simultaneous versions of rayon-core, you have two thread pools).

Please see [Rayon Docs] for details about using Rayon.

[Rayon Docs]: https://docs.rs/rayon/

Rayon-core currently requires `rustc 1.80.0` or greater.


================================================
FILE: rayon-core/build.rs
================================================
// We need a build script to use `link = "rayon-core"`.  But we're not
// *actually* linking to anything, just making sure that we're the only
// rayon-core in use.
fn main() {
    // we don't need to rebuild for anything else
    println!("cargo:rerun-if-changed=build.rs");
}


================================================
FILE: rayon-core/src/broadcast/mod.rs
================================================
use crate::job::{ArcJob, StackJob};
use crate::latch::{CountLatch, LatchRef};
use crate::registry::{Registry, WorkerThread};
use std::fmt;
use std::marker::PhantomData;
use std::sync::Arc;

mod test;

/// Executes `op` within every thread in the current thread pool. If this is
/// called from a non-Rayon thread, it will execute in the global thread pool.
/// Any attempts to use `join`, `scope`, or parallel iterators will then operate
/// within that thread pool. When the call has completed on each thread, returns
/// a vector containing all of their return values.
///
/// For more information, see the [`ThreadPool::broadcast()`] method.
///
/// [`ThreadPool::broadcast()`]: crate::ThreadPool::broadcast()
pub fn broadcast<OP, R>(op: OP) -> Vec<R>
where
    OP: Fn(BroadcastContext<'_>) -> R + Sync,
    R: Send,
{
    // We assert that current registry has not terminated.
    unsafe { broadcast_in(op, &Registry::current()) }
}

/// Spawns an asynchronous task on every thread in this thread pool. This task
/// will run in the implicit, global scope, which means that it may outlast the
/// current stack frame -- therefore, it cannot capture any references onto the
/// stack (you will likely need a `move` closure).
///
/// For more information, see the [`ThreadPool::spawn_broadcast()`] method.
///
/// [`ThreadPool::spawn_broadcast()`]: crate::ThreadPool::spawn_broadcast()
pub fn spawn_broadcast<OP>(op: OP)
where
    OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static,
{
    // We assert that current registry has not terminated.
    unsafe { spawn_broadcast_in(op, &Registry::current()) }
}

/// Provides context to a closure called by `broadcast`.
pub struct BroadcastContext<'a> {
    worker: &'a WorkerThread,

    /// Make sure to prevent auto-traits like `Send` and `Sync`.
    _marker: PhantomData<&'a mut dyn Fn()>,
}

impl<'a> BroadcastContext<'a> {
    pub(super) fn with<R>(f: impl FnOnce(BroadcastContext<'_>) -> R) -> R {
        let worker_thread = WorkerThread::current();
        assert!(!worker_thread.is_null());
        f(BroadcastContext {
            worker: unsafe { &*worker_thread },
            _marker: PhantomData,
        })
    }

    /// Our index amongst the broadcast threads (ranges from `0..self.num_threads()`).
    #[inline]
    pub fn index(&self) -> usize {
        self.worker.index()
    }

    /// The number of threads receiving the broadcast in the thread pool.
    ///
    /// # Future compatibility note
    ///
    /// Future versions of Rayon might vary the number of threads over time, but
    /// this method will always return the number of threads which are actually
    /// receiving your particular `broadcast` call.
    #[inline]
    pub fn num_threads(&self) -> usize {
        self.worker.registry().num_threads()
    }
}

impl<'a> fmt::Debug for BroadcastContext<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("BroadcastContext")
            .field("index", &self.index())
            .field("num_threads", &self.num_threads())
            .field("pool_id", &self.worker.registry().id())
            .finish()
    }
}

/// Execute `op` on every thread in the pool. It will be executed on each
/// thread when they have nothing else to do locally, before they try to
/// steal work from other threads. This function will not return until all
/// threads have completed the `op`.
///
/// Unsafe because `registry` must not yet have terminated.
pub(super) unsafe fn broadcast_in<OP, R>(op: OP, registry: &Arc<Registry>) -> Vec<R>
where
    OP: Fn(BroadcastContext<'_>) -> R + Sync,
    R: Send,
{
    let f = move |injected: bool| {
        debug_assert!(injected);
        BroadcastContext::with(&op)
    };

    let n_threads = registry.num_threads();
    let current_thread = WorkerThread::current().as_ref();
    let latch = CountLatch::with_count(n_threads, current_thread);
    let jobs: Vec<_> = (0..n_threads)
        .map(|_| StackJob::new(&f, LatchRef::new(&latch)))
        .collect();
    let job_refs = jobs.iter().map(|job| job.as_job_ref());

    registry.inject_broadcast(job_refs);

    // Wait for all jobs to complete, then collect the results, maybe propagating a panic.
    latch.wait(current_thread);
    jobs.into_iter().map(|job| job.into_result()).collect()
}

/// Execute `op` on every thread in the pool. It will be executed on each
/// thread when they have nothing else to do locally, before they try to
/// steal work from other threads. This function returns immediately after
/// injecting the jobs.
///
/// Unsafe because `registry` must not yet have terminated.
pub(super) unsafe fn spawn_broadcast_in<OP>(op: OP, registry: &Arc<Registry>)
where
    OP: Fn(BroadcastContext<'_>) + Send + Sync + 'static,
{
    let job = ArcJob::new({
        let registry = Arc::clone(registry);
        move || {
            registry.catch_unwind(|| BroadcastContext::with(&op));
            registry.terminate(); // (*) permit registry to terminate now
        }
    });

    let n_threads = registry.num_threads();
    let job_refs = (0..n_threads).map(|_| {
        // Ensure that registry cannot terminate until this job has executed
        // on each thread. This ref is decremented at the (*) above.
        registry.increment_terminate_count();

        ArcJob::as_static_job_ref(&job)
    });

    registry.inject_broadcast(job_refs);
}


================================================
FILE: rayon-core/src/broadcast/test.rs
================================================
#![cfg(test)]

use crate::ThreadPoolBuilder;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::{thread, time};

#[test]
fn broadcast_global() {
    let v = crate::broadcast(|ctx| ctx.index());
    assert!(v.into_iter().eq(0..crate::current_num_threads()));
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn spawn_broadcast_global() {
    let (tx, rx) = channel();
    crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap());

    let mut v: Vec<_> = rx.into_iter().collect();
    v.sort_unstable();
    assert!(v.into_iter().eq(0..crate::current_num_threads()));
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn broadcast_pool() {
    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    let v = pool.broadcast(|ctx| ctx.index());
    assert!(v.into_iter().eq(0..7));
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn spawn_broadcast_pool() {
    let (tx, rx) = channel();
    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    pool.spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap());

    let mut v: Vec<_> = rx.into_iter().collect();
    v.sort_unstable();
    assert!(v.into_iter().eq(0..7));
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn broadcast_self() {
    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    let v = pool.install(|| crate::broadcast(|ctx| ctx.index()));
    assert!(v.into_iter().eq(0..7));
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn spawn_broadcast_self() {
    let (tx, rx) = channel();
    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    pool.spawn(|| crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap()));

    let mut v: Vec<_> = rx.into_iter().collect();
    v.sort_unstable();
    assert!(v.into_iter().eq(0..7));
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn broadcast_mutual() {
    let count = AtomicUsize::new(0);
    let pool1 = ThreadPoolBuilder::new().num_threads(3).build().unwrap();
    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    pool1.install(|| {
        pool2.broadcast(|_| {
            pool1.broadcast(|_| {
                count.fetch_add(1, Ordering::Relaxed);
            })
        })
    });
    assert_eq!(count.into_inner(), 3 * 7);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn spawn_broadcast_mutual() {
    let (tx, rx) = channel();
    let pool1 = Arc::new(ThreadPoolBuilder::new().num_threads(3).build().unwrap());
    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    pool1.spawn({
        let pool1 = Arc::clone(&pool1);
        move || {
            pool2.spawn_broadcast(move |_| {
                let tx = tx.clone();
                pool1.spawn_broadcast(move |_| tx.send(()).unwrap())
            })
        }
    });
    assert_eq!(rx.into_iter().count(), 3 * 7);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn broadcast_mutual_sleepy() {
    let count = AtomicUsize::new(0);
    let pool1 = ThreadPoolBuilder::new().num_threads(3).build().unwrap();
    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    pool1.install(|| {
        thread::sleep(time::Duration::from_secs(1));
        pool2.broadcast(|_| {
            thread::sleep(time::Duration::from_secs(1));
            pool1.broadcast(|_| {
                thread::sleep(time::Duration::from_millis(100));
                count.fetch_add(1, Ordering::Relaxed);
            })
        })
    });
    assert_eq!(count.into_inner(), 3 * 7);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn spawn_broadcast_mutual_sleepy() {
    let (tx, rx) = channel();
    let pool1 = Arc::new(ThreadPoolBuilder::new().num_threads(3).build().unwrap());
    let pool2 = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    pool1.spawn({
        let pool1 = Arc::clone(&pool1);
        move || {
            thread::sleep(time::Duration::from_secs(1));
            pool2.spawn_broadcast(move |_| {
                let tx = tx.clone();
                thread::sleep(time::Duration::from_secs(1));
                pool1.spawn_broadcast(move |_| {
                    thread::sleep(time::Duration::from_millis(100));
                    tx.send(()).unwrap();
                })
            })
        }
    });
    assert_eq!(rx.into_iter().count(), 3 * 7);
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore)]
fn broadcast_panic_one() {
    let count = AtomicUsize::new(0);
    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    let result = crate::unwind::halt_unwinding(|| {
        pool.broadcast(|ctx| {
            count.fetch_add(1, Ordering::Relaxed);
            if ctx.index() == 3 {
                panic!("Hello, world!");
            }
        })
    });
    assert_eq!(count.into_inner(), 7);
    assert!(result.is_err(), "broadcast panic should propagate!");
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore)]
fn spawn_broadcast_panic_one() {
    let (tx, rx) = channel();
    let (panic_tx, panic_rx) = channel();
    let pool = ThreadPoolBuilder::new()
        .num_threads(7)
        .panic_handler(move |e| panic_tx.send(e).unwrap())
        .build()
        .unwrap();
    pool.spawn_broadcast(move |ctx| {
        tx.send(()).unwrap();
        if ctx.index() == 3 {
            panic!("Hello, world!");
        }
    });
    drop(pool); // including panic_tx
    assert_eq!(rx.into_iter().count(), 7);
    assert_eq!(panic_rx.into_iter().count(), 1);
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore)]
fn broadcast_panic_many() {
    let count = AtomicUsize::new(0);
    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    let result = crate::unwind::halt_unwinding(|| {
        pool.broadcast(|ctx| {
            count.fetch_add(1, Ordering::Relaxed);
            if ctx.index() % 2 == 0 {
                panic!("Hello, world!");
            }
        })
    });
    assert_eq!(count.into_inner(), 7);
    assert!(result.is_err(), "broadcast panic should propagate!");
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore)]
fn spawn_broadcast_panic_many() {
    let (tx, rx) = channel();
    let (panic_tx, panic_rx) = channel();
    let pool = ThreadPoolBuilder::new()
        .num_threads(7)
        .panic_handler(move |e| panic_tx.send(e).unwrap())
        .build()
        .unwrap();
    pool.spawn_broadcast(move |ctx| {
        tx.send(()).unwrap();
        if ctx.index() % 2 == 0 {
            panic!("Hello, world!");
        }
    });
    drop(pool); // including panic_tx
    assert_eq!(rx.into_iter().count(), 7);
    assert_eq!(panic_rx.into_iter().count(), 4);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn broadcast_sleep_race() {
    let test_duration = time::Duration::from_secs(1);
    let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
    let start = time::Instant::now();
    while start.elapsed() < test_duration {
        pool.broadcast(|ctx| {
            // A slight spread of sleep duration increases the chance that one
            // of the threads will race in the pool's idle sleep afterward.
            thread::sleep(time::Duration::from_micros(ctx.index() as u64));
        });
    }
}

#[test]
fn broadcast_after_spawn_broadcast() {
    let (tx, rx) = channel();

    // Queue a non-blocking spawn_broadcast.
    crate::spawn_broadcast(move |ctx| tx.send(ctx.index()).unwrap());

    // This blocking broadcast runs after all prior broadcasts.
    crate::broadcast(|_| {});

    // The spawn_broadcast **must** have run by now on all threads.
    let mut v: Vec<_> = rx.try_iter().collect();
    v.sort_unstable();
    assert!(v.into_iter().eq(0..crate::current_num_threads()));
}

#[test]
fn broadcast_after_spawn() {
    let (tx, rx) = channel();

    // Queue a regular spawn on a thread-local deque.
    crate::registry::in_worker(move |_, _| {
        crate::spawn(move || tx.send(22).unwrap());
    });

    // Broadcast runs after the local deque is empty.
    crate::broadcast(|_| {});

    // The spawn **must** have run by now.
    assert_eq!(22, rx.try_recv().unwrap());
}


================================================
FILE: rayon-core/src/compile_fail/mod.rs
================================================
// These modules contain `compile_fail` doc tests.
mod quicksort_race1;
mod quicksort_race2;
mod quicksort_race3;
mod rc_return;
mod rc_upvar;
mod scope_join_bad;


================================================
FILE: rayon-core/src/compile_fail/quicksort_race1.rs
================================================
/*! ```compile_fail,E0524

fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    let mid = partition(v);
    let (lo, _hi) = v.split_at_mut(mid);
    rayon_core::join(|| quick_sort(lo), || quick_sort(lo)); //~ ERROR
}

fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn main() { }

``` */


================================================
FILE: rayon-core/src/compile_fail/quicksort_race2.rs
================================================
/*! ```compile_fail,E0500

fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    let mid = partition(v);
    let (lo, _hi) = v.split_at_mut(mid);
    rayon_core::join(|| quick_sort(lo), || quick_sort(v)); //~ ERROR
}

fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn main() { }

``` */


================================================
FILE: rayon-core/src/compile_fail/quicksort_race3.rs
================================================
/*! ```compile_fail,E0524

fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    let mid = partition(v);
    let (_lo, hi) = v.split_at_mut(mid);
    rayon_core::join(|| quick_sort(hi), || quick_sort(hi)); //~ ERROR
}

fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn main() { }

``` */


================================================
FILE: rayon-core/src/compile_fail/rc_return.rs
================================================
/** ```compile_fail,E0277

use std::rc::Rc;

rayon_core::join(|| Rc::new(22), || ()); //~ ERROR

``` */
mod left {}

/** ```compile_fail,E0277

use std::rc::Rc;

rayon_core::join(|| (), || Rc::new(23)); //~ ERROR

``` */
mod right {}


================================================
FILE: rayon-core/src/compile_fail/rc_upvar.rs
================================================
/*! ```compile_fail,E0277

use std::rc::Rc;

let r = Rc::new(22);
rayon_core::join(|| r.clone(), || r.clone());
//~^ ERROR

``` */


================================================
FILE: rayon-core/src/compile_fail/scope_join_bad.rs
================================================
/*! ```compile_fail,E0373

fn bad_scope<F>(f: F)
    where F: FnOnce(&i32) + Send,
{
    rayon_core::scope(|s| {
        let x = 22;
        s.spawn(|_| f(&x)); //~ ERROR `x` does not live long enough
    });
}

fn good_scope<F>(f: F)
    where F: FnOnce(&i32) + Send,
{
    let x = 22;
    rayon_core::scope(|s| {
        s.spawn(|_| f(&x));
    });
}

fn main() {
}

``` */


================================================
FILE: rayon-core/src/job.rs
================================================
use crate::latch::Latch;
use crate::unwind;
use crossbeam_deque::{Injector, Steal};
use std::any::Any;
use std::cell::UnsafeCell;
use std::mem;
use std::sync::Arc;

pub(super) enum JobResult<T> {
    None,
    Ok(T),
    Panic(Box<dyn Any + Send>),
}

/// A `Job` is used to advertise work for other threads that they may
/// want to steal. In accordance with time honored tradition, jobs are
/// arranged in a deque, so that thieves can take from the top of the
/// deque while the main worker manages the bottom of the deque. This
/// deque is managed by the `thread_pool` module.
pub(super) trait Job {
    /// Unsafe: this may be called from a different thread than the one
    /// which scheduled the job, so the implementer must ensure the
    /// appropriate traits are met, whether `Send`, `Sync`, or both.
    unsafe fn execute(this: *const ());
}

/// Effectively a Job trait object. Each JobRef **must** be executed
/// exactly once, or else data may leak.
///
/// Internally, we store the job's data in a `*const ()` pointer.  The
/// true type is something like `*const StackJob<...>`, but we hide
/// it. We also carry the "execute fn" from the `Job` trait.
pub(super) struct JobRef {
    pointer: *const (),
    execute_fn: unsafe fn(*const ()),
}

unsafe impl Send for JobRef {}
unsafe impl Sync for JobRef {}

impl JobRef {
    /// Unsafe: caller asserts that `data` will remain valid until the
    /// job is executed.
    pub(super) unsafe fn new<T>(data: *const T) -> JobRef
    where
        T: Job,
    {
        // erase types:
        JobRef {
            pointer: data as *const (),
            execute_fn: <T as Job>::execute,
        }
    }

    /// Returns an opaque handle that can be saved and compared,
    /// without making `JobRef` itself `Copy + Eq`.
    #[inline]
    pub(super) fn id(&self) -> impl Eq {
        (self.pointer, self.execute_fn)
    }

    #[inline]
    pub(super) unsafe fn execute(self) {
        (self.execute_fn)(self.pointer)
    }
}

/// A job that will be owned by a stack slot. This means that when it
/// executes it need not free any heap data, the cleanup occurs when
/// the stack frame is later popped.  The function parameter indicates
/// `true` if the job was stolen -- executed on a different thread.
pub(super) struct StackJob<L, F, R>
where
    L: Latch + Sync,
    F: FnOnce(bool) -> R + Send,
    R: Send,
{
    pub(super) latch: L,
    func: UnsafeCell<Option<F>>,
    result: UnsafeCell<JobResult<R>>,
}

impl<L, F, R> StackJob<L, F, R>
where
    L: Latch + Sync,
    F: FnOnce(bool) -> R + Send,
    R: Send,
{
    pub(super) fn new(func: F, latch: L) -> StackJob<L, F, R> {
        StackJob {
            latch,
            func: UnsafeCell::new(Some(func)),
            result: UnsafeCell::new(JobResult::None),
        }
    }

    pub(super) unsafe fn as_job_ref(&self) -> JobRef {
        JobRef::new(self)
    }

    pub(super) unsafe fn run_inline(self, stolen: bool) -> R {
        self.func.into_inner().unwrap()(stolen)
    }

    pub(super) unsafe fn into_result(self) -> R {
        self.result.into_inner().into_return_value()
    }
}

impl<L, F, R> Job for StackJob<L, F, R>
where
    L: Latch + Sync,
    F: FnOnce(bool) -> R + Send,
    R: Send,
{
    unsafe fn execute(this: *const ()) {
        let this = &*(this as *const Self);
        let abort = unwind::AbortIfPanic;
        let func = (*this.func.get()).take().unwrap();
        (*this.result.get()) = JobResult::call(func);
        Latch::set(&this.latch);
        mem::forget(abort);
    }
}

/// Represents a job stored in the heap. Used to implement
/// `scope`. Unlike `StackJob`, when executed, `HeapJob` simply
/// invokes a closure, which then triggers the appropriate logic to
/// signal that the job executed.
///
/// (Probably `StackJob` should be refactored in a similar fashion.)
pub(super) struct HeapJob<BODY>
where
    BODY: FnOnce() + Send,
{
    job: BODY,
}

impl<BODY> HeapJob<BODY>
where
    BODY: FnOnce() + Send,
{
    pub(super) fn new(job: BODY) -> Box<Self> {
        Box::new(HeapJob { job })
    }

    /// Creates a `JobRef` from this job -- note that this hides all
    /// lifetimes, so it is up to you to ensure that this JobRef
    /// doesn't outlive any data that it closes over.
    pub(super) unsafe fn into_job_ref(self: Box<Self>) -> JobRef {
        JobRef::new(Box::into_raw(self))
    }

    /// Creates a static `JobRef` from this job.
    pub(super) fn into_static_job_ref(self: Box<Self>) -> JobRef
    where
        BODY: 'static,
    {
        unsafe { self.into_job_ref() }
    }
}

impl<BODY> Job for HeapJob<BODY>
where
    BODY: FnOnce() + Send,
{
    unsafe fn execute(this: *const ()) {
        let this = Box::from_raw(this as *mut Self);
        (this.job)();
    }
}

/// Represents a job stored in an `Arc` -- like `HeapJob`, but may
/// be turned into multiple `JobRef`s and called multiple times.
pub(super) struct ArcJob<BODY>
where
    BODY: Fn() + Send + Sync,
{
    job: BODY,
}

impl<BODY> ArcJob<BODY>
where
    BODY: Fn() + Send + Sync,
{
    pub(super) fn new(job: BODY) -> Arc<Self> {
        Arc::new(ArcJob { job })
    }

    /// Creates a `JobRef` from this job -- note that this hides all
    /// lifetimes, so it is up to you to ensure that this JobRef
    /// doesn't outlive any data that it closes over.
    pub(super) unsafe fn as_job_ref(this: &Arc<Self>) -> JobRef {
        JobRef::new(Arc::into_raw(Arc::clone(this)))
    }

    /// Creates a static `JobRef` from this job.
    pub(super) fn as_static_job_ref(this: &Arc<Self>) -> JobRef
    where
        BODY: 'static,
    {
        unsafe { Self::as_job_ref(this) }
    }
}

impl<BODY> Job for ArcJob<BODY>
where
    BODY: Fn() + Send + Sync,
{
    unsafe fn execute(this: *const ()) {
        let this = Arc::from_raw(this as *mut Self);
        (this.job)();
    }
}

impl<T> JobResult<T> {
    fn call(func: impl FnOnce(bool) -> T) -> Self {
        match unwind::halt_unwinding(|| func(true)) {
            Ok(x) => JobResult::Ok(x),
            Err(x) => JobResult::Panic(x),
        }
    }

    /// Convert the `JobResult` for a job that has finished (and hence
    /// its JobResult is populated) into its return value.
    ///
    /// NB. This will panic if the job panicked.
    pub(super) fn into_return_value(self) -> T {
        match self {
            JobResult::None => unreachable!(),
            JobResult::Ok(x) => x,
            JobResult::Panic(x) => unwind::resume_unwinding(x),
        }
    }
}

/// Indirect queue to provide FIFO job priority.
pub(super) struct JobFifo {
    inner: Injector<JobRef>,
}

impl JobFifo {
    pub(super) fn new() -> Self {
        JobFifo {
            inner: Injector::new(),
        }
    }

    pub(super) unsafe fn push(&self, job_ref: JobRef) -> JobRef {
        // A little indirection ensures that spawns are always prioritized in FIFO order.  The
        // jobs in a thread's deque may be popped from the back (LIFO) or stolen from the front
        // (FIFO), but either way they will end up popping from the front of this queue.
        self.inner.push(job_ref);
        JobRef::new(self)
    }
}

impl Job for JobFifo {
    unsafe fn execute(this: *const ()) {
        // We "execute" a queue by executing its first job, FIFO.
        let this = &*(this as *const Self);
        loop {
            match this.inner.steal() {
                Steal::Success(job_ref) => break job_ref.execute(),
                Steal::Empty => panic!("FIFO is empty"),
                Steal::Retry => {}
            }
        }
    }
}


================================================
FILE: rayon-core/src/join/mod.rs
================================================
use crate::job::StackJob;
use crate::latch::SpinLatch;
use crate::registry::{self, WorkerThread};
use crate::unwind;
use std::any::Any;

use crate::FnContext;

#[cfg(test)]
mod test;

/// Takes two closures and *potentially* runs them in parallel. It
/// returns a pair of the results from those closures.
///
/// Conceptually, calling `join()` is similar to spawning two threads,
/// one executing each of the two closures. However, the
/// implementation is quite different and incurs very low
/// overhead. The underlying technique is called "work stealing": the
/// Rayon runtime uses a fixed pool of worker threads and attempts to
/// only execute code in parallel when there are idle CPUs to handle
/// it.
///
/// When `join` is called from outside the thread pool, the calling
/// thread will block while the closures execute in the pool.  When
/// `join` is called within the pool, the calling thread still actively
/// participates in the thread pool. It will begin by executing closure
/// A (on the current thread). While it is doing that, it will advertise
/// closure B as being available for other threads to execute. Once closure A
/// has completed, the current thread will try to execute closure B;
/// if however closure B has been stolen, then it will look for other work
/// while waiting for the thief to fully execute closure B. (This is the
/// typical work-stealing strategy).
///
/// # Examples
///
/// This example uses join to perform a quick-sort (note this is not a
/// particularly optimized implementation: if you **actually** want to
/// sort for real, you should prefer [the `par_sort` method] offered
/// by Rayon).
///
/// [the `par_sort` method]: ../rayon/slice/trait.ParallelSliceMut.html#method.par_sort
///
/// ```rust
/// # use rayon_core as rayon;
/// let mut v = vec![5, 1, 8, 22, 0, 44];
/// quick_sort(&mut v);
/// assert_eq!(v, vec![0, 1, 5, 8, 22, 44]);
///
/// fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
///    if v.len() > 1 {
///        let mid = partition(v);
///        let (lo, hi) = v.split_at_mut(mid);
///        rayon::join(|| quick_sort(lo),
///                    || quick_sort(hi));
///    }
/// }
///
/// // Partition rearranges all items `<=` to the pivot
/// // item (arbitrary selected to be the last item in the slice)
/// // to the first half of the slice. It then returns the
/// // "dividing point" where the pivot is placed.
/// fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
///     let pivot = v.len() - 1;
///     let mut i = 0;
///     for j in 0..pivot {
///         if v[j] <= v[pivot] {
///             v.swap(i, j);
///             i += 1;
///         }
///     }
///     v.swap(i, pivot);
///     i
/// }
/// ```
///
/// # Warning about blocking I/O
///
/// The assumption is that the closures given to `join()` are
/// CPU-bound tasks that do not perform I/O or other blocking
/// operations. If you do perform I/O, and that I/O should block
/// (e.g., waiting for a network request), the overall performance may
/// be poor.  Moreover, if you cause one closure to be blocked waiting
/// on another (for example, using a channel), that could lead to a
/// deadlock.
///
/// # Panics
///
/// No matter what happens, both closures will always be executed.  If
/// a single closure panics, whether it be the first or second
/// closure, that panic will be propagated and hence `join()` will
/// panic with the same panic value. If both closures panic, `join()`
/// will panic with the panic value from the first closure.
pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
where
    A: FnOnce() -> RA + Send,
    B: FnOnce() -> RB + Send,
    RA: Send,
    RB: Send,
{
    #[inline]
    fn call<R>(f: impl FnOnce() -> R) -> impl FnOnce(FnContext) -> R {
        move |_| f()
    }

    join_context(call(oper_a), call(oper_b))
}

/// Identical to `join`, except that the closures have a parameter
/// that provides context for the way the closure has been called,
/// especially indicating whether they're executing on a different
/// thread than where `join_context` was called.  This will occur if
/// the second job is stolen by a different thread, or if
/// `join_context` was called from outside the thread pool to begin
/// with.
pub fn join_context<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
where
    A: FnOnce(FnContext) -> RA + Send,
    B: FnOnce(FnContext) -> RB + Send,
    RA: Send,
    RB: Send,
{
    #[inline]
    fn call_a<R>(f: impl FnOnce(FnContext) -> R, injected: bool) -> impl FnOnce() -> R {
        move || f(FnContext::new(injected))
    }

    #[inline]
    fn call_b<R>(f: impl FnOnce(FnContext) -> R) -> impl FnOnce(bool) -> R {
        move |migrated| f(FnContext::new(migrated))
    }

    registry::in_worker(|worker_thread, injected| unsafe {
        // Create virtual wrapper for task b; this all has to be
        // done here so that the stack frame can keep it all live
        // long enough.
        let job_b = StackJob::new(call_b(oper_b), SpinLatch::new(worker_thread));
        let job_b_ref = job_b.as_job_ref();
        let job_b_id = job_b_ref.id();
        worker_thread.push(job_b_ref);

        // Execute task a; hopefully b gets stolen in the meantime.
        let status_a = unwind::halt_unwinding(call_a(oper_a, injected));
        let result_a = match status_a {
            Ok(v) => v,
            Err(err) => join_recover_from_panic(worker_thread, &job_b.latch, err),
        };

        // Now that task A has finished, try to pop job B from the
        // local stack.  It may already have been popped by job A; it
        // may also have been stolen. There may also be some tasks
        // pushed on top of it in the stack, and we will have to pop
        // those off to get to it.
        while !job_b.latch.probe() {
            let Some(job) = worker_thread.take_local_job() else {
                // Local deque is empty. Time to steal from other
                // threads.
                worker_thread.wait_until(&job_b.latch);
                debug_assert!(job_b.latch.probe());
                break;
            };
            if job_b_id == job.id() {
                // Found it! Let's run it.
                //
                // Note that this could panic, but it's ok if we unwind here.
                let result_b = job_b.run_inline(injected);
                return (result_a, result_b);
            }
            worker_thread.execute(job);
        }

        (result_a, job_b.into_result())
    })
}

/// If job A panics, we still cannot return until we are sure that job
/// B is complete. This is because it may contain references into the
/// enclosing stack frame(s).
#[cold] // cold path
unsafe fn join_recover_from_panic(
    worker_thread: &WorkerThread,
    job_b_latch: &SpinLatch<'_>,
    err: Box<dyn Any + Send>,
) -> ! {
    worker_thread.wait_until(job_b_latch);
    unwind::resume_unwinding(err)
}


================================================
FILE: rayon-core/src/join/test.rs
================================================
//! Tests for the join code.

use super::*;
use crate::ThreadPoolBuilder;
use rand::distr::StandardUniform;
use rand::{Rng, SeedableRng};
use rand_xorshift::XorShiftRng;

fn quick_sort<T: PartialOrd + Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    let mid = partition(v);
    let (lo, hi) = v.split_at_mut(mid);
    join(|| quick_sort(lo), || quick_sort(hi));
}

fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn seeded_rng() -> XorShiftRng {
    let mut seed = <XorShiftRng as SeedableRng>::Seed::default();
    (0..).zip(seed.as_mut()).for_each(|(i, x)| *x = i);
    XorShiftRng::from_seed(seed)
}

#[test]
fn sort() {
    let rng = seeded_rng();
    let mut data: Vec<u32> = rng.sample_iter(&StandardUniform).take(6 * 1024).collect();
    let mut sorted_data = data.clone();
    sorted_data.sort();
    quick_sort(&mut data);
    assert_eq!(data, sorted_data);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn sort_in_pool() {
    let rng = seeded_rng();
    let mut data: Vec<u32> = rng.sample_iter(&StandardUniform).take(12 * 1024).collect();

    let pool = ThreadPoolBuilder::new().build().unwrap();
    let mut sorted_data = data.clone();
    sorted_data.sort();
    pool.install(|| quick_sort(&mut data));
    assert_eq!(data, sorted_data);
}

#[test]
#[should_panic(expected = "Hello, world!")]
fn panic_propagate_a() {
    join(|| panic!("Hello, world!"), || ());
}

#[test]
#[should_panic(expected = "Hello, world!")]
fn panic_propagate_b() {
    join(|| (), || panic!("Hello, world!"));
}

#[test]
#[should_panic(expected = "Hello, world!")]
fn panic_propagate_both() {
    join(|| panic!("Hello, world!"), || panic!("Goodbye, world!"));
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore)]
fn panic_b_still_executes() {
    let mut x = false;
    match unwind::halt_unwinding(|| join(|| panic!("Hello, world!"), || x = true)) {
        Ok(_) => panic!("failed to propagate panic from closure A,"),
        Err(_) => assert!(x, "closure b failed to execute"),
    }
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn join_context_both() {
    // If we're not in a pool, both should be marked stolen as they're injected.
    let (a_migrated, b_migrated) = join_context(|a| a.migrated(), |b| b.migrated());
    assert!(a_migrated);
    assert!(b_migrated);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn join_context_neither() {
    // If we're already in a 1-thread pool, neither job should be stolen.
    let pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
    let (a_migrated, b_migrated) =
        pool.install(|| join_context(|a| a.migrated(), |b| b.migrated()));
    assert!(!a_migrated);
    assert!(!b_migrated);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn join_context_second() {
    use std::sync::Barrier;

    // If we're already in a 2-thread pool, the second job should be stolen.
    let barrier = Barrier::new(2);
    let pool = ThreadPoolBuilder::new().num_threads(2).build().unwrap();
    let (a_migrated, b_migrated) = pool.install(|| {
        join_context(
            |a| {
                barrier.wait();
                a.migrated()
            },
            |b| {
                barrier.wait();
                b.migrated()
            },
        )
    });
    assert!(!a_migrated);
    assert!(b_migrated);
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
fn join_counter_overflow() {
    const MAX: u32 = 500_000;

    let mut i = 0;
    let mut j = 0;
    let pool = ThreadPoolBuilder::new().num_threads(2).build().unwrap();

    // Hammer on join a bunch of times -- used to hit overflow debug-assertions
    // in JEC on 32-bit targets: https://github.com/rayon-rs/rayon/issues/797
    for _ in 0..MAX {
        pool.join(|| i += 1, || j += 1);
    }

    assert_eq!(i, MAX);
    assert_eq!(j, MAX);
}


================================================
FILE: rayon-core/src/latch.rs
================================================
use std::marker::PhantomData;
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

use crate::registry::{Registry, WorkerThread};
use crate::sync::{Condvar, Mutex};

/// We define various kinds of latches, which are all a primitive signaling
/// mechanism. A latch starts as false. Eventually someone calls `set()` and
/// it becomes true. You can test if it has been set by calling `probe()`.
///
/// Some kinds of latches, but not all, support a `wait()` operation
/// that will wait until the latch is set, blocking efficiently. That
/// is not part of the trait since it is not possibly to do with all
/// latches.
///
/// The intention is that `set()` is called once, but `probe()` may be
/// called any number of times. Once `probe()` returns true, the memory
/// effects that occurred before `set()` become visible.
///
/// It'd probably be better to refactor the API into two paired types,
/// but that's a bit of work, and this is not a public API.
///
/// ## Memory ordering
///
/// Latches need to guarantee two things:
///
/// - Once `probe()` returns true, all memory effects from the `set()`
///   are visible (in other words, the set should synchronize-with
///   the probe).
/// - Once `set()` occurs, the next `probe()` *will* observe it.  This
///   typically requires a seq-cst ordering. See [the "tickle-then-get-sleepy" scenario in the sleep
///   README](/src/sleep/README.md#tickle-then-get-sleepy) for details.
pub(super) trait Latch {
    /// Set the latch, signalling others.
    ///
    /// # WARNING
    ///
    /// Setting a latch triggers other threads to wake up and (in some
    /// cases) complete. This may, in turn, cause memory to be
    /// deallocated and so forth. One must be very careful about this,
    /// and it's typically better to read all the fields you will need
    /// to access *before* a latch is set!
    ///
    /// This function operates on `*const Self` instead of `&self` to allow it
    /// to become dangling during this call. The caller must ensure that the
    /// pointer is valid upon entry, and not invalidated during the call by any
    /// actions other than `set` itself.
    unsafe fn set(this: *const Self);
}

pub(super) trait AsCoreLatch {
    fn as_core_latch(&self) -> &CoreLatch;
}

/// Latch is not set, owning thread is awake
const UNSET: usize = 0;

/// Latch is not set, owning thread is going to sleep on this latch
/// (but has not yet fallen asleep).
const SLEEPY: usize = 1;

/// Latch is not set, owning thread is asleep on this latch and
/// must be awoken.
const SLEEPING: usize = 2;

/// Latch is set.
const SET: usize = 3;

/// Spin latches are the simplest, most efficient kind, but they do
/// not support a `wait()` operation. They just have a boolean flag
/// that becomes true when `set()` is called.
#[derive(Debug)]
pub(super) struct CoreLatch {
    state: AtomicUsize,
}

impl CoreLatch {
    #[inline]
    fn new() -> Self {
        Self {
            state: AtomicUsize::new(0),
        }
    }

    /// Invoked by owning thread as it prepares to sleep. Returns true
    /// if the owning thread may proceed to fall asleep, false if the
    /// latch was set in the meantime.
    #[inline]
    pub(super) fn get_sleepy(&self) -> bool {
        self.state
            .compare_exchange(UNSET, SLEEPY, Ordering::SeqCst, Ordering::Relaxed)
            .is_ok()
    }

    /// Invoked by owning thread as it falls asleep sleep. Returns
    /// true if the owning thread should block, or false if the latch
    /// was set in the meantime.
    #[inline]
    pub(super) fn fall_asleep(&self) -> bool {
        self.state
            .compare_exchange(SLEEPY, SLEEPING, Ordering::SeqCst, Ordering::Relaxed)
            .is_ok()
    }

    /// Invoked by owning thread as it falls asleep sleep. Returns
    /// true if the owning thread should block, or false if the latch
    /// was set in the meantime.
    #[inline]
    pub(super) fn wake_up(&self) {
        if !self.probe() {
            let _ =
                self.state
                    .compare_exchange(SLEEPING, UNSET, Ordering::SeqCst, Ordering::Relaxed);
        }
    }

    /// Set the latch. If this returns true, the owning thread was sleeping
    /// and must be awoken.
    ///
    /// This is private because, typically, setting a latch involves
    /// doing some wakeups; those are encapsulated in the surrounding
    /// latch code.
    #[inline]
    unsafe fn set(this: *const Self) -> bool {
        let old_state = (*this).state.swap(SET, Ordering::AcqRel);
        old_state == SLEEPING
    }

    /// Test if this latch has been set.
    #[inline]
    pub(super) fn probe(&self) -> bool {
        self.state.load(Ordering::Acquire) == SET
    }
}

impl AsCoreLatch for CoreLatch {
    #[inline]
    fn as_core_latch(&self) -> &CoreLatch {
        self
    }
}

/// Spin latches are the simplest, most efficient kind, but they do
/// not support a `wait()` operation. They just have a boolean flag
/// that becomes true when `set()` is called.
pub(super) struct SpinLatch<'r> {
    core_latch: CoreLatch,
    registry: &'r Arc<Registry>,
    target_worker_index: usize,
    cross: bool,
}

impl<'r> SpinLatch<'r> {
    /// Creates a new spin latch that is owned by `thread`. This means
    /// that `thread` is the only thread that should be blocking on
    /// this latch -- it also means that when the latch is set, we
    /// will wake `thread` if it is sleeping.
    #[inline]
    pub(super) fn new(thread: &'r WorkerThread) -> SpinLatch<'r> {
        SpinLatch {
            core_latch: CoreLatch::new(),
            registry: thread.registry(),
            target_worker_index: thread.index(),
            cross: false,
        }
    }

    /// Creates a new spin latch for cross-thread-pool blocking.  Notably, we
    /// need to make sure the registry is kept alive after setting, so we can
    /// safely call the notification.
    #[inline]
    pub(super) fn cross(thread: &'r WorkerThread) -> SpinLatch<'r> {
        SpinLatch {
            cross: true,
            ..SpinLatch::new(thread)
        }
    }

    #[inline]
    pub(super) fn probe(&self) -> bool {
        self.core_latch.probe()
    }
}

impl AsCoreLatch for SpinLatch<'_> {
    #[inline]
    fn as_core_latch(&self) -> &CoreLatch {
        &self.core_latch
    }
}

impl Latch for SpinLatch<'_> {
    #[inline]
    unsafe fn set(this: *const Self) {
        let registry: &Registry = if (*this).cross {
            // Ensure the registry stays alive while we notify it.
            // Otherwise, it would be possible that we set the spin
            // latch and the other thread sees it and exits, causing
            // the registry to be deallocated, all before we get a
            // chance to invoke `registry.notify_worker_latch_is_set`.
            &Arc::clone((*this).registry)
        } else {
            // If this is not a "cross-registry" spin-latch, then the
            // thread which is performing `set` is itself ensuring
            // that the registry stays alive. However, that doesn't
            // include this *particular* `Arc` handle if the waiting
            // thread then exits, so we must completely dereference it.
            (*this).registry
        };
        let target_worker_index = (*this).target_worker_index;

        // NOTE: Once we `set`, the target may proceed and invalidate `this`!
        if CoreLatch::set(&(*this).core_latch) {
            // Subtle: at this point, we can no longer read from
            // `self`, because the thread owning this spin latch may
            // have awoken and deallocated the latch. Therefore, we
            // only use fields whose values we already read.
            registry.notify_worker_latch_is_set(target_worker_index);
        }
    }
}

/// A Latch starts as false and eventually becomes true. You can block
/// until it becomes true.
#[derive(Debug)]
pub(super) struct LockLatch {
    m: Mutex<bool>,
    v: Condvar,
}

impl LockLatch {
    #[inline]
    pub(super) const fn new() -> LockLatch {
        LockLatch {
            m: Mutex::new(false),
            v: Condvar::new(),
        }
    }

    /// Block until latch is set, then resets this lock latch so it can be reused again.
    pub(super) fn wait_and_reset(&self) {
        let mut guard = self.m.lock().unwrap();
        while !*guard {
            guard = self.v.wait(guard).unwrap();
        }
        *guard = false;
    }

    /// Block until latch is set.
    pub(super) fn wait(&self) {
        let mut guard = self.m.lock().unwrap();
        while !*guard {
            guard = self.v.wait(guard).unwrap();
        }
    }
}

impl Latch for LockLatch {
    #[inline]
    unsafe fn set(this: *const Self) {
        let mut guard = (*this).m.lock().unwrap();
        *guard = true;
        (*this).v.notify_all();
    }
}

/// Once latches are used to implement one-time blocking, primarily
/// for the termination flag of the threads in the pool.
///
/// Note: like a `SpinLatch`, once-latches are always associated with
/// some registry that is probing them, which must be tickled when
/// they are set. *Unlike* a `SpinLatch`, they don't themselves hold a
/// reference to that registry. This is because in some cases the
/// registry owns the once-latch, and that would create a cycle. So a
/// `OnceLatch` must be given a reference to its owning registry when
/// it is set. For this reason, it does not implement the `Latch`
/// trait (but it doesn't have to, as it is not used in those generic
/// contexts).
#[derive(Debug)]
pub(super) struct OnceLatch {
    core_latch: CoreLatch,
}

impl OnceLatch {
    #[inline]
    pub(super) fn new() -> OnceLatch {
        Self {
            core_latch: CoreLatch::new(),
        }
    }

    /// Set the latch, then tickle the specific worker thread,
    /// which should be the one that owns this latch.
    #[inline]
    pub(super) unsafe fn set_and_tickle_one(
        this: *const Self,
        registry: &Registry,
        target_worker_index: usize,
    ) {
        if CoreLatch::set(&(*this).core_latch) {
            registry.notify_worker_latch_is_set(target_worker_index);
        }
    }
}

impl AsCoreLatch for OnceLatch {
    #[inline]
    fn as_core_latch(&self) -> &CoreLatch {
        &self.core_latch
    }
}

/// Counting latches are used to implement scopes. They track a
/// counter. Unlike other latches, calling `set()` does not
/// necessarily make the latch be considered `set()`; instead, it just
/// decrements the counter. The latch is only "set" (in the sense that
/// `probe()` returns true) once the counter reaches zero.
#[derive(Debug)]
pub(super) struct CountLatch {
    counter: AtomicUsize,
    kind: CountLatchKind,
}

enum CountLatchKind {
    /// A latch for scopes created on a rayon thread which will participate in work
    /// stealing while it waits for completion. This thread is not necessarily part
    /// of the same registry as the scope itself!
    Stealing {
        latch: CoreLatch,
        /// If a worker thread in registry A calls `in_place_scope` on a ThreadPool
        /// with registry B, when a job completes in a thread of registry B, we may
        /// need to call `notify_worker_latch_is_set()` to wake the thread in registry A.
        /// That means we need a reference to registry A (since at that point we will
        /// only have a reference to registry B), so we stash it here.
        registry: Arc<Registry>,
        /// The index of the worker to wake in `registry`
        worker_index: usize,
    },

    /// A latch for scopes created on a non-rayon thread which will block to wait.
    Blocking { latch: LockLatch },
}

impl std::fmt::Debug for CountLatchKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            CountLatchKind::Stealing { latch, .. } => {
                f.debug_tuple("Stealing").field(latch).finish()
            }
            CountLatchKind::Blocking { latch, .. } => {
                f.debug_tuple("Blocking").field(latch).finish()
            }
        }
    }
}

impl CountLatch {
    pub(super) fn new(owner: Option<&WorkerThread>) -> Self {
        Self::with_count(1, owner)
    }

    pub(super) fn with_count(count: usize, owner: Option<&WorkerThread>) -> Self {
        Self {
            counter: AtomicUsize::new(count),
            kind: match owner {
                Some(owner) => CountLatchKind::Stealing {
                    latch: CoreLatch::new(),
                    registry: Arc::clone(owner.registry()),
                    worker_index: owner.index(),
                },
                None => CountLatchKind::Blocking {
                    latch: LockLatch::new(),
                },
            },
        }
    }

    #[inline]
    pub(super) fn increment(&self) {
        let old_counter = self.counter.fetch_add(1, Ordering::Relaxed);
        debug_assert!(old_counter != 0);
    }

    pub(super) fn wait(&self, owner: Option<&WorkerThread>) {
        match &self.kind {
            CountLatchKind::Stealing {
                latch,
                registry,
                worker_index,
            } => unsafe {
                let owner = owner.expect("owner thread");
                debug_assert_eq!(registry.id(), owner.registry().id());
                debug_assert_eq!(*worker_index, owner.index());
                owner.wait_until(latch);
            },
            CountLatchKind::Blocking { latch } => latch.wait(),
        }
    }
}

impl Latch for CountLatch {
    #[inline]
    unsafe fn set(this: *const Self) {
        if (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 {
            // NOTE: Once we call `set` on the internal `latch`,
            // the target may proceed and invalidate `this`!
            match (*this).kind {
                CountLatchKind::Stealing {
                    ref latch,
                    ref registry,
                    worker_index,
                } => {
                    let registry = Arc::clone(registry);
                    if CoreLatch::set(latch) {
                        registry.notify_worker_latch_is_set(worker_index);
                    }
                }
                CountLatchKind::Blocking { ref latch } => LockLatch::set(latch),
            }
        }
    }
}

/// `&L` without any implication of `dereferenceable` for `Latch::set`
pub(super) struct LatchRef<'a, L> {
    inner: *const L,
    marker: PhantomData<&'a L>,
}

impl<L> LatchRef<'_, L> {
    pub(super) fn new(inner: &L) -> LatchRef<'_, L> {
        LatchRef {
            inner,
            marker: PhantomData,
        }
    }
}

unsafe impl<L: Sync> Sync for LatchRef<'_, L> {}

impl<L> Deref for LatchRef<'_, L> {
    type Target = L;

    fn deref(&self) -> &L {
        // SAFETY: if we have &self, the inner latch is still alive
        unsafe { &*self.inner }
    }
}

impl<L: Latch> Latch for LatchRef<'_, L> {
    #[inline]
    unsafe fn set(this: *const Self) {
        L::set((*this).inner);
    }
}


================================================
FILE: rayon-core/src/lib.rs
================================================
//! Rayon-core houses the core stable APIs of Rayon.
//!
//! These APIs have been mirrored in the Rayon crate and it is recommended to use these from there.
//!
//! [`join()`] is used to take two closures and potentially run them in parallel.
//!   - It will run in parallel if task B gets stolen before task A can finish.
//!   - It will run sequentially if task A finishes before task B is stolen and can continue on task B.
//!
//! [`scope()`] creates a scope in which you can run any number of parallel tasks.
//! These tasks can spawn nested tasks and scopes, but given the nature of work stealing, the order of execution can not be guaranteed.
//! The scope will exist until all tasks spawned within the scope have been completed.
//!
//! [`spawn()`] add a task into the 'static' or 'global' scope, or a local scope created by the [`scope()`] function.
//!
//! [`ThreadPool`] can be used to create your own thread pools (using [`ThreadPoolBuilder`]) or to customize the global one.
//! Tasks spawned within the pool (using [`install()`][tpinstall], [`join()`][tpjoin], etc.) will be added to a deque,
//! where it becomes available for work stealing from other threads in the local thread pool.
//!
//! [tpinstall]: ThreadPool::install()
//! [tpjoin]: ThreadPool::join()
//!
//! # Global fallback when threading is unsupported
//!
//! Rayon uses `std` APIs for threading, but some targets have incomplete implementations that
//! always return `Unsupported` errors. The WebAssembly `wasm32-unknown-unknown` and `wasm32-wasi`
//! targets are notable examples of this. Rather than panicking on the unsupported error when
//! creating the implicit global thread pool, Rayon configures a fallback mode instead.
//!
//! This fallback mode mostly functions as if it were using a single-threaded "pool", like setting
//! `RAYON_NUM_THREADS=1`. For example, `join` will execute its two closures sequentially, since
//! there is no other thread to share the work. However, since the pool is not running independent
//! of the main thread, non-blocking calls like `spawn` may not execute at all, unless a lower-
//! priority call like `broadcast` gives them an opening. The fallback mode does not try to emulate
//! anything like thread preemption or `async` task switching, but `yield_now` or `yield_local`
//! can also volunteer execution time.
//!
//! Explicit `ThreadPoolBuilder` methods always report their error without any fallback.
//!
//! # Restricting multiple versions
//!
//! In order to ensure proper coordination between thread pools, and especially
//! to make sure there's only one global thread pool, `rayon-core` is actively
//! restricted from building multiple versions of itself into a single target.
//! You may see a build error like this in violation:
//!
//! ```text
//! error: native library `rayon-core` is being linked to by more
//! than one package, and can only be linked to by one package
//! ```
//!
//! While we strive to keep `rayon-core` semver-compatible, it's still
//! possible to arrive at this situation if different crates have overly
//! restrictive tilde or inequality requirements for `rayon-core`.  The
//! conflicting requirements will need to be resolved before the build will
//! succeed.

#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![deny(unreachable_pub)]
#![warn(rust_2018_idioms)]

use std::any::Any;
use std::env;
use std::error::Error;
use std::fmt;
use std::io;
use std::marker::PhantomData;
use std::str::FromStr;
use std::thread;

#[macro_use]
mod private;

mod broadcast;
mod job;
mod join;
mod latch;
mod registry;
mod scope;
mod sleep;
mod spawn;
mod thread_pool;
mod unwind;

mod compile_fail;
mod test;

pub use self::broadcast::{broadcast, spawn_broadcast, BroadcastContext};
pub use self::join::{join, join_context};
pub use self::registry::ThreadBuilder;
pub use self::scope::{in_place_scope, scope, Scope};
pub use self::scope::{in_place_scope_fifo, scope_fifo, ScopeFifo};
pub use self::spawn::{spawn, spawn_fifo};
pub use self::thread_pool::current_thread_has_pending_tasks;
pub use self::thread_pool::current_thread_index;
pub use self::thread_pool::ThreadPool;
pub use self::thread_pool::{yield_local, yield_now, Yield};

#[cfg(not(feature = "web_spin_lock"))]
use std::sync;

#[cfg(feature = "web_spin_lock")]
use wasm_sync as sync;

use self::registry::{CustomSpawn, DefaultSpawn, ThreadSpawn};

/// Returns the maximum number of threads that Rayon supports in a single thread pool.
///
/// If a higher thread count is requested by calling `ThreadPoolBuilder::num_threads` or by setting
/// the `RAYON_NUM_THREADS` environment variable, then it will be reduced to this maximum.
///
/// The value may vary between different targets, and is subject to change in new Rayon versions.
pub fn max_num_threads() -> usize {
    // We are limited by the bits available in the sleep counter's `AtomicUsize`.
    crate::sleep::THREADS_MAX
}

/// Returns the number of threads in the current registry. If this
/// code is executing within a Rayon thread pool, then this will be
/// the number of threads for the thread pool of the current
/// thread. Otherwise, it will be the number of threads for the global
/// thread pool.
///
/// This can be useful when trying to judge how many times to split
/// parallel work (the parallel iterator traits use this value
/// internally for this purpose).
///
/// # Future compatibility note
///
/// Note that unless this thread pool was created with a
/// builder that specifies the number of threads, then this
/// number may vary over time in future versions (see [the
/// `num_threads()` method for details][snt]).
///
/// [snt]: ThreadPoolBuilder::num_threads
pub fn current_num_threads() -> usize {
    crate::registry::Registry::current_num_threads()
}

/// Error when initializing a thread pool.
#[derive(Debug)]
pub struct ThreadPoolBuildError {
    kind: ErrorKind,
}

#[derive(Debug)]
enum ErrorKind {
    GlobalPoolAlreadyInitialized,
    CurrentThreadAlreadyInPool,
    IOError(io::Error),
}

/// Used to create a new [`ThreadPool`] or to configure the global rayon thread pool.
/// ## Creating a ThreadPool
/// The following creates a thread pool with 22 threads.
///
/// ```ignore-wasm
/// # use rayon_core as rayon;
/// let pool = rayon::ThreadPoolBuilder::new().num_threads(22).build().unwrap();
/// ```
///
/// To instead configure the global thread pool, use [`build_global()`]:
///
/// ```ignore-wasm
/// # use rayon_core as rayon;
/// rayon::ThreadPoolBuilder::new().num_threads(22).build_global().unwrap();
/// ```
///
/// [`build_global()`]: Self::build_global()
pub struct ThreadPoolBuilder<S = DefaultSpawn> {
    /// The number of threads in the rayon thread pool.
    /// If zero will use the RAYON_NUM_THREADS environment variable.
    /// If RAYON_NUM_THREADS is invalid or zero will use the default.
    num_threads: usize,

    /// The thread we're building *from* will also be part of the pool.
    use_current_thread: bool,

    /// Custom closure, if any, to handle a panic that we cannot propagate
    /// anywhere else.
    panic_handler: Option<Box<PanicHandler>>,

    /// Closure to compute the name of a thread.
    get_thread_name: Option<Box<dyn FnMut(usize) -> String>>,

    /// The stack size for the created worker threads
    stack_size: Option<usize>,

    /// Closure invoked on worker-thread start.
    start_handler: Option<Box<StartHandler>>,

    /// Closure invoked on worker-thread exit.
    exit_handler: Option<Box<ExitHandler>>,

    /// Closure invoked to spawn threads.
    spawn_handler: S,

    /// If false, worker threads will execute spawned jobs in a
    /// "depth-first" fashion. If true, they will do a "breadth-first"
    /// fashion. Depth-first is the default.
    breadth_first: bool,
}

/// Contains the rayon thread pool configuration. Use [`ThreadPoolBuilder`] instead.
#[deprecated(note = "Use `ThreadPoolBuilder`")]
#[derive(Default)]
pub struct Configuration {
    builder: ThreadPoolBuilder,
}

/// The type for a panic-handling closure. Note that this same closure
/// may be invoked multiple times in parallel.
type PanicHandler = dyn Fn(Box<dyn Any + Send>) + Send + Sync;

/// The type for a closure that gets invoked when a thread starts. The
/// closure is passed the index of the thread on which it is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type StartHandler = dyn Fn(usize) + Send + Sync;

/// The type for a closure that gets invoked when a thread exits. The
/// closure is passed the index of the thread on which it is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type ExitHandler = dyn Fn(usize) + Send + Sync;

// NB: We can't `#[derive(Default)]` because `S` is left ambiguous.
impl Default for ThreadPoolBuilder {
    fn default() -> Self {
        ThreadPoolBuilder {
            num_threads: 0,
            use_current_thread: false,
            panic_handler: None,
            get_thread_name: None,
            stack_size: None,
            start_handler: None,
            exit_handler: None,
            spawn_handler: DefaultSpawn,
            breadth_first: false,
        }
    }
}

impl ThreadPoolBuilder {
    /// Creates and returns a valid rayon thread pool builder, but does not initialize it.
    pub fn new() -> Self {
        Self::default()
    }
}

/// Note: the `S: ThreadSpawn` constraint is an internal implementation detail for the
/// default spawn and those set by [`spawn_handler`](#method.spawn_handler).
impl<S> ThreadPoolBuilder<S>
where
    S: ThreadSpawn,
{
    /// Creates a new `ThreadPool` initialized using this configuration.
    pub fn build(self) -> Result<ThreadPool, ThreadPoolBuildError> {
        ThreadPool::build(self)
    }

    /// Initializes the global thread pool. This initialization is
    /// **optional**.  If you do not call this function, the thread pool
    /// will be automatically initialized with the default
    /// configuration. Calling `build_global` is not recommended, except
    /// in two scenarios:
    ///
    /// - You wish to change the default configuration.
    /// - You are running a benchmark, in which case initializing may
    ///   yield slightly more consistent results, since the worker threads
    ///   will already be ready to go even in the first iteration.  But
    ///   this cost is minimal.
    ///
    /// Initialization of the global thread pool happens exactly
    /// once. Once started, the configuration cannot be
    /// changed. Therefore, if you call `build_global` a second time, it
    /// will return an error. An `Ok` result indicates that this
    /// is the first initialization of the thread pool.
    pub fn build_global(self) -> Result<(), ThreadPoolBuildError> {
        let registry = registry::init_global_registry(self)?;
        registry.wait_until_primed();
        Ok(())
    }
}

impl ThreadPoolBuilder {
    /// Creates a scoped `ThreadPool` initialized using this configuration.
    ///
    /// This is a convenience function for building a pool using [`std::thread::scope`]
    /// to spawn threads in a [`spawn_handler`].
    /// The threads in this pool will start by calling `wrapper`, which should
    /// do initialization and continue by calling `ThreadBuilder::run()`.
    ///
    /// [`spawn_handler`]: Self::spawn_handler()
    ///
    /// # Examples
    ///
    /// A scoped pool may be useful in combination with scoped thread-local variables.
    ///
    /// ```ignore-wasm
    /// # use rayon_core as rayon;
    ///
    /// scoped_tls::scoped_thread_local!(static POOL_DATA: Vec<i32>);
    ///
    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
    ///     let pool_data = vec![1, 2, 3];
    ///
    ///     // We haven't assigned any TLS data yet.
    ///     assert!(!POOL_DATA.is_set());
    ///
    ///     rayon::ThreadPoolBuilder::new()
    ///         .build_scoped(
    ///             // Borrow `pool_data` in TLS for each thread.
    ///             |thread| POOL_DATA.set(&pool_data, || thread.run()),
    ///             // Do some work that needs the TLS data.
    ///             |pool| pool.install(|| assert!(POOL_DATA.is_set())),
    ///         )?;
    ///
    ///     // Once we've returned, `pool_data` is no longer borrowed.
    ///     drop(pool_data);
    ///     Ok(())
    /// }
    /// ```
    pub fn build_scoped<W, F, R>(self, wrapper: W, with_pool: F) -> Result<R, ThreadPoolBuildError>
    where
        W: Fn(ThreadBuilder) + Sync, // expected to call `run()`
        F: FnOnce(&ThreadPool) -> R,
    {
        std::thread::scope(|scope| {
            let pool = self
                .spawn_handler(|thread| {
                    let mut builder = std::thread::Builder::new();
                    if let Some(name) = thread.name() {
                        builder = builder.name(name.to_string());
                    }
                    if let Some(size) = thread.stack_size() {
                        builder = builder.stack_size(size);
                    }
                    builder.spawn_scoped(scope, || wrapper(thread))?;
                    Ok(())
                })
                .build()?;
            Ok(with_pool(&pool))
        })
    }
}

impl<S> ThreadPoolBuilder<S> {
    /// Sets a custom function for spawning threads.
    ///
    /// Note that the threads will not exit until after the pool is dropped. It
    /// is up to the caller to wait for thread termination if that is important
    /// for any invariants. For instance, threads created in [`std::thread::scope`]
    /// will be joined before that scope returns, and this will block indefinitely
    /// if the pool is leaked. Furthermore, the global thread pool doesn't terminate
    /// until the entire process exits!
    ///
    /// # Examples
    ///
    /// A minimal spawn handler just needs to call `run()` from an independent thread.
    ///
    /// ```ignore-wasm
    /// # use rayon_core as rayon;
    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
    ///     let pool = rayon::ThreadPoolBuilder::new()
    ///         .spawn_handler(|thread| {
    ///             std::thread::spawn(|| thread.run());
    ///             Ok(())
    ///         })
    ///         .build()?;
    ///
    ///     pool.install(|| println!("Hello from my custom thread!"));
    ///     Ok(())
    /// }
    /// ```
    ///
    /// The default spawn handler sets the name and stack size if given, and propagates
    /// any errors from the thread builder.
    ///
    /// ```ignore-wasm
    /// # use rayon_core as rayon;
    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
    ///     let pool = rayon::ThreadPoolBuilder::new()
    ///         .spawn_handler(|thread| {
    ///             let mut b = std::thread::Builder::new();
    ///             if let Some(name) = thread.name() {
    ///                 b = b.name(name.to_owned());
    ///             }
    ///             if let Some(stack_size) = thread.stack_size() {
    ///                 b = b.stack_size(stack_size);
    ///             }
    ///             b.spawn(|| thread.run())?;
    ///             Ok(())
    ///         })
    ///         .build()?;
    ///
    ///     pool.install(|| println!("Hello from my fully custom thread!"));
    ///     Ok(())
    /// }
    /// ```
    ///
    /// This can also be used for a pool of scoped threads like [`crossbeam::scope`],
    /// or [`std::thread::scope`] introduced in Rust 1.63, which is encapsulated in
    /// [`build_scoped`].
    ///
    /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.8/crossbeam/fn.scope.html
    /// [`build_scoped`]: Self::build_scoped()
    ///
    /// ```ignore-wasm
    /// # use rayon_core as rayon;
    /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
    ///     std::thread::scope(|scope| {
    ///         let pool = rayon::ThreadPoolBuilder::new()
    ///             .spawn_handler(|thread| {
    ///                 let mut builder = std::thread::Builder::new();
    ///                 if let Some(name) = thread.name() {
    ///                     builder = builder.name(name.to_string());
    ///                 }
    ///                 if let Some(size) = thread.stack_size() {
    ///                     builder = builder.stack_size(size);
    ///                 }
    ///                 builder.spawn_scoped(scope, || {
    ///                     // Add any scoped initialization here, then run!
    ///                     thread.run()
    ///                 })?;
    ///                 Ok(())
    ///             })
    ///             .build()?;
    ///
    ///         pool.install(|| println!("Hello from my custom scoped thread!"));
    ///         Ok(())
    ///     })
    /// }
    /// ```
    pub fn spawn_handler<F>(self, spawn: F) -> ThreadPoolBuilder<CustomSpawn<F>>
    where
        F: FnMut(ThreadBuilder) -> io::Result<()>,
    {
        ThreadPoolBuilder {
            spawn_handler: CustomSpawn::new(spawn),
            // ..self
            num_threads: self.num_threads,
            use_current_thread: self.use_current_thread,
            panic_handler: self.panic_handler,
            get_thread_name: self.get_thread_name,
            stack_size: self.stack_size,
            start_handler: self.start_handler,
            exit_handler: self.exit_handler,
            breadth_first: self.breadth_first,
        }
    }

    /// Returns a reference to the current spawn handler.
    fn get_spawn_handler(&mut self) -> &mut S {
        &mut self.spawn_handler
    }

    /// Get the number of threads that will be used for the thread
    /// pool. See `num_threads()` for more information.
    fn get_num_threads(&self) -> usize {
        if self.num_threads > 0 {
            self.num_threads
        } else {
            let default = || {
                thread::available_parallelism()
                    .map(|n| n.get())
                    .unwrap_or(1)
            };

            match env::var("RAYON_NUM_THREADS")
                .ok()
                .and_then(|s| usize::from_str(&s).ok())
            {
                Some(x @ 1..) => return x,
                Some(0) => return default(),
                _ => {}
            }

            // Support for deprecated `RAYON_RS_NUM_CPUS`.
            match env::var("RAYON_RS_NUM_CPUS")
                .ok()
                .and_then(|s| usize::from_str(&s).ok())
            {
                Some(x @ 1..) => x,
                _ => default(),
            }
        }
    }

    /// Get the thread name for the thread with the given index.
    fn get_thread_name(&mut self, index: usize) -> Option<String> {
        let f = self.get_thread_name.as_mut()?;
        Some(f(index))
    }

    /// Sets a closure which takes a thread index and returns
    /// the thread's name.
    pub fn thread_name<F>(mut self, closure: F) -> Self
    where
        F: FnMut(usize) -> String + 'static,
    {
        self.get_thread_name = Some(Box::new(closure));
        self
    }

    /// Sets the number of threads to be used in the rayon thread pool.
    ///
    /// If you specify a non-zero number of threads using this
    /// function, then the resulting thread pools are guaranteed to
    /// start at most this number of threads.
    ///
    /// If `num_threads` is 0, or you do not call this function, then
    /// the Rayon runtime will select the number of threads
    /// automatically. At present, this is based on the
    /// `RAYON_NUM_THREADS` environment variable (if set),
    /// or the number of logical CPUs (otherwise).
    /// In the future, however, the default behavior may
    /// change to dynamically add or remove threads as needed.
    ///
    /// **Future compatibility warning:** Given the default behavior
    /// may change in the future, if you wish to rely on a fixed
    /// number of threads, you should use this function to specify
    /// that number. To reproduce the current default behavior, you
    /// may wish to use [`std::thread::available_parallelism`]
    /// to query the number of CPUs dynamically.
    ///
    /// **Old environment variable:** `RAYON_NUM_THREADS` is a one-to-one
    /// replacement of the now deprecated `RAYON_RS_NUM_CPUS` environment
    /// variable. If both variables are specified, `RAYON_NUM_THREADS` will
    /// be preferred.
    pub fn num_threads(mut self, num_threads: usize) -> Self {
        self.num_threads = num_threads;
        self
    }

    /// Use the current thread as one of the threads in the pool.
    ///
    /// The current thread is guaranteed to be at index 0, and since the thread is not managed by
    /// rayon, the spawn and exit handlers do not run for that thread.
    ///
    /// Note that the current thread won't run the main work-stealing loop, so jobs spawned into
    /// the thread pool will generally not be picked up automatically by this thread unless you
    /// yield to rayon in some way, like via [`yield_now()`], [`yield_local()`], or [`scope()`].
    ///
    /// # Local thread pools
    ///
    /// Using this in a local thread pool means the registry will be leaked. In future versions
    /// there might be a way of cleaning up the current-thread state.
    pub fn use_current_thread(mut self) -> Self {
        self.use_current_thread = true;
        self
    }

    /// Returns a copy of the current panic handler.
    fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {
        self.panic_handler.take()
    }

    /// Normally, whenever Rayon catches a panic, it tries to
    /// propagate it to someplace sensible, to try and reflect the
    /// semantics of sequential execution. But in some cases,
    /// particularly with the `spawn()` APIs, there is no
    /// obvious place where we should propagate the panic to.
    /// In that case, this panic handler is invoked.
    ///
    /// If no panic handler is set, the default is to abort the
    /// process, under the principle that panics should not go
    /// unobserved.
    ///
    /// If the panic handler itself panics, this will abort the
    /// process. To prevent this, wrap the body of your panic handler
    /// in a call to `std::panic::catch_unwind()`.
    pub fn panic_handler<H>(mut self, panic_handler: H) -> Self
    where
        H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,
    {
        self.panic_handler = Some(Box::new(panic_handler));
        self
    }

    /// Get the stack size of the worker threads
    fn get_stack_size(&self) -> Option<usize> {
        self.stack_size
    }

    /// Sets the stack size of the worker threads
    pub fn stack_size(mut self, stack_size: usize) -> Self {
        self.stack_size = Some(stack_size);
        self
    }

    /// **(DEPRECATED)** Suggest to worker threads that they execute
    /// spawned jobs in a "breadth-first" fashion.
    ///
    /// Typically, when a worker thread is idle or blocked, it will
    /// attempt to execute the job from the *top* of its local deque of
    /// work (i.e., the job most recently spawned). If this flag is set
    /// to true, however, workers will prefer to execute in a
    /// *breadth-first* fashion -- that is, they will search for jobs at
    /// the *bottom* of their local deque. (At present, workers *always*
    /// steal from the bottom of other workers' deques, regardless of
    /// the setting of this flag.)
    ///
    /// If you think of the tasks as a tree, where a parent task
    /// spawns its children in the tree, then this flag loosely
    /// corresponds to doing a breadth-first traversal of the tree,
    /// whereas the default would be to do a depth-first traversal.
    ///
    /// **Note that this is an "execution hint".** Rayon's task
    /// execution is highly dynamic and the precise order in which
    /// independent tasks are executed is not intended to be
    /// guaranteed.
    ///
    /// This `breadth_first()` method is now deprecated per [RFC #1],
    /// and in the future its effect may be removed. Consider using
    /// [`scope_fifo()`] for a similar effect.
    ///
    /// [RFC #1]: https://github.com/rayon-rs/rfcs/blob/main/accepted/rfc0001-scope-scheduling.md
    #[deprecated(note = "use `scope_fifo` and `spawn_fifo` for similar effect")]
    pub fn breadth_first(mut self) -> Self {
        self.breadth_first = true;
        self
    }

    fn get_breadth_first(&self) -> bool {
        self.breadth_first
    }

    /// Takes the current thread start callback, leaving `None`.
    fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {
        self.start_handler.take()
    }

    /// Sets a callback to be invoked on thread start.
    ///
    /// The closure is passed the index of the thread on which it is invoked.
    /// Note that this same closure may be invoked multiple times in parallel.
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then startup will continue normally.
    pub fn start_handler<H>(mut self, start_handler: H) -> Self
    where
        H: Fn(usize) + Send + Sync + 'static,
    {
        self.start_handler = Some(Box::new(start_handler));
        self
    }

    /// Returns a current thread exit callback, leaving `None`.
    fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {
        self.exit_handler.take()
    }

    /// Sets a callback to be invoked on thread exit.
    ///
    /// The closure is passed the index of the thread on which it is invoked.
    /// Note that this same closure may be invoked multiple times in parallel.
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then the thread will exit normally.
    pub fn exit_handler<H>(mut self, exit_handler: H) -> Self
    where
        H: Fn(usize) + Send + Sync + 'static,
    {
        self.exit_handler = Some(Box::new(exit_handler));
        self
    }
}

#[allow(deprecated)]
impl Configuration {
    /// Creates and return a valid rayon thread pool configuration, but does not initialize it.
    pub fn new() -> Configuration {
        Configuration {
            builder: ThreadPoolBuilder::new(),
        }
    }

    /// Deprecated in favor of `ThreadPoolBuilder::build`.
    pub fn build(self) -> Result<ThreadPool, Box<dyn Error + 'static>> {
        self.builder.build().map_err(Box::from)
    }

    /// Deprecated in favor of `ThreadPoolBuilder::thread_name`.
    pub fn thread_name<F>(mut self, closure: F) -> Self
    where
        F: FnMut(usize) -> String + 'static,
    {
        self.builder = self.builder.thread_name(closure);
        self
    }

    /// Deprecated in favor of `ThreadPoolBuilder::num_threads`.
    pub fn num_threads(mut self, num_threads: usize) -> Configuration {
        self.builder = self.builder.num_threads(num_threads);
        self
    }

    /// Deprecated in favor of `ThreadPoolBuilder::panic_handler`.
    pub fn panic_handler<H>(mut self, panic_handler: H) -> Configuration
    where
        H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,
    {
        self.builder = self.builder.panic_handler(panic_handler);
        self
    }

    /// Deprecated in favor of `ThreadPoolBuilder::stack_size`.
    pub fn stack_size(mut self, stack_size: usize) -> Self {
        self.builder = self.builder.stack_size(stack_size);
        self
    }

    /// Deprecated in favor of `ThreadPoolBuilder::breadth_first`.
    pub fn breadth_first(mut self) -> Self {
        self.builder = self.builder.breadth_first();
        self
    }

    /// Deprecated in favor of `ThreadPoolBuilder::start_handler`.
    pub fn start_handler<H>(mut self, start_handler: H) -> Configuration
    where
        H: Fn(usize) + Send + Sync + 'static,
    {
        self.builder = self.builder.start_handler(start_handler);
        self
    }

    /// Deprecated in favor of `ThreadPoolBuilder::exit_handler`.
    pub fn exit_handler<H>(mut self, exit_handler: H) -> Configuration
    where
        H: Fn(usize) + Send + Sync + 'static,
    {
        self.builder = self.builder.exit_handler(exit_handler);
        self
    }

    /// Returns a ThreadPoolBuilder with identical parameters.
    fn into_builder(self) -> ThreadPoolBuilder {
        self.builder
    }
}

impl ThreadPoolBuildError {
    fn new(kind: ErrorKind) -> ThreadPoolBuildError {
        ThreadPoolBuildError { kind }
    }

    fn is_unsupported(&self) -> bool {
        matches!(&self.kind, ErrorKind::IOError(e) if e.kind() == io::ErrorKind::Unsupported)
    }
}

const GLOBAL_POOL_ALREADY_INITIALIZED: &str =
    "The global thread pool has already been initialized.";

const CURRENT_THREAD_ALREADY_IN_POOL: &str =
    "The current thread is already part of another thread pool.";

impl Error for ThreadPoolBuildError {
    #[allow(deprecated)]
    fn description(&self) -> &str {
        match self.kind {
            ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED,
            ErrorKind::CurrentThreadAlreadyInPool => CURRENT_THREAD_ALREADY_IN_POOL,
            ErrorKind::IOError(ref e) => e.description(),
        }
    }

    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match &self.kind {
            ErrorKind::GlobalPoolAlreadyInitialized | ErrorKind::CurrentThreadAlreadyInPool => None,
            ErrorKind::IOError(e) => Some(e),
        }
    }
}

impl fmt::Display for ThreadPoolBuildError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self.kind {
            ErrorKind::CurrentThreadAlreadyInPool => CURRENT_THREAD_ALREADY_IN_POOL.fmt(f),
            ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED.fmt(f),
            ErrorKind::IOError(e) => e.fmt(f),
        }
    }
}

/// Deprecated in favor of `ThreadPoolBuilder::build_global`.
#[deprecated(note = "use `ThreadPoolBuilder::build_global`")]
#[allow(deprecated)]
pub fn initialize(config: Configuration) -> Result<(), Box<dyn Error>> {
    config.into_builder().build_global().map_err(Box::from)
}

impl<S> fmt::Debug for ThreadPoolBuilder<S> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let ThreadPoolBuilder {
            ref num_threads,
            ref use_current_thread,
            ref get_thread_name,
            ref panic_handler,
            ref stack_size,
            ref start_handler,
            ref exit_handler,
            spawn_handler: _,
            ref breadth_first,
        } = *self;

        // Just print `Some(<closure>)` or `None` to the debug
        // output.
        struct ClosurePlaceholder;
        impl fmt::Debug for ClosurePlaceholder {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str("<closure>")
            }
        }
        let get_thread_name = get_thread_name.as_ref().map(|_| ClosurePlaceholder);
        let panic_handler = panic_handler.as_ref().map(|_| ClosurePlaceholder);
        let start_handler = start_handler.as_ref().map(|_| ClosurePlaceholder);
        let exit_handler = exit_handler.as_ref().map(|_| ClosurePlaceholder);

        f.debug_struct("ThreadPoolBuilder")
            .field("num_threads", num_threads)
            .field("use_current_thread", use_current_thread)
            .field("get_thread_name", &get_thread_name)
            .field("panic_handler", &panic_handler)
            .field("stack_size", &stack_size)
            .field("start_handler", &start_handler)
            .field("exit_handler", &exit_handler)
            .field("breadth_first", &breadth_first)
            .finish()
    }
}

#[allow(deprecated)]
impl fmt::Debug for Configuration {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.builder.fmt(f)
    }
}

/// Provides the calling context to a closure called by `join_context`.
#[derive(Debug)]
pub struct FnContext {
    migrated: bool,

    /// disable `Send` and `Sync`, just for a little future-proofing.
    _marker: PhantomData<*mut ()>,
}

impl FnContext {
    #[inline]
    fn new(migrated: bool) -> Self {
        FnContext {
            migrated,
            _marker: PhantomData,
        }
    }
}

impl FnContext {
    /// Returns `true` if the closure was called from a different thread
    /// than it was provided from.
    #[inline]
    pub fn migrated(&self) -> bool {
        self.migrated
    }
}


================================================
FILE: rayon-core/src/private.rs
================================================
//! The public parts of this private module are used to create traits
//! that cannot be implemented outside of our own crate.  This way we
//! can feel free to extend those traits without worrying about it
//! being a breaking change for other implementations.

/// If this type is pub but not publicly reachable, third parties
/// can't name it and can't implement traits using it.
#[allow(missing_debug_implementations)]
pub struct PrivateMarker;

macro_rules! private_decl {
    () => {
        /// This trait is private; this method exists to make it
        /// impossible to implement outside the crate.
        #[doc(hidden)]
        fn __rayon_private__(&self) -> crate::private::PrivateMarker;
    };
}

macro_rules! private_impl {
    () => {
        fn __rayon_private__(&self) -> crate::private::PrivateMarker {
            crate::private::PrivateMarker
        }
    };
}


================================================
FILE: rayon-core/src/registry.rs
================================================
use crate::job::{JobFifo, JobRef, StackJob};
use crate::latch::{AsCoreLatch, CoreLatch, Latch, LatchRef, LockLatch, OnceLatch, SpinLatch};
use crate::sleep::Sleep;
use crate::sync::Mutex;
use crate::unwind;
use crate::{
    ErrorKind, ExitHandler, PanicHandler, StartHandler, ThreadPoolBuildError, ThreadPoolBuilder,
    Yield,
};
use crossbeam_deque::{Injector, Steal, Stealer, Worker};
use std::cell::Cell;
use std::fmt;
use std::hash::{DefaultHasher, Hasher};
use std::io;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Once};
use std::thread;

/// Thread builder used for customization via [`ThreadPoolBuilder::spawn_handler()`].
pub struct ThreadBuilder {
    name: Option<String>,
    stack_size: Option<usize>,
    worker: Worker<JobRef>,
    stealer: Stealer<JobRef>,
    registry: Arc<Registry>,
    index: usize,
}

impl ThreadBuilder {
    /// Gets the index of this thread in the pool, within `0..num_threads`.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Gets the string that was specified by `ThreadPoolBuilder::name()`.
    pub fn name(&self) -> Option<&str> {
        self.name.as_deref()
    }

    /// Gets the value that was specified by `ThreadPoolBuilder::stack_size()`.
    pub fn stack_size(&self) -> Option<usize> {
        self.stack_size
    }

    /// Executes the main loop for this thread. This will not return until the
    /// thread pool is dropped.
    pub fn run(self) {
        unsafe { main_loop(self) }
    }
}

impl fmt::Debug for ThreadBuilder {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ThreadBuilder")
            .field("pool", &self.registry.id())
            .field("index", &self.index)
            .field("name", &self.name)
            .field("stack_size", &self.stack_size)
            .finish()
    }
}

/// Generalized trait for spawning a thread in the `Registry`.
///
/// This trait is pub-in-private -- E0445 forces us to make it public,
/// but we don't actually want to expose these details in the API.
pub trait ThreadSpawn {
    private_decl! {}

    /// Spawn a thread with the `ThreadBuilder` parameters, and then
    /// call `ThreadBuilder::run()`.
    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()>;
}

/// Spawns a thread in the "normal" way with `std::thread::Builder`.
///
/// This type is pub-in-private -- E0445 forces us to make it public,
/// but we don't actually want to expose these details in the API.
#[derive(Debug, Default)]
pub struct DefaultSpawn;

impl ThreadSpawn for DefaultSpawn {
    private_impl! {}

    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {
        let mut b = thread::Builder::new();
        if let Some(name) = thread.name() {
            b = b.name(name.to_owned());
        }
        if let Some(stack_size) = thread.stack_size() {
            b = b.stack_size(stack_size);
        }
        b.spawn(|| thread.run())?;
        Ok(())
    }
}

/// Spawns a thread with a user's custom callback.
///
/// This type is pub-in-private -- E0445 forces us to make it public,
/// but we don't actually want to expose these details in the API.
#[derive(Debug)]
pub struct CustomSpawn<F>(F);

impl<F> CustomSpawn<F>
where
    F: FnMut(ThreadBuilder) -> io::Result<()>,
{
    pub(super) fn new(spawn: F) -> Self {
        CustomSpawn(spawn)
    }
}

impl<F> ThreadSpawn for CustomSpawn<F>
where
    F: FnMut(ThreadBuilder) -> io::Result<()>,
{
    private_impl! {}

    #[inline]
    fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {
        (self.0)(thread)
    }
}

pub(super) struct Registry {
    thread_infos: Vec<ThreadInfo>,
    sleep: Sleep,
    injected_jobs: Injector<JobRef>,
    broadcasts: Mutex<Vec<Worker<JobRef>>>,
    panic_handler: Option<Box<PanicHandler>>,
    start_handler: Option<Box<StartHandler>>,
    exit_handler: Option<Box<ExitHandler>>,

    // When this latch reaches 0, it means that all work on this
    // registry must be complete. This is ensured in the following ways:
    //
    // - if this is the global registry, there is a ref-count that never
    //   gets released.
    // - if this is a user-created thread pool, then so long as the thread pool
    //   exists, it holds a reference.
    // - when we inject a "blocking job" into the registry with `ThreadPool::install()`,
    //   no adjustment is needed; the `ThreadPool` holds the reference, and since we won't
    //   return until the blocking job is complete, that ref will continue to be held.
    // - when `join()` or `scope()` is invoked, similarly, no adjustments are needed.
    //   These are always owned by some other job (e.g., one injected by `ThreadPool::install()`)
    //   and that job will keep the pool alive.
    terminate_count: AtomicUsize,
}

// ////////////////////////////////////////////////////////////////////////
// Initialization

static mut THE_REGISTRY: Option<Arc<Registry>> = None;
static THE_REGISTRY_SET: Once = Once::new();

/// Starts the worker threads (if that has not already happened). If
/// initialization has not already occurred, use the default
/// configuration.
pub(super) fn global_registry() -> &'static Arc<Registry> {
    set_global_registry(default_global_registry)
        .or_else(|err| {
            // SAFETY: we only create a shared reference to `THE_REGISTRY` after the `call_once`
            // that initializes it, and there will be no more mutable accesses at all.
            debug_assert!(THE_REGISTRY_SET.is_completed());
            let the_registry = unsafe { &*ptr::addr_of!(THE_REGISTRY) };
            the_registry.as_ref().ok_or(err)
        })
        .expect("The global thread pool has not been initialized.")
}

/// Starts the worker threads (if that has not already happened) with
/// the given builder.
pub(super) fn init_global_registry<S>(
    builder: ThreadPoolBuilder<S>,
) -> Result<&'static Arc<Registry>, ThreadPoolBuildError>
where
    S: ThreadSpawn,
{
    set_global_registry(|| Registry::new(builder))
}

/// Starts the worker threads (if that has not already happened)
/// by creating a registry with the given callback.
fn set_global_registry<F>(registry: F) -> Result<&'static Arc<Registry>, ThreadPoolBuildError>
where
    F: FnOnce() -> Result<Arc<Registry>, ThreadPoolBuildError>,
{
    let mut result = Err(ThreadPoolBuildError::new(
        ErrorKind::GlobalPoolAlreadyInitialized,
    ));

    THE_REGISTRY_SET.call_once(|| {
        result = registry().map(|registry: Arc<Registry>| {
            // SAFETY: this is the only mutable access to `THE_REGISTRY`, thanks to `Once`, and
            // `global_registry()` only takes a shared reference **after** this `call_once`.
            unsafe {
                ptr::addr_of_mut!(THE_REGISTRY).write(Some(registry));
                (*ptr::addr_of!(THE_REGISTRY)).as_ref().unwrap_unchecked()
            }
        })
    });

    result
}

fn default_global_registry() -> Result<Arc<Registry>, ThreadPoolBuildError> {
    let result = Registry::new(ThreadPoolBuilder::new());

    // If we're running in an environment that doesn't support threads at all, we can fall back to
    // using the current thread alone. This is crude, and probably won't work for non-blocking
    // calls like `spawn` or `broadcast_spawn`, but a lot of stuff does work fine.
    //
    // Notably, this allows current WebAssembly targets to work even though their threading support
    // is stubbed out, and we won't have to change anything if they do add real threading.
    let unsupported = matches!(&result, Err(e) if e.is_unsupported());
    if unsupported && WorkerThread::current().is_null() {
        let builder = ThreadPoolBuilder::new().num_threads(1).use_current_thread();
        let fallback_result = Registry::new(builder);
        if fallback_result.is_ok() {
            return fallback_result;
        }
    }

    result
}

struct Terminator<'a>(&'a Arc<Registry>);

impl<'a> Drop for Terminator<'a> {
    fn drop(&mut self) {
        self.0.terminate()
    }
}

impl Registry {
    pub(super) fn new<S>(
        mut builder: ThreadPoolBuilder<S>,
    ) -> Result<Arc<Self>, ThreadPoolBuildError>
    where
        S: ThreadSpawn,
    {
        // Soft-limit the number of threads that we can actually support.
        let n_threads = Ord::min(builder.get_num_threads(), crate::max_num_threads());

        let breadth_first = builder.get_breadth_first();

        let (workers, stealers): (Vec<_>, Vec<_>) = (0..n_threads)
            .map(|_| {
                let worker = if breadth_first {
                    Worker::new_fifo()
                } else {
                    Worker::new_lifo()
                };

                let stealer = worker.stealer();
                (worker, stealer)
            })
            .unzip();

        let (broadcasts, broadcast_stealers): (Vec<_>, Vec<_>) = (0..n_threads)
            .map(|_| {
                let worker = Worker::new_fifo();
                let stealer = worker.stealer();
                (worker, stealer)
            })
            .unzip();

        let registry = Arc::new(Registry {
            thread_infos: stealers.into_iter().map(ThreadInfo::new).collect(),
            sleep: Sleep::new(n_threads),
            injected_jobs: Injector::new(),
            broadcasts: Mutex::new(broadcasts),
            terminate_count: AtomicUsize::new(1),
            panic_handler: builder.take_panic_handler(),
            start_handler: builder.take_start_handler(),
            exit_handler: builder.take_exit_handler(),
        });

        // If we return early or panic, make sure to terminate existing threads.
        let t1000 = Terminator(&registry);

        for (index, (worker, stealer)) in workers.into_iter().zip(broadcast_stealers).enumerate() {
            let thread = ThreadBuilder {
                name: builder.get_thread_name(index),
                stack_size: builder.get_stack_size(),
                registry: Arc::clone(&registry),
                worker,
                stealer,
                index,
            };

            if index == 0 && builder.use_current_thread {
                if !WorkerThread::current().is_null() {
                    return Err(ThreadPoolBuildError::new(
                        ErrorKind::CurrentThreadAlreadyInPool,
                    ));
                }
                // Rather than starting a new thread, we're just taking over the current thread
                // *without* running the main loop, so we can still return from here.
                // The WorkerThread is leaked, but we never shutdown the global pool anyway.
                let worker_thread = Box::into_raw(Box::new(WorkerThread::from(thread)));

                unsafe {
                    WorkerThread::set_current(worker_thread);
                    Latch::set(&registry.thread_infos[index].primed);
                }
                continue;
            }

            if let Err(e) = builder.get_spawn_handler().spawn(thread) {
                return Err(ThreadPoolBuildError::new(ErrorKind::IOError(e)));
            }
        }

        // Returning normally now, without termination.
        mem::forget(t1000);

        Ok(registry)
    }

    pub(super) fn current() -> Arc<Registry> {
        unsafe {
            let worker_thread = WorkerThread::current();
            let registry = if worker_thread.is_null() {
                global_registry()
            } else {
                &(*worker_thread).registry
            };
            Arc::clone(registry)
        }
    }

    /// Returns the number of threads in the current registry.  This
    /// is better than `Registry::current().num_threads()` because it
    /// avoids incrementing the `Arc`.
    pub(super) fn current_num_threads() -> usize {
        unsafe {
            let worker_thread = WorkerThread::current();
            if worker_thread.is_null() {
                global_registry().num_threads()
            } else {
                (*worker_thread).registry.num_threads()
            }
        }
    }

    /// Returns the current `WorkerThread` if it's part of this `Registry`.
    pub(super) fn current_thread(&self) -> Option<&WorkerThread> {
        unsafe {
            let worker = WorkerThread::current().as_ref()?;
            if worker.registry().id() == self.id() {
                Some(worker)
            } else {
                None
            }
        }
    }

    /// Returns an opaque identifier for this registry.
    pub(super) fn id(&self) -> RegistryId {
        // We can rely on `self` not to change since we only ever create
        // registries that are boxed up in an `Arc` (see `new()` above).
        RegistryId {
            addr: self as *const Self as usize,
        }
    }

    pub(super) fn num_threads(&self) -> usize {
        self.thread_infos.len()
    }

    pub(super) fn catch_unwind(&self, f: impl FnOnce()) {
        if let Err(err) = unwind::halt_unwinding(f) {
            // If there is no handler, or if that handler itself panics, then we abort.
            let abort_guard = unwind::AbortIfPanic;
            if let Some(ref handler) = self.panic_handler {
                handler(err);
                mem::forget(abort_guard);
            }
        }
    }

    /// Waits for the worker threads to get up and running.  This is
    /// meant to be used for benchmarking purposes, primarily, so that
    /// you can get more consistent numbers by having everything
    /// "ready to go".
    pub(super) fn wait_until_primed(&self) {
        for info in &self.thread_infos {
            info.primed.wait();
        }
    }

    /// Waits for the worker threads to stop. This is used for testing
    /// -- so we can check that termination actually works.
    #[cfg(test)]
    pub(super) fn wait_until_stopped(&self) {
        for info in &self.thread_infos {
            info.stopped.wait();
        }
    }

    // ////////////////////////////////////////////////////////////////////////
    // MAIN LOOP
    //
    // So long as all of the worker threads are hanging out in their
    // top-level loop, there is no work to be done.

    /// Push a job into the given `registry`. If we are running on a
    /// worker thread for the registry, this will push onto the
    /// deque. Else, it will inject from the outside (which is slower).
    pub(super) fn inject_or_push(&self, job_ref: JobRef) {
        let worker_thread = WorkerThread::current();
        unsafe {
            if !worker_thread.is_null() && (*worker_thread).registry().id() == self.id() {
                (*worker_thread).push(job_ref);
            } else {
                self.inject(job_ref);
            }
        }
    }

    /// Push a job into the "external jobs" queue; it will be taken by
    /// whatever worker has nothing to do. Use this if you know that
    /// you are not on a worker of this registry.
    pub(super) fn inject(&self, injected_job: JobRef) {
        // It should not be possible for `state.terminate` to be true
        // here. It is only set to true when the user creates (and
        // drops) a `ThreadPool`; and, in that case, they cannot be
        // calling `inject()` later, since they dropped their
        // `ThreadPool`.
        debug_assert_ne!(
            self.terminate_count.load(Ordering::Acquire),
            0,
            "inject() sees state.terminate as true"
        );

        let queue_was_empty = self.injected_jobs.is_empty();

        self.injected_jobs.push(injected_job);
        self.sleep.new_injected_jobs(1, queue_was_empty);
    }

    fn has_injected_job(&self) -> bool {
        !self.injected_jobs.is_empty()
    }

    fn pop_injected_job(&self) -> Option<JobRef> {
        loop {
            match self.injected_jobs.steal() {
                Steal::Success(job) => return Some(job),
                Steal::Empty => return None,
                Steal::Retry => {}
            }
        }
    }

    /// Push a job into each thread's own "external jobs" queue; it will be
    /// executed only on that thread, when it has nothing else to do locally,
    /// before it tries to steal other work.
    ///
    /// **Panics** if not given exactly as many jobs as there are threads.
    pub(super) fn inject_broadcast(&self, injected_jobs: impl ExactSizeIterator<Item = JobRef>) {
        assert_eq!(self.num_threads(), injected_jobs.len());
        {
            let broadcasts = self.broadcasts.lock().unwrap();

            // It should not be possible for `state.terminate` to be true
            // here. It is only set to true when the user creates (and
            // drops) a `ThreadPool`; and, in that case, they cannot be
            // calling `inject_broadcast()` later, since they dropped their
            // `ThreadPool`.
            debug_assert_ne!(
                self.terminate_count.load(Ordering::Acquire),
                0,
                "inject_broadcast() sees state.terminate as true"
            );

            assert_eq!(broadcasts.len(), injected_jobs.len());
            for (worker, job_ref) in broadcasts.iter().zip(injected_jobs) {
                worker.push(job_ref);
            }
        }
        for i in 0..self.num_threads() {
            self.sleep.notify_worker_latch_is_set(i);
        }
    }

    /// If already in a worker-thread of this registry, just execute `op`.
    /// Otherwise, inject `op` in this thread pool. Either way, block until `op`
    /// completes and return its return value. If `op` panics, that panic will
    /// be propagated as well.  The second argument indicates `true` if injection
    /// was performed, `false` if executed directly.
    pub(super) fn in_worker<OP, R>(&self, op: OP) -> R
    where
        OP: FnOnce(&WorkerThread, bool) -> R + Send,
        R: Send,
    {
        unsafe {
            let worker_thread = WorkerThread::current();
            if worker_thread.is_null() {
                self.in_worker_cold(op)
            } else if (*worker_thread).registry().id() != self.id() {
                self.in_worker_cross(&*worker_thread, op)
            } else {
                // Perfectly valid to give them a `&T`: this is the
                // current thread, so we know the data structure won't be
                // invalidated until we return.
                op(&*worker_thread, false)
            }
        }
    }

    #[cold]
    unsafe fn in_worker_cold<OP, R>(&self, op: OP) -> R
    where
        OP: FnOnce(&WorkerThread, bool) -> R + Send,
        R: Send,
    {
        thread_local!(static LOCK_LATCH: LockLatch = const { LockLatch::new() });

        LOCK_LATCH.with(|l| {
            // This thread isn't a member of *any* thread pool, so just block.
            debug_assert!(WorkerThread::current().is_null());
            let job = StackJob::new(
                |injected| {
                    let worker_thread = WorkerThread::current();
                    assert!(injected && !worker_thread.is_null());
                    op(&*worker_thread, true)
                },
                LatchRef::new(l),
            );
            self.inject(job.as_job_ref());
            job.latch.wait_and_reset(); // Make sure we can use the same latch again next time.

            job.into_result()
        })
    }

    #[cold]
    unsafe fn in_worker_cross<OP, R>(&self, current_thread: &WorkerThread, op: OP) -> R
    where
        OP: FnOnce(&WorkerThread, bool) -> R + Send,
        R: Send,
    {
        // This thread is a member of a different pool, so let it process
        // other work while waiting for this `op` to complete.
        debug_assert!(current_thread.registry().id() != self.id());
        let latch = SpinLatch::cross(current_thread);
        let job = StackJob::new(
            |injected| {
                let worker_thread = WorkerThread::current();
                assert!(injected && !worker_thread.is_null());
                op(&*worker_thread, true)
            },
            latch,
        );
        self.inject(job.as_job_ref());
        current_thread.wait_until(&job.latch);
        job.into_result()
    }

    /// Increments the terminate counter. This increment should be
    /// balanced by a call to `terminate`, which will decrement. This
    /// is used when spawning asynchronous work, which needs to
    /// prevent the registry from terminating so long as it is active.
    ///
    /// Note that blocking functions such as `join` and `scope` do not
    /// need to concern themselves with this fn; their context is
    /// responsible for ensuring the current thread pool will not
    /// terminate until they return.
    ///
    /// The global thread pool always has an outstanding reference
    /// (the initial one). Custom thread pools have one outstanding
    /// reference that is dropped when the `ThreadPool` is dropped:
    /// since installing the thread pool blocks until any joins/scopes
    /// complete, this ensures that joins/scopes are covered.
    ///
    /// The exception is `::spawn()`, which can create a job outside
    /// of any blocking scope. In that case, the job itself holds a
    /// terminate count and is responsible for invoking `terminate()`
    /// when finished.
    pub(super) fn increment_terminate_count(&self) {
        let previous = self.terminate_count.fetch_add(1, Ordering::AcqRel);
        debug_assert!(previous != 0, "registry ref count incremented from zero");
        assert!(previous != usize::MAX, "overflow in registry ref count");
    }

    /// Signals that the thread pool which owns this registry has been
    /// dropped. The worker threads will gradually terminate, once any
    /// extant work is completed.
    pub(super) fn terminate(&self) {
        if self.terminate_count.fetch_sub(1, Ordering::AcqRel) == 1 {
            for (i, thread_info) in self.thread_infos.iter().enumerate() {
                unsafe { OnceLatch::set_and_tickle_one(&thread_info.terminate, self, i) };
            }
        }
    }

    /// Notify the worker that the latch they are sleeping on has been "set".
    pub(super) fn notify_worker_latch_is_set(&self, target_worker_index: usize) {
        self.sleep.notify_worker_latch_is_set(target_worker_index);
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub(super) struct RegistryId {
    addr: usize,
}

struct ThreadInfo {
    /// Latch set once thread has started and we are entering into the
    /// main loop. Used to wait for worker threads to become primed,
    /// primarily of interest for benchmarking.
    primed: LockLatch,

    /// Latch is set once worker thread has completed. Used to wait
    /// until workers have stopped; only used for tests.
    stopped: LockLatch,

    /// The latch used to signal that terminated has been requested.
    /// This latch is *set* by the `terminate` method on the
    /// `Registry`, once the registry's main "terminate" counter
    /// reaches zero.
    terminate: OnceLatch,

    /// the "stealer" half of the worker's deque
    stealer: Stealer<JobRef>,
}

impl ThreadInfo {
    fn new(stealer: Stealer<JobRef>) -> ThreadInfo {
        ThreadInfo {
            primed: LockLatch::new(),
            stopped: LockLatch::new(),
            terminate: OnceLatch::new(),
            stealer,
        }
    }
}

// ////////////////////////////////////////////////////////////////////////
// WorkerThread identifiers

pub(super) struct WorkerThread {
    /// the "worker" half of our local deque
    worker: Worker<JobRef>,

    /// the "stealer" half of the worker's broadcast deque
    stealer: Stealer<JobRef>,

    /// local queue used for `spawn_fifo` indirection
    fifo: JobFifo,

    index: usize,

    /// A weak random number generator.
    rng: XorShift64Star,

    registry: Arc<Registry>,
}

// This is a bit sketchy, but basically: the WorkerThread is
// allocated on the stack of the worker on entry and stored into this
// thread-local variable. So it will remain valid at least until the
// worker is fully unwound. Using an unsafe pointer avoids the need
// for a RefCell<T> etc.
thread_local! {
    static WORKER_THREAD_STATE: Cell<*const WorkerThread> = const { Cell::new(ptr::null()) };
}

impl From<ThreadBuilder> for WorkerThread {
    fn from(thread: ThreadBuilder) -> Self {
        Self {
            worker: thread.worker,
            stealer: thread.stealer,
            fifo: JobFifo::new(),
            index: thread.index,
            rng: XorShift64Star::new(),
            registry: thread.registry,
        }
    }
}

impl Drop for WorkerThread {
    fn drop(&mut self) {
        // Undo `set_current`
        WORKER_THREAD_STATE.with(|t| {
            assert!(t.get().eq(&(self as *const _)));
            t.set(ptr::null());
        });
    }
}

impl WorkerThread {
    /// Gets the `WorkerThread` index for the current thread; returns
    /// NULL if this is not a worker thread. This pointer is
Download .txt
gitextract_j0otbdne/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── ci.yaml
│       ├── main.yaml
│       └── pr.yaml
├── .gitignore
├── Cargo.toml
├── FAQ.md
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── RELEASES.md
├── ci/
│   ├── alt-core/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   └── src/
│   │       └── lib.rs
│   ├── highlander/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   └── highlander.sh
├── rayon-core/
│   ├── Cargo.toml
│   ├── LICENSE-APACHE
│   ├── LICENSE-MIT
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── broadcast/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── compile_fail/
│   │   │   ├── mod.rs
│   │   │   ├── quicksort_race1.rs
│   │   │   ├── quicksort_race2.rs
│   │   │   ├── quicksort_race3.rs
│   │   │   ├── rc_return.rs
│   │   │   ├── rc_upvar.rs
│   │   │   └── scope_join_bad.rs
│   │   ├── job.rs
│   │   ├── join/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── latch.rs
│   │   ├── lib.rs
│   │   ├── private.rs
│   │   ├── registry.rs
│   │   ├── scope/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── sleep/
│   │   │   ├── README.md
│   │   │   ├── counters.rs
│   │   │   └── mod.rs
│   │   ├── spawn/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── test.rs
│   │   ├── thread_pool/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   └── unwind.rs
│   └── tests/
│       ├── double_init_fail.rs
│       ├── init_zero_threads.rs
│       ├── scope_join.rs
│       ├── scoped_threadpool.rs
│       ├── simple_panic.rs
│       ├── stack_overflow_crash.rs
│       └── use_current_thread.rs
├── rayon-demo/
│   ├── Cargo.toml
│   ├── data/
│   │   ├── README.md
│   │   └── tsp/
│   │       ├── README.md
│   │       ├── dj10.tsp
│   │       ├── dj15.tsp
│   │       └── dj38.tsp
│   ├── examples/
│   │   ├── README.md
│   │   └── cpu_monitor.rs
│   └── src/
│       ├── cpu_time/
│       │   ├── mod.rs
│       │   ├── unix.rs
│       │   └── win.rs
│       ├── factorial/
│       │   └── mod.rs
│       ├── fibonacci/
│       │   └── mod.rs
│       ├── find/
│       │   └── mod.rs
│       ├── join_microbench.rs
│       ├── lib.rs
│       ├── life/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── main.rs
│       ├── map_collect.rs
│       ├── matmul/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── mergesort/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── nbody/
│       │   ├── bench.rs
│       │   ├── mod.rs
│       │   ├── nbody.rs
│       │   └── visualize.rs
│       ├── noop/
│       │   └── mod.rs
│       ├── pythagoras/
│       │   └── mod.rs
│       ├── quicksort/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── sieve/
│       │   ├── bench.rs
│       │   └── mod.rs
│       ├── sort.rs
│       ├── str_split.rs
│       ├── tree.rs
│       ├── tsp/
│       │   ├── bench.rs
│       │   ├── graph.rs
│       │   ├── mod.rs
│       │   ├── parser.rs
│       │   ├── solver.rs
│       │   ├── step.rs
│       │   ├── tour.rs
│       │   └── weight.rs
│       └── vec_collect.rs
├── src/
│   ├── array.rs
│   ├── collections/
│   │   ├── binary_heap.rs
│   │   ├── btree_map.rs
│   │   ├── btree_set.rs
│   │   ├── hash_map.rs
│   │   ├── hash_set.rs
│   │   ├── linked_list.rs
│   │   ├── mod.rs
│   │   └── vec_deque.rs
│   ├── compile_fail/
│   │   ├── cannot_collect_filtermap_data.rs
│   │   ├── cannot_zip_filtered_data.rs
│   │   ├── cell_par_iter.rs
│   │   ├── mod.rs
│   │   ├── must_use.rs
│   │   ├── no_send_par_iter.rs
│   │   └── rc_par_iter.rs
│   ├── delegate.rs
│   ├── iter/
│   │   ├── blocks.rs
│   │   ├── chain.rs
│   │   ├── chunks.rs
│   │   ├── cloned.rs
│   │   ├── collect/
│   │   │   ├── consumer.rs
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── copied.rs
│   │   ├── empty.rs
│   │   ├── enumerate.rs
│   │   ├── extend.rs
│   │   ├── filter.rs
│   │   ├── filter_map.rs
│   │   ├── find.rs
│   │   ├── find_first_last/
│   │   │   ├── mod.rs
│   │   │   └── test.rs
│   │   ├── flat_map.rs
│   │   ├── flat_map_iter.rs
│   │   ├── flatten.rs
│   │   ├── flatten_iter.rs
│   │   ├── fold.rs
│   │   ├── fold_chunks.rs
│   │   ├── fold_chunks_with.rs
│   │   ├── for_each.rs
│   │   ├── from_par_iter.rs
│   │   ├── inspect.rs
│   │   ├── interleave.rs
│   │   ├── interleave_shortest.rs
│   │   ├── intersperse.rs
│   │   ├── len.rs
│   │   ├── map.rs
│   │   ├── map_with.rs
│   │   ├── mod.rs
│   │   ├── multizip.rs
│   │   ├── noop.rs
│   │   ├── once.rs
│   │   ├── panic_fuse.rs
│   │   ├── par_bridge.rs
│   │   ├── plumbing/
│   │   │   ├── README.md
│   │   │   └── mod.rs
│   │   ├── positions.rs
│   │   ├── product.rs
│   │   ├── reduce.rs
│   │   ├── repeat.rs
│   │   ├── rev.rs
│   │   ├── skip.rs
│   │   ├── skip_any.rs
│   │   ├── skip_any_while.rs
│   │   ├── splitter.rs
│   │   ├── step_by.rs
│   │   ├── sum.rs
│   │   ├── take.rs
│   │   ├── take_any.rs
│   │   ├── take_any_while.rs
│   │   ├── test.rs
│   │   ├── try_fold.rs
│   │   ├── try_reduce.rs
│   │   ├── try_reduce_with.rs
│   │   ├── unzip.rs
│   │   ├── update.rs
│   │   ├── walk_tree.rs
│   │   ├── while_some.rs
│   │   ├── zip.rs
│   │   └── zip_eq.rs
│   ├── lib.rs
│   ├── math.rs
│   ├── option.rs
│   ├── par_either.rs
│   ├── prelude.rs
│   ├── private.rs
│   ├── range.rs
│   ├── range_inclusive.rs
│   ├── result.rs
│   ├── slice/
│   │   ├── chunk_by.rs
│   │   ├── chunks.rs
│   │   ├── mod.rs
│   │   ├── rchunks.rs
│   │   ├── sort.rs
│   │   └── test.rs
│   ├── split_producer.rs
│   ├── str.rs
│   ├── string.rs
│   └── vec.rs
└── tests/
    ├── chars.rs
    ├── clones.rs
    ├── collect.rs
    ├── cross-pool.rs
    ├── debug.rs
    ├── drain_vec.rs
    ├── intersperse.rs
    ├── issue671-unzip.rs
    ├── issue671.rs
    ├── iter_panic.rs
    ├── named-threads.rs
    ├── octillion.rs
    ├── par_bridge_recursion.rs
    ├── producer_split_at.rs
    ├── sort-panic-safe.rs
    └── str.rs
Download .txt
Showing preview only (244K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3282 symbols across 173 files)

FILE: ci/alt-core/build.rs
  function main (line 1) | fn main() {}

FILE: ci/highlander/src/main.rs
  function main (line 1) | fn main() {}

FILE: rayon-core/build.rs
  function main (line 4) | fn main() {

FILE: rayon-core/src/broadcast/mod.rs
  function broadcast (line 19) | pub fn broadcast<OP, R>(op: OP) -> Vec<R>
  function spawn_broadcast (line 36) | pub fn spawn_broadcast<OP>(op: OP)
  type BroadcastContext (line 45) | pub struct BroadcastContext<'a> {
  function with (line 53) | pub(super) fn with<R>(f: impl FnOnce(BroadcastContext<'_>) -> R) -> R {
  function index (line 64) | pub fn index(&self) -> usize {
  function num_threads (line 76) | pub fn num_threads(&self) -> usize {
  function fmt (line 82) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
  function broadcast_in (line 97) | pub(super) unsafe fn broadcast_in<OP, R>(op: OP, registry: &Arc<Registry...
  function spawn_broadcast_in (line 128) | pub(super) unsafe fn spawn_broadcast_in<OP>(op: OP, registry: &Arc<Regis...

FILE: rayon-core/src/broadcast/test.rs
  function broadcast_global (line 10) | fn broadcast_global() {
  function spawn_broadcast_global (line 17) | fn spawn_broadcast_global() {
  function broadcast_pool (line 28) | fn broadcast_pool() {
  function spawn_broadcast_pool (line 36) | fn spawn_broadcast_pool() {
  function broadcast_self (line 48) | fn broadcast_self() {
  function spawn_broadcast_self (line 56) | fn spawn_broadcast_self() {
  function broadcast_mutual (line 68) | fn broadcast_mutual() {
  function spawn_broadcast_mutual (line 84) | fn spawn_broadcast_mutual() {
  function broadcast_mutual_sleepy (line 102) | fn broadcast_mutual_sleepy() {
  function spawn_broadcast_mutual_sleepy (line 121) | fn spawn_broadcast_mutual_sleepy() {
  function broadcast_panic_one (line 144) | fn broadcast_panic_one() {
  function spawn_broadcast_panic_one (line 161) | fn spawn_broadcast_panic_one() {
  function broadcast_panic_many (line 182) | fn broadcast_panic_many() {
  function spawn_broadcast_panic_many (line 199) | fn spawn_broadcast_panic_many() {
  function broadcast_sleep_race (line 220) | fn broadcast_sleep_race() {
  function broadcast_after_spawn_broadcast (line 234) | fn broadcast_after_spawn_broadcast() {
  function broadcast_after_spawn (line 250) | fn broadcast_after_spawn() {

FILE: rayon-core/src/job.rs
  type JobResult (line 9) | pub(super) enum JobResult<T> {
  type Job (line 20) | pub(super) trait Job {
    method execute (line 24) | unsafe fn execute(this: *const ());
    method execute (line 116) | unsafe fn execute(this: *const ()) {
    method execute (line 167) | unsafe fn execute(this: *const ()) {
    method execute (line 210) | unsafe fn execute(this: *const ()) {
    method execute (line 259) | unsafe fn execute(this: *const ()) {
  type JobRef (line 33) | pub(super) struct JobRef {
    method new (line 44) | pub(super) unsafe fn new<T>(data: *const T) -> JobRef
    method id (line 58) | pub(super) fn id(&self) -> impl Eq {
    method execute (line 63) | pub(super) unsafe fn execute(self) {
  type StackJob (line 72) | pub(super) struct StackJob<L, F, R>
  function new (line 89) | pub(super) fn new(func: F, latch: L) -> StackJob<L, F, R> {
  function as_job_ref (line 97) | pub(super) unsafe fn as_job_ref(&self) -> JobRef {
  function run_inline (line 101) | pub(super) unsafe fn run_inline(self, stolen: bool) -> R {
  function into_result (line 105) | pub(super) unsafe fn into_result(self) -> R {
  type HeapJob (line 132) | pub(super) struct HeapJob<BODY>
  function new (line 143) | pub(super) fn new(job: BODY) -> Box<Self> {
  function into_job_ref (line 150) | pub(super) unsafe fn into_job_ref(self: Box<Self>) -> JobRef {
  function into_static_job_ref (line 155) | pub(super) fn into_static_job_ref(self: Box<Self>) -> JobRef
  type ArcJob (line 175) | pub(super) struct ArcJob<BODY>
  function new (line 186) | pub(super) fn new(job: BODY) -> Arc<Self> {
  function as_job_ref (line 193) | pub(super) unsafe fn as_job_ref(this: &Arc<Self>) -> JobRef {
  function as_static_job_ref (line 198) | pub(super) fn as_static_job_ref(this: &Arc<Self>) -> JobRef
  function call (line 217) | fn call(func: impl FnOnce(bool) -> T) -> Self {
  function into_return_value (line 228) | pub(super) fn into_return_value(self) -> T {
  type JobFifo (line 238) | pub(super) struct JobFifo {
    method new (line 243) | pub(super) fn new() -> Self {
    method push (line 249) | pub(super) unsafe fn push(&self, job_ref: JobRef) -> JobRef {

FILE: rayon-core/src/join/mod.rs
  function join (line 93) | pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
  function join_context (line 115) | pub fn join_context<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
  function join_recover_from_panic (line 179) | unsafe fn join_recover_from_panic(

FILE: rayon-core/src/join/test.rs
  function quick_sort (line 9) | fn quick_sort<T: PartialOrd + Send>(v: &mut [T]) {
  function partition (line 19) | fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
  function seeded_rng (line 32) | fn seeded_rng() -> XorShiftRng {
  function sort (line 39) | fn sort() {
  function sort_in_pool (line 50) | fn sort_in_pool() {
  function panic_propagate_a (line 63) | fn panic_propagate_a() {
  function panic_propagate_b (line 69) | fn panic_propagate_b() {
  function panic_propagate_both (line 75) | fn panic_propagate_both() {
  function panic_b_still_executes (line 81) | fn panic_b_still_executes() {
  function join_context_both (line 91) | fn join_context_both() {
  function join_context_neither (line 100) | fn join_context_neither() {
  function join_context_second (line 111) | fn join_context_second() {
  function join_counter_overflow (line 135) | fn join_counter_overflow() {

FILE: rayon-core/src/latch.rs
  type Latch (line 35) | pub(super) trait Latch {
    method set (line 50) | unsafe fn set(this: *const Self);
    method set (line 196) | unsafe fn set(this: *const Self) {
    method set (line 262) | unsafe fn set(this: *const Self) {
    method set (line 405) | unsafe fn set(this: *const Self) {
    method set (line 454) | unsafe fn set(this: *const Self) {
  type AsCoreLatch (line 53) | pub(super) trait AsCoreLatch {
    method as_core_latch (line 54) | fn as_core_latch(&self) -> &CoreLatch;
    method as_core_latch (line 140) | fn as_core_latch(&self) -> &CoreLatch {
    method as_core_latch (line 189) | fn as_core_latch(&self) -> &CoreLatch {
    method as_core_latch (line 310) | fn as_core_latch(&self) -> &CoreLatch {
  constant UNSET (line 58) | const UNSET: usize = 0;
  constant SLEEPY (line 62) | const SLEEPY: usize = 1;
  constant SLEEPING (line 66) | const SLEEPING: usize = 2;
  constant SET (line 69) | const SET: usize = 3;
  type CoreLatch (line 75) | pub(super) struct CoreLatch {
    method new (line 81) | fn new() -> Self {
    method get_sleepy (line 91) | pub(super) fn get_sleepy(&self) -> bool {
    method fall_asleep (line 101) | pub(super) fn fall_asleep(&self) -> bool {
    method wake_up (line 111) | pub(super) fn wake_up(&self) {
    method set (line 126) | unsafe fn set(this: *const Self) -> bool {
    method probe (line 133) | pub(super) fn probe(&self) -> bool {
  type SpinLatch (line 148) | pub(super) struct SpinLatch<'r> {
  function new (line 161) | pub(super) fn new(thread: &'r WorkerThread) -> SpinLatch<'r> {
  function cross (line 174) | pub(super) fn cross(thread: &'r WorkerThread) -> SpinLatch<'r> {
  function probe (line 182) | pub(super) fn probe(&self) -> bool {
  type LockLatch (line 228) | pub(super) struct LockLatch {
    method new (line 235) | pub(super) const fn new() -> LockLatch {
    method wait_and_reset (line 243) | pub(super) fn wait_and_reset(&self) {
    method wait (line 252) | pub(super) fn wait(&self) {
  type OnceLatch (line 282) | pub(super) struct OnceLatch {
    method new (line 288) | pub(super) fn new() -> OnceLatch {
    method set_and_tickle_one (line 297) | pub(super) unsafe fn set_and_tickle_one(
  type CountLatch (line 321) | pub(super) struct CountLatch {
    method new (line 360) | pub(super) fn new(owner: Option<&WorkerThread>) -> Self {
    method with_count (line 364) | pub(super) fn with_count(count: usize, owner: Option<&WorkerThread>) -...
    method increment (line 381) | pub(super) fn increment(&self) {
    method wait (line 386) | pub(super) fn wait(&self, owner: Option<&WorkerThread>) {
  type CountLatchKind (line 326) | enum CountLatchKind {
    method fmt (line 347) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type LatchRef (line 427) | pub(super) struct LatchRef<'a, L> {
  function new (line 433) | pub(super) fn new(inner: &L) -> LatchRef<'_, L> {
  type Target (line 444) | type Target = L;
  method deref (line 446) | fn deref(&self) -> &L {

FILE: rayon-core/src/lib.rs
  function max_num_threads (line 113) | pub fn max_num_threads() -> usize {
  function current_num_threads (line 136) | pub fn current_num_threads() -> usize {
  type ThreadPoolBuildError (line 142) | pub struct ThreadPoolBuildError {
    method new (line 741) | fn new(kind: ErrorKind) -> ThreadPoolBuildError {
    method is_unsupported (line 745) | fn is_unsupported(&self) -> bool {
    method fmt (line 775) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type ErrorKind (line 147) | enum ErrorKind {
  type ThreadPoolBuilder (line 170) | pub struct ThreadPoolBuilder<S = DefaultSpawn> {
    method new (line 244) | pub fn new() -> Self {
    method build_scoped (line 322) | pub fn build_scoped<W, F, R>(self, wrapper: W, with_pool: F) -> Result...
  type Configuration (line 207) | pub struct Configuration {
    method new (line 669) | pub fn new() -> Configuration {
    method build (line 676) | pub fn build(self) -> Result<ThreadPool, Box<dyn Error + 'static>> {
    method thread_name (line 681) | pub fn thread_name<F>(mut self, closure: F) -> Self
    method num_threads (line 690) | pub fn num_threads(mut self, num_threads: usize) -> Configuration {
    method panic_handler (line 696) | pub fn panic_handler<H>(mut self, panic_handler: H) -> Configuration
    method stack_size (line 705) | pub fn stack_size(mut self, stack_size: usize) -> Self {
    method breadth_first (line 711) | pub fn breadth_first(mut self) -> Self {
    method start_handler (line 717) | pub fn start_handler<H>(mut self, start_handler: H) -> Configuration
    method exit_handler (line 726) | pub fn exit_handler<H>(mut self, exit_handler: H) -> Configuration
    method into_builder (line 735) | fn into_builder(self) -> ThreadPoolBuilder {
    method fmt (line 833) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type PanicHandler (line 213) | type PanicHandler = dyn Fn(Box<dyn Any + Send>) + Send + Sync;
  type StartHandler (line 218) | type StartHandler = dyn Fn(usize) + Send + Sync;
  type ExitHandler (line 223) | type ExitHandler = dyn Fn(usize) + Send + Sync;
  method default (line 227) | fn default() -> Self {
  function build (line 256) | pub fn build(self) -> Result<ThreadPool, ThreadPoolBuildError> {
  function build_global (line 277) | pub fn build_global(self) -> Result<(), ThreadPoolBuildError> {
  function spawn_handler (line 433) | pub fn spawn_handler<F>(self, spawn: F) -> ThreadPoolBuilder<CustomSpawn...
  function get_spawn_handler (line 452) | fn get_spawn_handler(&mut self) -> &mut S {
  function get_num_threads (line 458) | fn get_num_threads(&self) -> usize {
  function get_thread_name (line 489) | fn get_thread_name(&mut self, index: usize) -> Option<String> {
  function thread_name (line 496) | pub fn thread_name<F>(mut self, closure: F) -> Self
  function num_threads (line 529) | pub fn num_threads(mut self, num_threads: usize) -> Self {
  function use_current_thread (line 547) | pub fn use_current_thread(mut self) -> Self {
  function take_panic_handler (line 553) | fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {
  function panic_handler (line 571) | pub fn panic_handler<H>(mut self, panic_handler: H) -> Self
  function get_stack_size (line 580) | fn get_stack_size(&self) -> Option<usize> {
  function stack_size (line 585) | pub fn stack_size(mut self, stack_size: usize) -> Self {
  function breadth_first (line 618) | pub fn breadth_first(mut self) -> Self {
  function get_breadth_first (line 623) | fn get_breadth_first(&self) -> bool {
  function take_start_handler (line 628) | fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {
  function start_handler (line 638) | pub fn start_handler<H>(mut self, start_handler: H) -> Self
  function take_exit_handler (line 647) | fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {
  function exit_handler (line 657) | pub fn exit_handler<H>(mut self, exit_handler: H) -> Self
  constant GLOBAL_POOL_ALREADY_INITIALIZED (line 750) | const GLOBAL_POOL_ALREADY_INITIALIZED: &str =
  constant CURRENT_THREAD_ALREADY_IN_POOL (line 753) | const CURRENT_THREAD_ALREADY_IN_POOL: &str =
  method description (line 758) | fn description(&self) -> &str {
  method source (line 766) | fn source(&self) -> Option<&(dyn Error + 'static)> {
  function initialize (line 787) | pub fn initialize(config: Configuration) -> Result<(), Box<dyn Error>> {
  function fmt (line 792) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type FnContext (line 840) | pub struct FnContext {
    method new (line 849) | fn new(migrated: bool) -> Self {
    method migrated (line 861) | pub fn migrated(&self) -> bool {

FILE: rayon-core/src/private.rs
  type PrivateMarker (line 9) | pub struct PrivateMarker;

FILE: rayon-core/src/registry.rs
  type ThreadBuilder (line 22) | pub struct ThreadBuilder {
    method index (line 33) | pub fn index(&self) -> usize {
    method name (line 38) | pub fn name(&self) -> Option<&str> {
    method stack_size (line 43) | pub fn stack_size(&self) -> Option<usize> {
    method run (line 49) | pub fn run(self) {
    method fmt (line 55) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type ThreadSpawn (line 69) | pub trait ThreadSpawn {
    method spawn (line 74) | fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()>;
    method spawn (line 87) | fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {
    method spawn (line 123) | fn spawn(&mut self, thread: ThreadBuilder) -> io::Result<()> {
  type DefaultSpawn (line 82) | pub struct DefaultSpawn;
  type CustomSpawn (line 105) | pub struct CustomSpawn<F>(F);
  function new (line 111) | pub(super) fn new(spawn: F) -> Self {
  type Registry (line 128) | pub(super) struct Registry {
    method new (line 239) | pub(super) fn new<S>(
    method current (line 324) | pub(super) fn current() -> Arc<Registry> {
    method current_num_threads (line 339) | pub(super) fn current_num_threads() -> usize {
    method current_thread (line 351) | pub(super) fn current_thread(&self) -> Option<&WorkerThread> {
    method id (line 363) | pub(super) fn id(&self) -> RegistryId {
    method num_threads (line 371) | pub(super) fn num_threads(&self) -> usize {
    method catch_unwind (line 375) | pub(super) fn catch_unwind(&self, f: impl FnOnce()) {
    method wait_until_primed (line 390) | pub(super) fn wait_until_primed(&self) {
    method wait_until_stopped (line 399) | pub(super) fn wait_until_stopped(&self) {
    method inject_or_push (line 414) | pub(super) fn inject_or_push(&self, job_ref: JobRef) {
    method inject (line 428) | pub(super) fn inject(&self, injected_job: JobRef) {
    method has_injected_job (line 446) | fn has_injected_job(&self) -> bool {
    method pop_injected_job (line 450) | fn pop_injected_job(&self) -> Option<JobRef> {
    method inject_broadcast (line 465) | pub(super) fn inject_broadcast(&self, injected_jobs: impl ExactSizeIte...
    method in_worker (line 496) | pub(super) fn in_worker<OP, R>(&self, op: OP) -> R
    method in_worker_cold (line 517) | unsafe fn in_worker_cold<OP, R>(&self, op: OP) -> R
    method in_worker_cross (line 543) | unsafe fn in_worker_cross<OP, R>(&self, current_thread: &WorkerThread,...
    method increment_terminate_count (line 585) | pub(super) fn increment_terminate_count(&self) {
    method terminate (line 594) | pub(super) fn terminate(&self) {
    method notify_worker_latch_is_set (line 603) | pub(super) fn notify_worker_latch_is_set(&self, target_worker_index: u...
  function global_registry (line 162) | pub(super) fn global_registry() -> &'static Arc<Registry> {
  function init_global_registry (line 176) | pub(super) fn init_global_registry<S>(
  function set_global_registry (line 187) | fn set_global_registry<F>(registry: F) -> Result<&'static Arc<Registry>,...
  function default_global_registry (line 209) | fn default_global_registry() -> Result<Arc<Registry>, ThreadPoolBuildErr...
  type Terminator (line 230) | struct Terminator<'a>(&'a Arc<Registry>);
  method drop (line 233) | fn drop(&mut self) {
  type RegistryId (line 609) | pub(super) struct RegistryId {
  type ThreadInfo (line 613) | struct ThreadInfo {
    method new (line 634) | fn new(stealer: Stealer<JobRef>) -> ThreadInfo {
  type WorkerThread (line 647) | pub(super) struct WorkerThread {
    method from (line 675) | fn from(thread: ThreadBuilder) -> Self {
    method current (line 702) | pub(super) fn current() -> *const WorkerThread {
    method set_current (line 708) | unsafe fn set_current(thread: *const WorkerThread) {
    method registry (line 717) | pub(super) fn registry(&self) -> &Arc<Registry> {
    method index (line 723) | pub(super) fn index(&self) -> usize {
    method push (line 728) | pub(super) unsafe fn push(&self, job: JobRef) {
    method push_fifo (line 735) | pub(super) unsafe fn push_fifo(&self, job: JobRef) {
    method local_deque_is_empty (line 740) | pub(super) fn local_deque_is_empty(&self) -> bool {
    method take_local_job (line 749) | pub(super) fn take_local_job(&self) -> Option<JobRef> {
    method has_injected_job (line 765) | fn has_injected_job(&self) -> bool {
    method wait_until (line 772) | pub(super) unsafe fn wait_until<L: AsCoreLatch + ?Sized>(&self, latch:...
    method wait_until_cold (line 780) | unsafe fn wait_until_cold(&self, latch: &CoreLatch) {
    method wait_until_out_of_work (line 819) | unsafe fn wait_until_out_of_work(&self) {
    method find_work (line 833) | fn find_work(&self) -> Option<JobRef> {
    method yield_now (line 844) | pub(super) fn yield_now(&self) -> Yield {
    method yield_local (line 854) | pub(super) fn yield_local(&self) -> Yield {
    method execute (line 865) | pub(super) unsafe fn execute(&self, job: JobRef) {
    method steal (line 873) | fn steal(&self) -> Option<JobRef> {
  method drop (line 688) | fn drop(&mut self) {
  function main_loop (line 910) | unsafe fn main_loop(thread: ThreadBuilder) {
  function in_worker (line 946) | pub(super) fn in_worker<OP, R>(op: OP) -> R
  type XorShift64Star (line 968) | struct XorShift64Star {
    method new (line 973) | fn new() -> Self {
    method next (line 988) | fn next(&self) -> u64 {
    method next_usize (line 999) | fn next_usize(&self, n: usize) -> usize {

FILE: rayon-core/src/scope/mod.rs
  type Scope (line 24) | pub struct Scope<'scope> {
  type ScopeFifo (line 31) | pub struct ScopeFifo<'scope> {
  type ScopeBase (line 36) | struct ScopeBase<'scope> {
  function scope (line 277) | pub fn scope<'scope, OP, R>(op: OP) -> R
  function scope_fifo (line 366) | pub fn scope_fifo<'scope, OP, R>(op: OP) -> R
  function in_place_scope (line 398) | pub fn in_place_scope<'scope, OP, R>(op: OP) -> R
  function do_in_place_scope (line 405) | pub(crate) fn do_in_place_scope<'scope, OP, R>(registry: Option<&Arc<Reg...
  function get_in_place_thread_registry (line 414) | fn get_in_place_thread_registry(
  function in_place_scope_fifo (line 449) | pub fn in_place_scope_fifo<'scope, OP, R>(op: OP) -> R
  function do_in_place_scope_fifo (line 456) | pub(crate) fn do_in_place_scope_fifo<'scope, OP, R>(registry: Option<&Ar...
  function new (line 466) | fn new(owner: Option<&WorkerThread>, registry: Option<&Arc<Registry>>) -...
  function spawn (line 523) | pub fn spawn<BODY>(&self, body: BODY)
  function spawn_broadcast (line 545) | pub fn spawn_broadcast<BODY>(&self, body: BODY)
  function new (line 562) | fn new(owner: Option<&WorkerThread>, registry: Option<&Arc<Registry>>) -...
  function spawn_fifo (line 582) | pub fn spawn_fifo<BODY>(&self, body: BODY)
  function spawn_broadcast (line 610) | pub fn spawn_broadcast<BODY>(&self, body: BODY)
  function new (line 628) | fn new(owner: Option<&WorkerThread>, registry: Option<&Arc<Registry>>) -...
  function heap_job_ref (line 642) | fn heap_job_ref<FUNC>(&self, job: Box<HeapJob<FUNC>>) -> JobRef
  function inject_broadcast (line 652) | fn inject_broadcast<FUNC>(&self, job: Arc<ArcJob<FUNC>>)
  function complete (line 667) | fn complete<FUNC, R>(&self, owner: Option<&WorkerThread>, func: FUNC) -> R
  function execute_job (line 679) | unsafe fn execute_job<FUNC>(this: *const Self, func: FUNC)
  function execute_job_closure (line 689) | unsafe fn execute_job_closure<FUNC, R>(this: *const Self, func: FUNC) ->...
  function job_panicked (line 704) | fn job_panicked(&self, err: Box<dyn Any + Send + 'static>) {
  function maybe_propagate_panic (line 723) | fn maybe_propagate_panic(&self) {
  function fmt (line 736) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
  function fmt (line 746) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
  type ScopePtr (line 760) | struct ScopePtr<T>(*const T);
  function as_ref (line 770) | unsafe fn as_ref(&self) -> &T {

FILE: rayon-core/src/scope/test.rs
  function scope_empty (line 12) | fn scope_empty() {
  function scope_result (line 17) | fn scope_result() {
  function scope_two (line 23) | fn scope_two() {
  function scope_divide_and_conquer (line 39) | fn scope_divide_and_conquer() {
  function divide_and_conquer (line 51) | fn divide_and_conquer<'scope>(scope: &Scope<'scope>, counter: &'scope At...
  function divide_and_conquer_seq (line 61) | fn divide_and_conquer_seq(counter: &AtomicUsize, size: usize) {
  type Tree (line 71) | struct Tree<T: Send> {
  function iter (line 77) | fn iter(&self) -> vec::IntoIter<&T> {
  function update (line 84) | fn update<OP>(&mut self, op: OP)
  function update_in_scope (line 92) | fn update_in_scope<'scope, OP>(&'scope mut self, op: &'scope OP, scope: ...
  function random_tree (line 110) | fn random_tree(depth: usize) -> Tree<u32> {
  function random_tree1 (line 118) | fn random_tree1(depth: usize, rng: &mut XorShiftRng) -> Tree<u32> {
  function update_tree (line 134) | fn update_tree() {
  function linear_stack_growth (line 151) | fn linear_stack_growth() {
  function the_final_countdown (line 171) | fn the_final_countdown<'scope>(
  function panic_propagate_scope (line 192) | fn panic_propagate_scope() {
  function panic_propagate_spawn (line 198) | fn panic_propagate_spawn() {
  function panic_propagate_nested_spawn (line 204) | fn panic_propagate_nested_spawn() {
  function panic_propagate_nested_scope_spawn (line 210) | fn panic_propagate_nested_scope_spawn() {
  function panic_propagate_still_execute_1 (line 216) | fn panic_propagate_still_execute_1() {
  function panic_propagate_still_execute_2 (line 232) | fn panic_propagate_still_execute_2() {
  function panic_propagate_still_execute_3 (line 248) | fn panic_propagate_still_execute_3() {
  function panic_propagate_still_execute_4 (line 264) | fn panic_propagate_still_execute_4() {
  function lifo_order (line 303) | fn lifo_order() {
  function fifo_order (line 312) | fn fifo_order() {
  function nested_lifo_order (line 347) | fn nested_lifo_order() {
  function nested_fifo_order (line 356) | fn nested_fifo_order() {
  function nested_lifo_fifo_order (line 365) | fn nested_lifo_fifo_order() {
  function nested_fifo_lifo_order (line 377) | fn nested_fifo_lifo_order() {
  function mixed_lifo_order (line 420) | fn mixed_lifo_order() {
  function mixed_fifo_order (line 430) | fn mixed_fifo_order() {
  function mixed_lifo_fifo_order (line 438) | fn mixed_lifo_fifo_order() {
  function mixed_fifo_lifo_order (line 448) | fn mixed_fifo_lifo_order() {
  function static_scope (line 455) | fn static_scope() {
  function static_scope_fifo (line 477) | fn static_scope_fifo() {
  function mixed_lifetime_scope (line 499) | fn mixed_lifetime_scope() {
  function mixed_lifetime_scope_fifo (line 517) | fn mixed_lifetime_scope_fifo() {
  function scope_spawn_broadcast (line 535) | fn scope_spawn_broadcast() {
  function scope_fifo_spawn_broadcast (line 547) | fn scope_fifo_spawn_broadcast() {
  function scope_spawn_broadcast_nested (line 559) | fn scope_spawn_broadcast_nested() {
  function scope_spawn_broadcast_barrier (line 574) | fn scope_spawn_broadcast_barrier() {
  function scope_spawn_broadcast_panic_one (line 587) | fn scope_spawn_broadcast_panic_one() {
  function scope_spawn_broadcast_panic_many (line 606) | fn scope_spawn_broadcast_panic_many() {

FILE: rayon-core/src/sleep/counters.rs
  type AtomicCounters (line 3) | pub(super) struct AtomicCounters {
    method new (line 91) | pub(super) fn new() -> AtomicCounters {
    method load (line 101) | pub(super) fn load(&self, ordering: Ordering) -> Counters {
    method try_exchange (line 106) | fn try_exchange(&self, old_value: Counters, new_value: Counters, order...
    method add_inactive_thread (line 120) | pub(super) fn add_inactive_thread(&self) {
    method increment_jobs_event_counter_if (line 128) | pub(super) fn increment_jobs_event_counter_if(
    method sub_inactive_thread (line 151) | pub(super) fn sub_inactive_thread(&self) -> usize {
    method sub_sleeping_thread (line 176) | pub(super) fn sub_sleeping_thread(&self) {
    method try_add_sleeping_thread (line 192) | pub(super) fn try_add_sleeping_thread(&self, old_value: Counters) -> b...
  type Counters (line 19) | pub(super) struct Counters {
    method new (line 221) | fn new(word: usize) -> Counters {
    method increment_jobs_counter (line 226) | fn increment_jobs_counter(self) -> Counters {
    method jobs_counter (line 235) | pub(super) fn jobs_counter(self) -> JobsEventCounter {
    method inactive_threads (line 242) | pub(super) fn inactive_threads(self) -> usize {
    method awake_but_idle_threads (line 247) | pub(super) fn awake_but_idle_threads(self) -> usize {
    method sleeping_threads (line 258) | pub(super) fn sleeping_threads(self) -> usize {
    method fmt (line 264) | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type JobsEventCounter (line 27) | pub(super) struct JobsEventCounter(usize);
    constant DUMMY (line 30) | pub(super) const DUMMY: JobsEventCounter = JobsEventCounter(usize::MAX);
    method as_usize (line 33) | pub(super) fn as_usize(self) -> usize {
    method is_sleepy (line 42) | pub(super) fn is_sleepy(self) -> bool {
    method is_active (line 50) | pub(super) fn is_active(self) -> bool {
  constant THREADS_BITS (line 57) | const THREADS_BITS: usize = 16;
  constant THREADS_BITS (line 60) | const THREADS_BITS: usize = 8;
  constant SLEEPING_SHIFT (line 65) | const SLEEPING_SHIFT: usize = 0 * THREADS_BITS;
  constant INACTIVE_SHIFT (line 70) | const INACTIVE_SHIFT: usize = 1 * THREADS_BITS;
  constant JEC_SHIFT (line 74) | const JEC_SHIFT: usize = 2 * THREADS_BITS;
  constant THREADS_MAX (line 77) | pub(crate) const THREADS_MAX: usize = (1 << THREADS_BITS) - 1;
  constant ONE_SLEEPING (line 80) | const ONE_SLEEPING: usize = 1;
  constant ONE_INACTIVE (line 84) | const ONE_INACTIVE: usize = 1 << INACTIVE_SHIFT;
  constant ONE_JEC (line 87) | const ONE_JEC: usize = 1 << JEC_SHIFT;
  function select_thread (line 210) | fn select_thread(word: usize, shift: usize) -> usize {
  function select_jec (line 215) | fn select_jec(word: usize) -> usize {

FILE: rayon-core/src/sleep/mod.rs
  type Sleep (line 21) | pub(super) struct Sleep {
    method new (line 60) | pub(super) fn new(n_threads: usize) -> Sleep {
    method start_looking (line 69) | pub(super) fn start_looking(&self, worker_index: usize) -> IdleState {
    method work_found (line 80) | pub(super) fn work_found(&self) {
    method no_work_found (line 88) | pub(super) fn no_work_found(
    method announce_sleepy (line 111) | fn announce_sleepy(&self) -> JobsEventCounter {
    method sleep (line 118) | fn sleep(
    method notify_worker_latch_is_set (line 200) | pub(super) fn notify_worker_latch_is_set(&self, target_worker_index: u...
    method new_injected_jobs (line 214) | pub(super) fn new_injected_jobs(&self, num_jobs: u32, queue_was_empty:...
    method new_internal_jobs (line 236) | pub(super) fn new_internal_jobs(&self, num_jobs: u32, queue_was_empty:...
    method new_jobs (line 242) | fn new_jobs(&self, num_jobs: u32, queue_was_empty: bool) {
    method wake_any_threads (line 275) | fn wake_any_threads(&self, mut num_to_wake: u32) {
    method wake_specific_thread (line 288) | fn wake_specific_thread(&self, index: usize) -> bool {
  type IdleState (line 34) | pub(super) struct IdleState {
    method wake_fully (line 315) | fn wake_fully(&mut self) {
    method wake_partly (line 320) | fn wake_partly(&mut self) {
  type WorkerSleepState (line 48) | struct WorkerSleepState {
  constant ROUNDS_UNTIL_SLEEPY (line 56) | const ROUNDS_UNTIL_SLEEPY: u32 = 32;
  constant ROUNDS_UNTIL_SLEEPING (line 57) | const ROUNDS_UNTIL_SLEEPING: u32 = ROUNDS_UNTIL_SLEEPY + 1;

FILE: rayon-core/src/spawn/mod.rs
  function spawn (line 58) | pub fn spawn<F>(func: F)
  function spawn_in (line 69) | pub(super) unsafe fn spawn_in<F>(func: F, registry: &Arc<Registry>)
  function spawn_job (line 84) | unsafe fn spawn_job<F>(func: F, registry: &Arc<Registry>) -> JobRef
  function spawn_fifo (line 130) | pub fn spawn_fifo<F>(func: F)
  function spawn_fifo_in (line 141) | pub(super) unsafe fn spawn_fifo_in<F>(func: F, registry: &Arc<Registry>)

FILE: rayon-core/src/spawn/test.rs
  function spawn_then_join_in_worker (line 11) | fn spawn_then_join_in_worker() {
  function spawn_then_join_outside_worker (line 21) | fn spawn_then_join_outside_worker() {
  function panic_fwd (line 29) | fn panic_fwd() {
  function termination_while_things_are_executing (line 61) | fn termination_while_things_are_executing() {
  function custom_panic_handler_and_spawn (line 88) | fn custom_panic_handler_and_spawn() {
  function custom_panic_handler_and_nested_spawn (line 116) | fn custom_panic_handler_and_nested_spawn() {
  function lifo_order (line 175) | fn lifo_order() {
  function fifo_order (line 184) | fn fifo_order() {
  function lifo_fifo_order (line 193) | fn lifo_fifo_order() {
  function fifo_lifo_order (line 205) | fn fifo_lifo_order() {
  function mixed_lifo_fifo_order (line 243) | fn mixed_lifo_fifo_order() {
  function mixed_fifo_lifo_order (line 251) | fn mixed_fifo_lifo_order() {

FILE: rayon-core/src/test.rs
  function worker_thread_index (line 9) | fn worker_thread_index() {
  function start_callback_called (line 19) | fn start_callback_called() {
  function exit_callback_called (line 46) | fn exit_callback_called() {
  function handler_panics_handled_correctly (line 76) | fn handler_panics_handled_correctly() {
  function check_config_build (line 127) | fn check_config_build() {
  function _send_sync (line 133) | fn _send_sync<T: Send + Sync>() {}
  function check_error_send_sync (line 136) | fn check_error_send_sync() {
  function configuration (line 143) | fn configuration() {
  function default_pool (line 164) | fn default_pool() {
  function cleared_current_thread (line 173) | fn cleared_current_thread() -> Result<(), ThreadPoolBuildError> {

FILE: rayon-core/src/thread_pool/mod.rs
  type ThreadPool (line 46) | pub struct ThreadPool {
    method new (line 54) | pub fn new(configuration: crate::Configuration) -> Result<ThreadPool, ...
    method build (line 58) | pub(super) fn build<S>(
    method install (line 137) | pub fn install<OP, R>(&self, op: OP) -> R
    method broadcast (line 187) | pub fn broadcast<OP, R>(&self, op: OP) -> Vec<R>
    method current_num_threads (line 207) | pub fn current_num_threads(&self) -> usize {
    method current_thread_index (line 232) | pub fn current_thread_index(&self) -> Option<usize> {
    method current_thread_has_pending_tasks (line 259) | pub fn current_thread_has_pending_tasks(&self) -> Option<bool> {
    method join (line 267) | pub fn join<A, B, RA, RB>(&self, oper_a: A, oper_b: B) -> (RA, RB)
    method scope (line 283) | pub fn scope<'scope, OP, R>(&self, op: OP) -> R
    method scope_fifo (line 298) | pub fn scope_fifo<'scope, OP, R>(&self, op: OP) -> R
    method in_place_scope (line 311) | pub fn in_place_scope<'scope, OP, R>(&self, op: OP) -> R
    method in_place_scope_fifo (line 323) | pub fn in_place_scope_fifo<'scope, OP, R>(&self, op: OP) -> R
    method spawn (line 338) | pub fn spawn<OP>(&self, op: OP)
    method spawn_fifo (line 354) | pub fn spawn_fifo<OP>(&self, op: OP)
    method spawn_broadcast (line 366) | pub fn spawn_broadcast<OP>(&self, op: OP)
    method yield_now (line 381) | pub fn yield_now(&self) -> Option<Yield> {
    method yield_local (line 393) | pub fn yield_local(&self) -> Option<Yield> {
    method fmt (line 406) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
  method drop (line 400) | fn drop(&mut self) {
  function current_thread_index (line 438) | pub fn current_thread_index() -> Option<usize> {
  function current_thread_has_pending_tasks (line 452) | pub fn current_thread_has_pending_tasks() -> Option<bool> {
  function yield_now (line 471) | pub fn yield_now() -> Option<Yield> {
  function yield_local (line 488) | pub fn yield_local() -> Option<Yield> {
  type Yield (line 497) | pub enum Yield {

FILE: rayon-core/src/thread_pool/test.rs
  function panic_propagate (line 11) | fn panic_propagate() {
  function workers_stop (line 20) | fn workers_stop() {
  function join_a_lot (line 40) | fn join_a_lot(n: usize) {
  function sleeper_stop (line 48) | fn sleeper_stop() {
  function count_handler (line 68) | fn count_handler() -> (Arc<AtomicUsize>, impl Fn(usize)) {
  function wait_for_counter (line 76) | fn wait_for_counter(mut counter: Arc<AtomicUsize>) -> usize {
  function failed_thread_stack (line 95) | fn failed_thread_stack() {
  function panic_thread_name (line 122) | fn panic_thread_name() {
  function self_install (line 147) | fn self_install() {
  function mutual_install (line 156) | fn mutual_install() {
  function mutual_install_sleepy (line 176) | fn mutual_install_sleepy() {
  function check_thread_pool_new (line 205) | fn check_thread_pool_new() {
  function scope_lifo_order (line 231) | fn scope_lifo_order() {
  function scope_fifo_order (line 239) | fn scope_fifo_order() {
  function spawn_lifo_order (line 264) | fn spawn_lifo_order() {
  function spawn_fifo_order (line 272) | fn spawn_fifo_order() {
  function nested_scopes (line 280) | fn nested_scopes() {
  function nested_fifo_scopes (line 317) | fn nested_fifo_scopes() {
  function in_place_scope_no_deadlock (line 354) | fn in_place_scope_no_deadlock() {
  function in_place_scope_fifo_no_deadlock (line 370) | fn in_place_scope_fifo_no_deadlock() {
  function yield_now_to_spawn (line 385) | fn yield_now_to_spawn() {
  function yield_local_to_spawn (line 403) | fn yield_local_to_spawn() {

FILE: rayon-core/src/unwind.rs
  function halt_unwinding (line 13) | pub(super) fn halt_unwinding<F, R>(func: F) -> thread::Result<R>
  function resume_unwinding (line 20) | pub(super) fn resume_unwinding(payload: Box<dyn Any + Send>) -> ! {
  type AbortIfPanic (line 24) | pub(super) struct AbortIfPanic;
  method drop (line 27) | fn drop(&mut self) {

FILE: rayon-core/tests/double_init_fail.rs
  function double_init_fail (line 6) | fn double_init_fail() {

FILE: rayon-core/tests/init_zero_threads.rs
  function init_zero_threads (line 5) | fn init_zero_threads() {

FILE: rayon-core/tests/scope_join.rs
  function pseudo_join (line 2) | fn pseudo_join<F, G>(f: F, g: G)
  function quick_sort (line 13) | fn quick_sort<T: PartialOrd + Send>(v: &mut [T]) {
  function partition (line 23) | fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
  function is_sorted (line 36) | fn is_sorted<T: Send + Ord>(v: &[T]) -> bool {
  function scope_join (line 41) | fn scope_join() {

FILE: rayon-core/tests/scoped_threadpool.rs
  type Local (line 5) | struct Local(i32);
  function missing_scoped_tls (line 11) | fn missing_scoped_tls() {
  function spawn_scoped_tls_threadpool (line 26) | fn spawn_scoped_tls_threadpool() {
  function build_scoped_tls_threadpool (line 69) | fn build_scoped_tls_threadpool() {

FILE: rayon-core/tests/simple_panic.rs
  function simple_panic (line 5) | fn simple_panic() {

FILE: rayon-core/tests/stack_overflow_crash.rs
  function force_stack_overflow (line 9) | fn force_stack_overflow(depth: u32) {
  function disable_core (line 18) | fn disable_core() {
  function overflow_code (line 31) | fn overflow_code() -> Option<i32> {
  function overflow_code (line 36) | fn overflow_code() -> Option<i32> {
  function stack_overflow_crash (line 44) | fn stack_overflow_crash() {
  function run_ignored (line 64) | fn run_ignored(test: &str) -> ExitStatus {
  function run_with_small_stack (line 77) | fn run_with_small_stack() {
  function run_with_large_stack (line 83) | fn run_with_large_stack() {
  function run_with_stack (line 87) | fn run_with_stack(stack_size_in_mb: usize) {

FILE: rayon-core/tests/use_current_thread.rs
  function use_current_thread_basic (line 7) | fn use_current_thread_basic() {

FILE: rayon-demo/examples/cpu_monitor.rs
  constant USAGE (line 5) | const USAGE: &str = "
  type Args (line 26) | pub struct Args {
  function main (line 31) | fn main() {
  function wait_for_user (line 48) | fn wait_for_user() {
  function task (line 53) | fn task(args: &Args) {
  function tasks_ended (line 67) | fn tasks_ended(args: &Args) {
  function task_stall_root (line 72) | fn task_stall_root(args: &Args) {
  function task_stall_scope (line 76) | fn task_stall_scope(args: &Args) {

FILE: rayon-demo/src/cpu_time/mod.rs
  function get_cpu_time (line 14) | pub fn get_cpu_time() -> Option<u64> {
  function get_cpu_duration (line 18) | pub fn get_cpu_duration(start: Option<u64>, stop: Option<u64>) -> Option...
  type CpuMeasure (line 23) | pub struct CpuMeasure {
  function measure_cpu (line 31) | pub fn measure_cpu(op: impl FnOnce()) -> CpuMeasure {
  function print_time (line 47) | pub fn print_time(m: CpuMeasure) {

FILE: rayon-demo/src/cpu_time/unix.rs
  function get_cpu_time (line 4) | pub fn get_cpu_time() -> Option<u64> {

FILE: rayon-demo/src/cpu_time/win.rs
  function get_cpu_time (line 4) | pub fn get_cpu_time() -> Option<u64> {

FILE: rayon-demo/src/factorial/mod.rs
  constant N (line 7) | const N: u32 = 9999;
  function factorial (line 10) | fn factorial(n: u32) -> BigUint {
  function factorial_iterator (line 16) | fn factorial_iterator(b: &mut test::Bencher) {
  function factorial_par_iter (line 23) | fn factorial_par_iter(b: &mut test::Bencher) {
  function factorial_fold_with (line 38) | fn factorial_fold_with(b: &mut test::Bencher) {
  function factorial_fold_chunks_with (line 54) | fn factorial_fold_chunks_with(b: &mut test::Bencher) {
  function factorial_recursion (line 69) | fn factorial_recursion(b: &mut test::Bencher) {
  function factorial_join (line 84) | fn factorial_join(b: &mut test::Bencher) {

FILE: rayon-demo/src/fibonacci/mod.rs
  constant N (line 16) | const N: u32 = 32;
  constant FN (line 17) | const FN: u32 = 2_178_309;
  function fib_iterative (line 19) | fn fib_iterative(n: u32) -> u32 {
  function fib_recursive (line 30) | fn fib_recursive(n: u32) -> u32 {
  function fibonacci_recursive (line 40) | fn fibonacci_recursive(b: &mut test::Bencher) {
  function fibonacci_join_1_2 (line 47) | fn fibonacci_join_1_2(b: &mut test::Bencher) {
  function fibonacci_join_2_1 (line 63) | fn fibonacci_join_2_1(b: &mut test::Bencher) {
  function fibonacci_split_recursive (line 78) | fn fibonacci_split_recursive(b: &mut test::Bencher) {
  function fibonacci_split_iterative (line 98) | fn fibonacci_split_iterative(b: &mut test::Bencher) {
  function fibonacci_iterative (line 119) | fn fibonacci_iterative(b: &mut test::Bencher) {

FILE: rayon-demo/src/join_microbench.rs
  function increment_all (line 7) | fn increment_all(b: &mut Bencher) {
  function increment_all_min (line 15) | fn increment_all_min(b: &mut Bencher) {
  function increment_all_serialized (line 26) | fn increment_all_serialized(b: &mut Bencher) {
  function increment_all_max (line 37) | fn increment_all_max(b: &mut Bencher) {
  function increment_all_atomized (line 48) | fn increment_all_atomized(b: &mut Bencher) {
  function join_recursively (line 59) | fn join_recursively(b: &mut Bencher) {

FILE: rayon-demo/src/life/bench.rs
  function generations (line 4) | fn generations(b: &mut ::test::Bencher) {
  function par_iter_generations (line 9) | fn par_iter_generations(b: &mut ::test::Bencher) {
  function par_bridge_generations (line 14) | fn par_bridge_generations(b: &mut ::test::Bencher) {

FILE: rayon-demo/src/life/mod.rs
  constant USAGE (line 1) | const USAGE: &str = "
  type Args (line 33) | pub struct Args {
  type Board (line 43) | pub struct Board {
    method new (line 52) | pub fn new(rows: usize, cols: usize) -> Board {
    method new_with_custom_rules (line 59) | fn new_with_custom_rules(
    method len (line 76) | fn len(&self) -> usize {
    method next_board (line 80) | fn next_board(&self, new_board: Vec<bool>) -> Board {
    method random (line 92) | pub fn random(&self) -> Board {
    method next_generation (line 101) | pub fn next_generation(&self) -> Board {
    method parallel_next_generation (line 109) | pub fn parallel_next_generation(&self) -> Board {
    method par_bridge_next_generation (line 118) | pub fn par_bridge_next_generation(&self) -> Board {
    method cell_live (line 127) | fn cell_live(&self, x: usize, y: usize) -> bool {
    method living_neighbors (line 131) | fn living_neighbors(&self, x: usize, y: usize) -> usize {
    method successor_cell (line 147) | fn successor_cell(&self, cell: usize) -> bool {
    method successor (line 151) | fn successor(&self, x: usize, y: usize) -> bool {
  function test_life (line 162) | fn test_life() {
  function generations (line 174) | fn generations(board: Board, gens: usize) {
  function parallel_generations (line 181) | fn parallel_generations(board: Board, gens: usize) {
  function par_bridge_generations (line 188) | fn par_bridge_generations(board: Board, gens: usize) {
  function delay (line 195) | fn delay(last_start: Instant, min_interval: Duration) -> Instant {
  function generations_limited (line 206) | fn generations_limited(board: Board, gens: usize, min_interval: Duration) {
  function parallel_generations_limited (line 215) | fn parallel_generations_limited(board: Board, gens: usize, min_interval:...
  function par_bridge_generations_limited (line 224) | fn par_bridge_generations_limited(board: Board, gens: usize, min_interva...
  function measure (line 233) | fn measure(f: fn(Board, usize) -> (), args: &Args) -> Duration {
  type CpuResult (line 243) | struct CpuResult {
  function measure_cpu (line 248) | fn measure_cpu(f: fn(Board, usize, Duration) -> (), args: &Args) -> CpuR...
  function main (line 264) | pub fn main(args: &[String]) {

FILE: rayon-demo/src/main.rs
  constant USAGE (line 42) | const USAGE: &str = "
  function usage (line 68) | fn usage() -> ! {
  function main (line 73) | fn main() {
  function seeded_rng (line 94) | fn seeded_rng() -> rand_xorshift::XorShiftRng {

FILE: rayon-demo/src/map_collect.rs
  function collect (line 11) | pub fn collect<K, V, PI>(pi: PI) -> HashMap<K, V>
  function mutex (line 21) | pub fn mutex<K, V, PI>(pi: PI) -> HashMap<K, V>
  function mutex_vec (line 36) | pub fn mutex_vec<K, V, PI>(pi: PI) -> HashMap<K, V>
  function linked_list_collect (line 55) | pub fn linked_list_collect<K, V, PI>(pi: PI) -> HashMap<K, V>
  function linked_list_collect_vec (line 66) | pub fn linked_list_collect_vec<K, V, PI>(pi: PI) -> HashMap<K, V>
  function linked_list_collect_vec_sized (line 85) | pub fn linked_list_collect_vec_sized<K, V, PI>(pi: PI) -> HashMap<K, V>
  function linked_list_map_reduce_vec_sized (line 107) | pub fn linked_list_map_reduce_vec_sized<K, V, PI>(pi: PI) -> HashMap<K, V>
  function vec_vec_sized (line 137) | pub fn vec_vec_sized<K, V, PI>(pi: PI) -> HashMap<K, V>
  function fold (line 163) | pub fn fold<K, V, PI>(pi: PI) -> HashMap<K, V>
  function fold_vec (line 185) | pub fn fold_vec<K, V, PI>(pi: PI) -> HashMap<K, V>
  constant N (line 294) | const N: u32 = 256 * 1024;
  function generate (line 296) | fn generate() -> impl ParallelIterator<Item = (u32, u32)> {
  function check (line 300) | fn check(hm: &HashMap<u32, u32>) {
  constant N (line 317) | const N: u32 = 256 * 1024;
  function generate (line 319) | fn generate() -> impl ParallelIterator<Item = (u32, u32)> {
  function check (line 323) | fn check(hm: &HashMap<u32, u32>) {

FILE: rayon-demo/src/matmul/bench.rs
  constant ROW_SIZE (line 1) | const ROW_SIZE: usize = 256;
  function bench_matmul_strassen (line 4) | fn bench_matmul_strassen(b: &mut test::Bencher) {

FILE: rayon-demo/src/matmul/mod.rs
  constant USAGE (line 1) | const USAGE: &str = "
  type Args (line 14) | pub struct Args {
  function seq_matmul (line 27) | pub fn seq_matmul(a: &[f32], b: &[f32], dest: &mut [f32]) {
  type SplayedBitsCounter (line 49) | struct SplayedBitsCounter {
    method new (line 55) | fn new(max: usize) -> Self {
  type Item (line 61) | type Item = usize;
  method next (line 63) | fn next(&mut self) -> Option<usize> {
  function test_splayed_counter (line 79) | fn test_splayed_counter() {
  function seq_matmulz (line 90) | pub fn seq_matmulz(a: &[f32], b: &[f32], dest: &mut [f32]) {
  constant MULT_CHUNK (line 120) | const MULT_CHUNK: usize = 1 * 1024;
  constant LINEAR_CHUNK (line 121) | const LINEAR_CHUNK: usize = 64 * 1024;
  function quarter_chunks (line 123) | fn quarter_chunks(v: &[f32]) -> (&[f32], &[f32], &[f32], &[f32]) {
  function quarter_chunks_mut (line 132) | fn quarter_chunks_mut(v: &mut [f32]) -> (&mut [f32], &mut [f32], &mut [f...
  function join4 (line 141) | fn join4<F1, F2, F3, F4, R1, R2, R3, R4>(f1: F1, f2: F2, f3: F3, f4: F4)...
  function join8 (line 157) | fn join8<F1, F2, F3, F4, F5, F6, F7, F8, R1, R2, R3, R4, R5, R6, R7, R8>(
  function matmulz (line 193) | pub fn matmulz(a: &[f32], b: &[f32], dest: &mut [f32]) {
  function matmul_strassen (line 224) | pub fn matmul_strassen(a: &[f32], b: &[f32], dest: &mut [f32]) {
  function raw_buffer (line 256) | fn raw_buffer(n: usize) -> Vec<f32> {
  function strassen_add2_mul (line 261) | fn strassen_add2_mul(a1: &[f32], a2: &[f32], b1: &[f32], b2: &[f32]) -> ...
  function strassen_sub_add_mul (line 268) | fn strassen_sub_add_mul(a1: &[f32], a2: &[f32], b1: &[f32], b2: &[f32]) ...
  function strassen_add_mul (line 275) | fn strassen_add_mul(a1: &[f32], a2: &[f32], b: &[f32]) -> Vec<f32> {
  function strassen_sub_mul (line 282) | fn strassen_sub_mul(b1: &[f32], b2: &[f32], a: &[f32]) -> Vec<f32> {
  function strassen_sum_sub (line 289) | fn strassen_sum_sub(a: &[f32], b: &[f32], c: &[f32], s: &[f32], dest: &m...
  function strassen_sum (line 296) | fn strassen_sum(a: &[f32], b: &[f32], dest: &mut [f32]) {
  function rtmp_sum (line 301) | fn rtmp_sum(a: &[f32], b: &[f32]) -> Vec<f32> {
  function rtmp_sub (line 308) | fn rtmp_sub(a: &[f32], b: &[f32]) -> Vec<f32> {
  function rmatsum (line 316) | fn rmatsum(src: &[f32], dest: &mut [f32]) {
  function rmatsub (line 322) | fn rmatsub(src: &[f32], dest: &mut [f32]) {
  function rcopy (line 328) | fn rcopy(src: &[f32], dest: &mut [f32]) {
  function test_matmul (line 341) | fn test_matmul() {
  function timed_matmul (line 375) | fn timed_matmul<F: FnOnce(&[f32], &[f32], &mut [f32])>(size: usize, f: F...
  function main (line 400) | pub fn main(args: &[String]) {

FILE: rayon-demo/src/mergesort/bench.rs
  constant BENCH_SIZE (line 3) | const BENCH_SIZE: usize = 250_000_000 / 512;
  function bench_harness (line 5) | fn bench_harness<F: FnMut(&mut [u32])>(mut f: F, b: &mut test::Bencher) {
  function merge_sort_par_bench (line 16) | fn merge_sort_par_bench(b: &mut test::Bencher) {
  function merge_sort_seq_bench (line 21) | fn merge_sort_seq_bench(b: &mut test::Bencher) {

FILE: rayon-demo/src/mergesort/mod.rs
  constant USAGE (line 4) | const USAGE: &str = "
  type Args (line 22) | pub struct Args {
  function merge_sort (line 33) | pub fn merge_sort<T: Ord + Send + Copy>(v: &mut [T]) {
  constant SORT_CHUNK (line 44) | const SORT_CHUNK: usize = 32 * 1024;
  constant MERGE_CHUNK (line 45) | const MERGE_CHUNK: usize = 64 * 1024;
  function as_uninit_slice (line 47) | fn as_uninit_slice<T: Copy>(slice: &[T]) -> &[MaybeUninit<T>] {
  function as_uninit_slice_mut (line 53) | fn as_uninit_slice_mut<T: Copy>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
  function slice_assume_init_mut (line 59) | unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut...
  function rsort (line 65) | fn rsort<T: Ord + Send + Copy>(src: &mut [T], buf: &mut [MaybeUninit<T>]) {
  function rsort_into (line 82) | fn rsort_into<'dest, T: Ord + Send + Copy>(
  function rmerge (line 105) | fn rmerge<T: Ord + Send + Copy>(a: &mut [T], b: &mut [T], dest: &mut [Ma...
  function seq_merge (line 129) | fn seq_merge<T: Ord + Copy>(a: &[T], b: &[T], dest: &mut [MaybeUninit<T>...
  function test_merge_sort (line 157) | fn test_merge_sort() {
  function seq_merge_sort (line 171) | pub fn seq_merge_sort<T: Ord + Copy>(v: &mut [T]) {
  function seq_sort (line 182) | fn seq_sort<T: Ord + Copy>(src: &mut [T], buf: &mut [MaybeUninit<T>]) {
  function seq_sort_into (line 199) | fn seq_sort_into<'dest, T: Ord + Copy>(
  function is_sorted (line 217) | pub fn is_sorted<T: Send + Ord>(v: &mut [T]) -> bool {
  function default_vec (line 237) | fn default_vec(n: usize) -> Vec<u32> {
  function timed_sort (line 242) | fn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {
  function main (line 257) | pub fn main(args: &[String]) {

FILE: rayon-demo/src/nbody/bench.rs
  constant BENCH_BODIES (line 4) | const BENCH_BODIES: usize = 1000;
  constant BENCH_TICKS (line 6) | const BENCH_TICKS: usize = 10;
  function nbody_bench (line 8) | fn nbody_bench<TICK>(b: &mut test::Bencher, mut tick: TICK)
  function nbody_seq (line 22) | fn nbody_seq(b: &mut ::test::Bencher) {
  function nbody_par_iter (line 29) | fn nbody_par_iter(b: &mut ::test::Bencher) {
  function nbody_par_bridge (line 36) | fn nbody_par_bridge(b: &mut ::test::Bencher) {
  function nbody_parreduce (line 43) | fn nbody_parreduce(b: &mut ::test::Bencher) {

FILE: rayon-demo/src/nbody/mod.rs
  constant USAGE (line 12) | const USAGE: &str = "
  type ExecutionMode (line 47) | pub enum ExecutionMode {
  type Args (line 54) | pub struct Args {
  function main (line 62) | pub fn main(args: &[String]) {
  function run_benchmarks (line 79) | fn run_benchmarks(mode: Option<ExecutionMode>, bodies: usize, ticks: usi...

FILE: rayon-demo/src/nbody/nbody.rs
  constant INITIAL_VELOCITY (line 37) | const INITIAL_VELOCITY: f64 = 8.0;
  type NBodyBenchmark (line 39) | pub struct NBodyBenchmark {
    method new (line 52) | pub fn new<R: Rng>(num_bodies: usize, rng: &mut R) -> NBodyBenchmark {
    method tick_par (line 92) | pub fn tick_par(&mut self) -> &[Body] {
    method tick_par_bridge (line 118) | pub fn tick_par_bridge(&mut self) -> &[Body] {
    method tick_par_reduce (line 144) | pub fn tick_par_reduce(&mut self) -> &[Body] {
    method tick_seq (line 169) | pub fn tick_seq(&mut self) -> &[Body] {
  type Body (line 45) | pub struct Body {
  function next_velocity (line 193) | fn next_velocity(time: usize, prev: &Body, bodies: &[Body]) -> (Vector3<...
  function next_velocity_par (line 332) | fn next_velocity_par(time: usize, prev: &Body, bodies: &[Body]) -> (Vect...

FILE: rayon-demo/src/nbody/visualize.rs
  type Vertex (line 19) | struct Vertex {
  function icosahedron (line 25) | fn icosahedron() -> ([Vertex; 12], Vec<u8>) {
  type Instance (line 77) | struct Instance {
  type State (line 84) | struct State {
  method resumed (line 96) | fn resumed(&mut self, _event_loop: &ActiveEventLoop) {}
  method window_event (line 98) | fn window_event(
  method about_to_wait (line 166) | fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
  function visualize_benchmarks (line 187) | pub fn visualize_benchmarks(num_bodies: usize, mode: ExecutionMode) {

FILE: rayon-demo/src/noop/mod.rs
  constant USAGE (line 1) | const USAGE: &str = "
  type Args (line 15) | pub struct Args {
  function main (line 20) | pub fn main(args: &[String]) {

FILE: rayon-demo/src/pythagoras/mod.rs
  function par_euclid (line 17) | fn par_euclid<FM, M, FN, N>(map_m: FM, map_n: FN) -> u32
  function par_euclid_weightless (line 35) | fn par_euclid_weightless() -> u32 {
  function euclid (line 49) | fn euclid() -> u32 {
  function euclid_serial (line 62) | fn euclid_serial(b: &mut test::Bencher) {
  function euclid_faux_serial (line 69) | fn euclid_faux_serial(b: &mut test::Bencher) {
  function euclid_parallel_weightless (line 77) | fn euclid_parallel_weightless(b: &mut test::Bencher) {
  function euclid_parallel_one (line 84) | fn euclid_parallel_one(b: &mut test::Bencher) {
  function euclid_parallel_outer (line 91) | fn euclid_parallel_outer(b: &mut test::Bencher) {
  function euclid_parallel_full (line 99) | fn euclid_parallel_full(b: &mut test::Bencher) {

FILE: rayon-demo/src/quicksort/bench.rs
  constant BENCH_SIZE (line 5) | const BENCH_SIZE: usize = 250_000_000 / 512;
  function bench_harness (line 7) | fn bench_harness<F: FnMut(&mut [u32])>(mut f: F, b: &mut test::Bencher) {
  function quick_sort_par_bench (line 18) | fn quick_sort_par_bench(b: &mut test::Bencher) {
  function quick_sort_seq_bench (line 23) | fn quick_sort_seq_bench(b: &mut test::Bencher) {
  function quick_sort_splitter (line 28) | fn quick_sort_splitter(b: &mut test::Bencher) {

FILE: rayon-demo/src/quicksort/mod.rs
  constant USAGE (line 3) | const USAGE: &str = "
  type Args (line 19) | pub struct Args {
  type Joiner (line 30) | pub trait Joiner {
    method is_parallel (line 31) | fn is_parallel() -> bool;
    method join (line 32) | fn join<A, R_A, B, R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
    method is_parallel (line 43) | fn is_parallel() -> bool {
    method join (line 47) | fn join<A, R_A, B, R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
    method is_parallel (line 61) | fn is_parallel() -> bool {
    method join (line 65) | fn join<A, R_A, B, R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
  type Parallel (line 40) | pub struct Parallel;
  type Sequential (line 58) | struct Sequential;
  function quick_sort (line 78) | pub fn quick_sort<J: Joiner, T: PartialOrd + Send>(v: &mut [T]) {
  function partition (line 92) | fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
  function is_sorted (line 105) | pub fn is_sorted<T: Send + Ord>(v: &[T]) -> bool {
  function default_vec (line 109) | fn default_vec(n: usize) -> Vec<u32> {
  function timed_sort (line 114) | fn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {
  function main (line 129) | pub fn main(args: &[String]) {

FILE: rayon-demo/src/sieve/bench.rs
  constant MAGNITUDE (line 3) | const MAGNITUDE: usize = 7;
  function sieve_bench (line 5) | fn sieve_bench<TICK>(b: &mut test::Bencher, mut tick: TICK)
  function sieve_serial (line 16) | fn sieve_serial(b: &mut ::test::Bencher) {
  function sieve_chunks (line 21) | fn sieve_chunks(b: &mut ::test::Bencher) {
  function sieve_parallel (line 26) | fn sieve_parallel(b: &mut ::test::Bencher) {

FILE: rayon-demo/src/sieve/mod.rs
  constant USAGE (line 1) | const USAGE: &str = "
  type Args (line 35) | pub struct Args {
  constant CHUNK_SIZE (line 46) | const CHUNK_SIZE: usize = 100_000;
  constant NUM_PRIMES (line 50) | const NUM_PRIMES: &[usize] = &[
  function max (line 76) | fn max(magnitude: usize) -> usize {
  function sieve_serial (line 81) | fn sieve_serial(max: usize) -> Vec<bool> {
  function sieve_chunks (line 98) | fn sieve_chunks(max: usize) -> Vec<bool> {
  function sieve_parallel (line 117) | fn sieve_parallel(max: usize) -> Vec<bool> {
  function update_chunk (line 139) | fn update_chunk(low: &[bool], chunk: &mut [bool], base: usize) {
  function clear_stride (line 163) | fn clear_stride(slice: &mut [bool], from: usize, stride: usize) {
  function measure (line 170) | fn measure(f: fn(usize) -> Vec<bool>) -> Duration {
  function main (line 184) | pub fn main(args: &[String]) {

FILE: rayon-demo/src/sort.rs
  function gen_ascending (line 8) | fn gen_ascending(len: usize) -> Vec<u64> {
  function gen_descending (line 12) | fn gen_descending(len: usize) -> Vec<u64> {
  function gen_random (line 16) | fn gen_random(len: usize) -> Vec<u64> {
  function gen_mostly_ascending (line 21) | fn gen_mostly_ascending(len: usize) -> Vec<u64> {
  function gen_mostly_descending (line 33) | fn gen_mostly_descending(len: usize) -> Vec<u64> {
  function gen_strings (line 45) | fn gen_strings(len: usize) -> Vec<String> {
  function gen_big_random (line 62) | fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
  type MergeSort (line 212) | trait MergeSort {
    method demo_merge_sort (line 213) | fn demo_merge_sort(&mut self);
    method demo_merge_sort (line 217) | fn demo_merge_sort(&mut self) {
  type QuickSort (line 256) | trait QuickSort {
    method demo_quick_sort (line 257) | fn demo_quick_sort(&mut self);
    method demo_quick_sort (line 261) | fn demo_quick_sort(&mut self) {

FILE: rayon-demo/src/str_split.rs
  constant WHITESPACE (line 18) | const WHITESPACE: &[char] = &['\r', '\n', ' ', '\t'];
  function get_string_count (line 20) | fn get_string_count() -> (&'static str, usize) {
  function parallel_space_char (line 25) | fn parallel_space_char(b: &mut Bencher) {
  function parallel_space_chars (line 31) | fn parallel_space_chars(b: &mut Bencher) {
  function parallel_space_fn (line 37) | fn parallel_space_fn(b: &mut Bencher) {
  function serial_space_char (line 43) | fn serial_space_char(b: &mut Bencher) {
  function serial_space_chars (line 49) | fn serial_space_chars(b: &mut Bencher) {
  function serial_space_fn (line 56) | fn serial_space_fn(b: &mut Bencher) {
  function serial_space_str (line 62) | fn serial_space_str(b: &mut Bencher) {

FILE: rayon-demo/src/tree.rs
  constant SIZE (line 4) | const SIZE: u64 = 100_000;
  constant VAL (line 5) | const VAL: u64 = SIZE * (SIZE - 1) / 2;
  function tree_prefix_collect (line 8) | fn tree_prefix_collect(b: &mut ::test::Bencher) {
  function tree_postfix_collect (line 28) | fn tree_postfix_collect(b: &mut ::test::Bencher) {
  function tree_prefix_sum (line 48) | fn tree_prefix_sum(b: &mut ::test::Bencher) {
  function tree_postfix_sum (line 65) | fn tree_postfix_sum(b: &mut ::test::Bencher) {

FILE: rayon-demo/src/tsp/bench.rs
  function run_dir (line 7) | fn run_dir(
  function dj10 (line 40) | fn dj10(b: &mut test::Bencher) {

FILE: rayon-demo/src/tsp/graph.rs
  type Graph (line 6) | pub struct Graph {
    method new (line 16) | pub fn new(num_nodes: usize) -> Graph {
    method num_nodes (line 25) | pub fn num_nodes(&self) -> usize {
    method all_nodes (line 29) | pub fn all_nodes(&self) -> impl Iterator<Item = Node> {
    method node_set (line 33) | pub fn node_set(&self) -> NodeSet {
    method edge_index (line 39) | fn edge_index(&self, source: Node, target: Node) -> usize {
    method set_weight (line 43) | pub fn set_weight(&mut self, source: Node, target: Node, w: Weight) {
    method edge_weight (line 49) | pub fn edge_weight(&self, source: Node, target: Node) -> Option<Weight> {
    method edges (line 58) | pub fn edges(&self, source: Node) -> impl Iterator<Item = Edge> + '_ {
  type Node (line 70) | pub struct Node {
    method new (line 75) | pub fn new(index: usize) -> Node {
    method index (line 79) | pub fn index(self) -> usize {
  type Edge (line 85) | pub struct Edge {
  type NodeSet (line 92) | pub struct NodeSet {
    method contains (line 97) | pub fn contains(&self, node: Node) -> bool {
    method with (line 101) | pub fn with(&self, node: Node) -> NodeSet {
    method insert (line 107) | pub fn insert(&mut self, node: Node) {
    method remove (line 111) | pub fn remove(&mut self, node: Node) {

FILE: rayon-demo/src/tsp/mod.rs
  constant USAGE (line 26) | const USAGE: &str = "
  type Args (line 47) | pub struct Args {
  function main (line 54) | pub fn main(args: &[String]) {
  function run_solver (line 68) | fn run_solver(datafile: &Path, seq_threshold: usize, from: usize) -> Res...
  function parse_solver (line 107) | fn parse_solver(datafile: &Path) -> Result<Graph, Box<dyn Error>> {

FILE: rayon-demo/src/tsp/parser.rs
  function parse_tsp_data (line 32) | pub fn parse_tsp_data(text: &str) -> Result<Graph, String> {
  type Data (line 141) | pub struct Data<'text> {
  function new (line 148) | pub fn new(data: &'text str) -> Data<'text> {
  function advance (line 158) | pub fn advance(&mut self) {
  type Header (line 164) | pub struct Header<'text> {
  function parse_tsp_header (line 170) | pub fn parse_tsp_header<'text>(data: &mut Data<'text>) -> Option<Header<...
  function parse_coord_header (line 183) | pub fn parse_coord_header(data: &mut Data<'_>) -> Option<()> {
  function parse_coord (line 194) | pub fn parse_coord(data: &mut Data<'_>) -> Option<(Node, f64, f64)> {
  function parse_blank (line 220) | pub fn parse_blank(data: &mut Data<'_>) -> Option<()> {

FILE: rayon-demo/src/tsp/solver.rs
  type SolverCx (line 11) | pub struct SolverCx<'s> {
  type TourId (line 23) | pub struct TourId {
  function new (line 28) | pub fn new(graph: &'s Graph, seq_threshold: usize) -> Self {
  function search_from (line 39) | pub fn search_from(&mut self, node: Node) {
  function seq_threshold (line 61) | pub fn seq_threshold(&self) -> usize {
  function tour_id (line 65) | pub fn tour_id(&self) -> TourId {
  function graph (line 70) | pub fn graph(&self) -> &'s Graph {
  function enqueue (line 74) | pub fn enqueue(&self, tour_element: Arc<TourPrefix>) {
  function dequeue (line 79) | pub fn dequeue(&self) -> Option<Arc<TourPrefix>> {
  function min_tour_weight (line 84) | pub fn min_tour_weight(&self) -> Weight {
  function add_complete_tour (line 91) | pub fn add_complete_tour(&self, tour: &[Node], weight: Weight) {
  function into_result (line 103) | pub fn into_result(self) -> (Option<Vec<Node>>, Weight) {

FILE: rayon-demo/src/tsp/step.rs
  function step (line 9) | pub fn step<'s>(scope: &Scope<'s>, solver: &'s SolverCx<'s>) {
  function split_tour (line 20) | fn split_tour<'s>(scope: &Scope<'s>, solver: &'s SolverCx<'s>, element: ...
  function compute_lower_bound (line 60) | fn compute_lower_bound(
  function solve_tour_seq (line 100) | fn solve_tour_seq(solver: &SolverCx<'_>, element: Arc<TourPrefix>) {
  function enumerate_sequentially (line 129) | fn enumerate_sequentially(
  function complete_tour (line 175) | fn complete_tour(solver: &SolverCx<'_>, path: &mut Vec<Node>, weight: We...

FILE: rayon-demo/src/tsp/tour.rs
  type TourPrefix (line 9) | pub struct TourPrefix {
    method to_cmp_elements (line 35) | fn to_cmp_elements(&self) -> (Priority, TourId) {
    method visited (line 39) | pub fn visited(&self, node: Node) -> bool {
  method eq (line 45) | fn eq(&self, other: &Self) -> bool {
  method partial_cmp (line 53) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  method cmp (line 59) | fn cmp(&self, other: &Self) -> Ordering {

FILE: rayon-demo/src/tsp/weight.rs
  type Weight (line 4) | pub struct Weight {
    method new (line 14) | pub fn new(w: usize) -> Weight {
    method zero (line 18) | pub fn zero() -> Weight {
    method max (line 22) | pub fn max() -> Weight {
    method to_usize (line 26) | pub fn to_usize(self) -> usize {
    method is_max (line 30) | pub fn is_max(self) -> bool {
    method to_priority (line 36) | pub fn to_priority(self) -> Priority {
  type Priority (line 9) | pub struct Priority {
  type Output (line 44) | type Output = Weight;
  method add (line 46) | fn add(self, rhs: Weight) -> Weight {
  method add_assign (line 52) | fn add_assign(&mut self, rhs: Weight) {
  type Output (line 58) | type Output = Weight;
  method sub (line 60) | fn sub(self, rhs: Weight) -> Weight {
  method sub_assign (line 66) | fn sub_assign(&mut self, rhs: Weight) {

FILE: rayon-demo/src/vec_collect.rs
  function collect (line 8) | pub fn collect<T, PI>(pi: PI) -> Vec<T>
  function linked_list_collect_vec (line 17) | pub fn linked_list_collect_vec<T, PI>(pi: PI) -> Vec<T>
  function linked_list_collect_vec_sized (line 35) | pub fn linked_list_collect_vec_sized<T, PI>(pi: PI) -> Vec<T>
  function linked_list_map_reduce_vec_sized (line 56) | pub fn linked_list_map_reduce_vec_sized<T, PI>(pi: PI) -> Vec<T>
  function vec_vec_sized (line 85) | pub fn vec_vec_sized<T, PI>(pi: PI) -> Vec<T>
  function fold (line 110) | pub fn fold<T, PI>(pi: PI) -> Vec<T>
  constant N (line 182) | const N: u32 = 4 * 1024 * 1024;
  function generate (line 184) | fn generate() -> impl IndexedParallelIterator<Item = u32> {
  function check (line 188) | fn check(v: &[u32]) {
  function with_collect_into_vec (line 193) | fn with_collect_into_vec(b: &mut ::test::Bencher) {
  function with_collect_into_vec_reused (line 204) | fn with_collect_into_vec_reused(b: &mut ::test::Bencher) {
  constant N (line 218) | const N: u32 = 4 * 1024 * 1024;
  function generate (line 220) | fn generate() -> impl ParallelIterator<Item = u32> {
  function check (line 224) | fn check(v: &[u32]) {

FILE: src/array.rs
  type Item (line 15) | type Item = &'data T;
  type Iter (line 16) | type Iter = Iter<'data, T>;
  method into_par_iter (line 18) | fn into_par_iter(self) -> Self::Iter {
  type Item (line 24) | type Item = &'data mut T;
  type Iter (line 25) | type Iter = IterMut<'data, T>;
  method into_par_iter (line 27) | fn into_par_iter(self) -> Self::Iter {
  type Item (line 33) | type Item = T;
  type Iter (line 34) | type Iter = IntoIter<T, N>;
  method into_par_iter (line 36) | fn into_par_iter(self) -> Self::Iter {
  type IntoIter (line 43) | pub struct IntoIter<T, const N: usize> {
  type Item (line 48) | type Item = T;
  method drive_unindexed (line 50) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 57) | fn opt_len(&self) -> Option<usize> {
  method drive (line 63) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 70) | fn len(&self) -> usize {
  method with_producer (line 74) | fn with_producer<CB>(self, callback: CB) -> CB::Output

FILE: src/collections/binary_heap.rs
  type IntoIter (line 15) | pub struct IntoIter<T> {
  type Item (line 20) | type Item = T;
  type Iter (line 21) | type Iter = IntoIter<T>;
  method into_par_iter (line 23) | fn into_par_iter(self) -> Self::Iter {
  type Iter (line 37) | pub struct Iter<'a, T> {
  method clone (line 42) | fn clone(&self) -> Self {
  type Item (line 50) | type Item = &'a T;
  type Iter (line 51) | type Iter = Iter<'a, T>;
  method into_par_iter (line 53) | fn into_par_iter(self) -> Self::Iter {
  type Drain (line 70) | pub struct Drain<'a, T> {
  type Iter (line 77) | type Iter = Drain<'a, T>;
  type Item (line 78) | type Item = T;
  method par_drain (line 80) | fn par_drain(self) -> Self::Iter {
  type Item (line 86) | type Item = T;
  method drive_unindexed (line 88) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 95) | fn opt_len(&self) -> Option<usize> {
  method drive (line 101) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 108) | fn len(&self) -> usize {
  method with_producer (line 112) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  method drop (line 123) | fn drop(&mut self) {

FILE: src/collections/btree_map.rs
  type IntoIter (line 14) | pub struct IntoIter<K, V> {
  type Iter (line 30) | pub struct Iter<'a, K, V> {
  method clone (line 35) | fn clone(&self) -> Self {
  type IterMut (line 54) | pub struct IterMut<'a, K, V> {

FILE: src/collections/btree_set.rs
  type IntoIter (line 14) | pub struct IntoIter<T> {
  type Iter (line 30) | pub struct Iter<'a, T> {
  method clone (line 35) | fn clone(&self) -> Self {

FILE: src/collections/hash_map.rs
  type IntoIter (line 15) | pub struct IntoIter<K, V> {
  type Iter (line 31) | pub struct Iter<'a, K, V> {
  method clone (line 36) | fn clone(&self) -> Self {
  type IterMut (line 55) | pub struct IterMut<'a, K, V> {
  type Drain (line 72) | pub struct Drain<'a, K, V> {
  type Iter (line 78) | type Iter = Drain<'a, K, V>;
  type Item (line 79) | type Item = (K, V);
  method par_drain (line 81) | fn par_drain(self) -> Self::Iter {

FILE: src/collections/hash_set.rs
  type IntoIter (line 15) | pub struct IntoIter<T> {
  type Iter (line 31) | pub struct Iter<'a, T> {
  method clone (line 36) | fn clone(&self) -> Self {
  type Drain (line 58) | pub struct Drain<'a, T> {
  type Iter (line 64) | type Iter = Drain<'a, T>;
  type Item (line 65) | type Item = T;
  method par_drain (line 67) | fn par_drain(self) -> Self::Iter {

FILE: src/collections/linked_list.rs
  type IntoIter (line 14) | pub struct IntoIter<T> {
  type Iter (line 30) | pub struct Iter<'a, T> {
  method clone (line 35) | fn clone(&self) -> Self {
  type IterMut (line 54) | pub struct IterMut<'a, T> {

FILE: src/collections/mod.rs
  type DrainGuard (line 46) | pub(super) struct DrainGuard<'a, T, C: From<Vec<T>>> {
  function new (line 56) | pub(super) fn new(collection: &'a mut C) -> Self {
  method drop (line 66) | fn drop(&mut self) {
  type Iter (line 77) | type Iter = crate::vec::Drain<'a, T>;
  type Item (line 78) | type Item = T;
  function par_drain (line 80) | fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter {

FILE: src/collections/vec_deque.rs
  type IntoIter (line 17) | pub struct IntoIter<T: Send> {
  type Item (line 22) | type Item = T;
  type Iter (line 23) | type Iter = IntoIter<T>;
  method into_par_iter (line 25) | fn into_par_iter(self) -> Self::Iter {
  type Iter (line 39) | pub struct Iter<'a, T> {
  method clone (line 44) | fn clone(&self) -> Self {
  type Item (line 52) | type Item = &'a T;
  type Iter (line 53) | type Iter = Iter<'a, T>;
  method into_par_iter (line 55) | fn into_par_iter(self) -> Self::Iter {
  type IterMut (line 70) | pub struct IterMut<'a, T> {
  type Item (line 75) | type Item = &'a mut T;
  type Iter (line 76) | type Iter = IterMut<'a, T>;
  method into_par_iter (line 78) | fn into_par_iter(self) -> Self::Iter {
  type Drain (line 94) | pub struct Drain<'a, T> {
  type Iter (line 101) | type Iter = Drain<'a, T>;
  type Item (line 102) | type Item = T;
  function par_drain (line 104) | fn par_drain<R: RangeBounds<usize>>(self, range: R) -> Self::Iter {
  type Item (line 114) | type Item = T;
  method drive_unindexed (line 116) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 123) | fn opt_len(&self) -> Option<usize> {
  method drive (line 129) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 136) | fn len(&self) -> usize {
  method with_producer (line 140) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  method drop (line 152) | fn drop(&mut self) {

FILE: src/delegate.rs
  function unindexed_example (line 64) | fn unindexed_example() {
  function indexed_example (line 89) | fn indexed_example() {

FILE: src/iter/blocks.rs
  type BlocksCallback (line 4) | struct BlocksCallback<S, C> {
  type Output (line 15) | type Output = C::Result;
  function callback (line 17) | fn callback<P: Producer<Item = T>>(mut self, mut producer: P) -> Self::O...
  type ExponentialBlocks (line 59) | pub struct ExponentialBlocks<I> {
  function new (line 64) | pub(super) fn new(base: I) -> Self {
  type Item (line 73) | type Item = I::Item;
  method drive_unindexed (line 75) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  function exponential_size (line 89) | fn exponential_size(size: &usize) -> Option<usize> {
  type UniformBlocks (line 101) | pub struct UniformBlocks<I> {
  function new (line 107) | pub(super) fn new(base: I, block_size: usize) -> Self {
  type Item (line 116) | type Item = I::Item;
  method drive_unindexed (line 118) | fn drive_unindexed<C>(self, consumer: C) -> C::Result

FILE: src/iter/chain.rs
  type Chain (line 12) | pub struct Chain<A, B> {
  function new (line 19) | pub(super) fn new(a: A, b: B) -> Self {
  type Item (line 29) | type Item = A::Item;
  method drive_unindexed (line 31) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 52) | fn opt_len(&self) -> Option<usize> {
  method drive (line 62) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 72) | fn len(&self) -> usize {
  method with_producer (line 76) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type ChainProducer (line 138) | struct ChainProducer<A, B>
  function new (line 153) | fn new(a_len: usize, a: A, b: B) -> Self {
  type Item (line 163) | type Item = A::Item;
  type IntoIter (line 164) | type IntoIter = ChainSeq<A::IntoIter, B::IntoIter>;
  method into_iter (line 166) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 170) | fn min_len(&self) -> usize {
  method max_len (line 174) | fn max_len(&self) -> usize {
  method split_at (line 178) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 197) | fn fold_with<F>(self, mut folder: F) -> F
  type ChainSeq (line 213) | struct ChainSeq<A, B> {
  function new (line 218) | fn new(a: A, b: B) -> ChainSeq<A, B>
  type Item (line 232) | type Item = A::Item;
  method next (line 234) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 238) | fn size_hint(&self) -> (usize, Option<usize>) {
  method next_back (line 255) | fn next_back(&mut self) -> Option<Self::Item> {

FILE: src/iter/chunks.rs
  type Chunks (line 11) | pub struct Chunks<I> {
  function new (line 18) | pub(super) fn new(i: I, size: usize) -> Self {
  type Item (line 27) | type Item = Vec<I::Item>;
  method drive_unindexed (line 29) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 36) | fn opt_len(&self) -> Option<usize> {
  method drive (line 45) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 52) | fn len(&self) -> usize {
  method with_producer (line 56) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type ChunkProducer (line 90) | pub(super) struct ChunkProducer<P, F> {
  function new (line 98) | pub(super) fn new(chunk_size: usize, len: usize, base: P, map: F) -> Self {
  type Item (line 113) | type Item = T;
  type IntoIter (line 114) | type IntoIter = std::iter::Map<ChunkSeq<P>, F>;
  method into_iter (line 116) | fn into_iter(self) -> Self::IntoIter {
  method split_at (line 125) | fn split_at(self, index: usize) -> (Self, Self) {
  method min_len (line 144) | fn min_len(&self) -> usize {
  method max_len (line 148) | fn max_len(&self) -> usize {
  type ChunkSeq (line 153) | pub(super) struct ChunkSeq<P> {
  type Item (line 163) | type Item = P::IntoIter;
  method next (line 165) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 179) | fn size_hint(&self) -> (usize, Option<usize>) {
  method len (line 190) | fn len(&self) -> usize {
  method next_back (line 199) | fn next_back(&mut self) -> Option<Self::Item> {

FILE: src/iter/cloned.rs
  type Cloned (line 13) | pub struct Cloned<I> {
  function new (line 19) | pub(super) fn new(base: I) -> Self {
  type Item (line 29) | type Item = T;
  method drive_unindexed (line 31) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 39) | fn opt_len(&self) -> Option<usize> {
  method drive (line 49) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 57) | fn len(&self) -> usize {
  method with_producer (line 61) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type ClonedProducer (line 91) | struct ClonedProducer<P> {
  type Item (line 100) | type Item = T;
  type IntoIter (line 101) | type IntoIter = iter::Cloned<P::IntoIter>;
  method into_iter (line 103) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 107) | fn min_len(&self) -> usize {
  method max_len (line 111) | fn max_len(&self) -> usize {
  method split_at (line 115) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 123) | fn fold_with<F>(self, folder: F) -> F
  type ClonedConsumer (line 134) | struct ClonedConsumer<C> {
  function new (line 139) | fn new(base: C) -> Self {
  type Folder (line 149) | type Folder = ClonedFolder<C::Folder>;
  type Reducer (line 150) | type Reducer = C::Reducer;
  type Result (line 151) | type Result = C::Result;
  function split_at (line 153) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 162) | fn into_folder(self) -> Self::Folder {
  function full (line 168) | fn full(&self) -> bool {
  function split_off_left (line 178) | fn split_off_left(&self) -> Self {
  function to_reducer (line 182) | fn to_reducer(&self) -> Self::Reducer {
  type ClonedFolder (line 187) | struct ClonedFolder<F> {
  type Result (line 196) | type Result = F::Result;
  function consume (line 198) | fn consume(self, item: &'a T) -> Self {
  function consume_iter (line 204) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 212) | fn complete(self) -> F::Result {
  function full (line 216) | fn full(&self) -> bool {

FILE: src/iter/collect/consumer.rs
  type CollectConsumer (line 6) | pub(super) struct CollectConsumer<'c, T: Send> {
  function appender (line 15) | pub(super) fn appender(vec: &mut Vec<T>, len: usize) -> CollectConsumer<...
  function new (line 29) | unsafe fn new(start: *mut T, len: usize) -> Self {
  type CollectResult (line 43) | pub(super) struct CollectResult<'c, T> {
  function len (line 60) | pub(super) fn len(&self) -> usize {
  function release_ownership (line 65) | pub(super) fn release_ownership(mut self) -> usize {
  method drop (line 73) | fn drop(&mut self) {
  type Folder (line 86) | type Folder = CollectResult<'c, T>;
  type Reducer (line 87) | type Reducer = CollectReducer;
  type Result (line 88) | type Result = CollectResult<'c, T>;
  function split_at (line 90) | fn split_at(self, index: usize) -> (Self, Self, CollectReducer) {
  function into_folder (line 105) | fn into_folder(self) -> Self::Folder {
  function full (line 116) | fn full(&self) -> bool {
  type Result (line 122) | type Result = Self;
  function consume (line 124) | fn consume(mut self, item: T) -> Self {
  function complete (line 141) | fn complete(self) -> Self::Result {
  function full (line 147) | fn full(&self) -> bool {
  function split_off_left (line 155) | fn split_off_left(&self) -> Self {
  function to_reducer (line 158) | fn to_reducer(&self) -> Self::Reducer {
  type CollectReducer (line 165) | pub(super) struct CollectReducer;
    method reduce (line 168) | fn reduce(

FILE: src/iter/collect/mod.rs
  function collect_into_vec (line 13) | pub(super) fn collect_into_vec<I, T>(pi: I, v: &mut Vec<T>)
  function special_extend (line 34) | pub(super) fn special_extend<I, T>(pi: I, len: usize, v: &mut Vec<T>)
  function unzip_into_vecs (line 45) | pub(super) fn unzip_into_vecs<I, A, B>(pi: I, left: &mut Vec<A>, right: ...
  function collect_with_consumer (line 75) | fn collect_with_consumer<T, F>(vec: &mut Vec<T>, len: usize, scope_fn: F)

FILE: src/iter/collect/test.rs
  function produce_too_many_items (line 21) | fn produce_too_many_items() {
  function produce_fewer_items (line 36) | fn produce_fewer_items() {
  function left_produces_items_with_no_complete (line 49) | fn left_produces_items_with_no_complete() {
  function right_produces_items_with_no_complete (line 65) | fn right_produces_items_with_no_complete() {
  function produces_items_with_no_complete (line 80) | fn produces_items_with_no_complete() {
  function left_produces_too_many_items (line 100) | fn left_produces_too_many_items() {
  function right_produces_too_many_items (line 117) | fn right_produces_too_many_items() {
  function left_produces_fewer_items (line 134) | fn left_produces_fewer_items() {
  function only_left_result (line 153) | fn only_left_result() {
  function only_right_result (line 171) | fn only_right_result() {
  function reducer_does_not_preserve_order (line 188) | fn reducer_does_not_preserve_order() {
  function right_produces_fewer_items (line 207) | fn right_produces_fewer_items() {
  function left_panics (line 226) | fn left_panics() {
  function right_panics (line 252) | fn right_panics() {
  function left_produces_fewer_items_drops (line 278) | fn left_produces_fewer_items_drops() {
  type DropCounter (line 304) | struct DropCounter {
    method created (line 312) | fn created(&self) -> usize {
    method dropped (line 316) | fn dropped(&self) -> usize {
    method element (line 320) | fn element(&self) -> Element<'_> {
    method assert_drop_count (line 325) | fn assert_drop_count(&self) {
  type Element (line 309) | struct Element<'a>(&'a AtomicUsize);
  method drop (line 337) | fn drop(&mut self) {
  function assert_is_panic_with_message (line 343) | fn assert_is_panic_with_message<T>(result: &ThreadResult<T>, expected: &...

FILE: src/iter/copied.rs
  type Copied (line 13) | pub struct Copied<I> {
  function new (line 19) | pub(super) fn new(base: I) -> Self {
  type Item (line 29) | type Item = T;
  method drive_unindexed (line 31) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 39) | fn opt_len(&self) -> Option<usize> {
  method drive (line 49) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 57) | fn len(&self) -> usize {
  method with_producer (line 61) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type CopiedProducer (line 91) | struct CopiedProducer<P> {
  type Item (line 100) | type Item = T;
  type IntoIter (line 101) | type IntoIter = iter::Copied<P::IntoIter>;
  method into_iter (line 103) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 107) | fn min_len(&self) -> usize {
  method max_len (line 111) | fn max_len(&self) -> usize {
  method split_at (line 115) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 123) | fn fold_with<F>(self, folder: F) -> F
  type CopiedConsumer (line 134) | struct CopiedConsumer<C> {
  function new (line 139) | fn new(base: C) -> Self {
  type Folder (line 149) | type Folder = CopiedFolder<C::Folder>;
  type Reducer (line 150) | type Reducer = C::Reducer;
  type Result (line 151) | type Result = C::Result;
  function split_at (line 153) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 162) | fn into_folder(self) -> Self::Folder {
  function full (line 168) | fn full(&self) -> bool {
  function split_off_left (line 178) | fn split_off_left(&self) -> Self {
  function to_reducer (line 182) | fn to_reducer(&self) -> Self::Reducer {
  type CopiedFolder (line 187) | struct CopiedFolder<F> {
  type Result (line 196) | type Result = F::Result;
  function consume (line 198) | fn consume(self, &item: &'a T) -> Self {
  function consume_iter (line 204) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 212) | fn complete(self) -> F::Result {
  function full (line 216) | fn full(&self) -> bool {

FILE: src/iter/empty.rs
  function empty (line 24) | pub fn empty<T: Send>() -> Empty<T> {
  type Empty (line 33) | pub struct Empty<T> {
  method clone (line 38) | fn clone(&self) -> Self {
  function fmt (line 46) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 52) | type Item = T;
  method drive_unindexed (line 54) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 61) | fn opt_len(&self) -> Option<usize> {
  method drive (line 67) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 74) | fn len(&self) -> usize {
  method with_producer (line 78) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type EmptyProducer (line 87) | struct EmptyProducer<T: Send>(PhantomData<T>);
  type Item (line 90) | type Item = T;
  type IntoIter (line 91) | type IntoIter = std::iter::Empty<T>;
  method into_iter (line 93) | fn into_iter(self) -> Self::IntoIter {
  method split_at (line 97) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 102) | fn fold_with<F>(self, folder: F) -> F

FILE: src/iter/enumerate.rs
  type Enumerate (line 12) | pub struct Enumerate<I> {
  function new (line 18) | pub(super) fn new(base: I) -> Self {
  type Item (line 27) | type Item = (usize, I::Item);
  method drive_unindexed (line 29) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 36) | fn opt_len(&self) -> Option<usize> {
  method drive (line 45) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
  method len (line 49) | fn len(&self) -> usize {
  method with_producer (line 53) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type EnumerateProducer (line 82) | struct EnumerateProducer<P> {
  type Item (line 91) | type Item = (usize, P::Item);
  type IntoIter (line 92) | type IntoIter = iter::Zip<Range<usize>, P::IntoIter>;
  method into_iter (line 94) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 108) | fn min_len(&self) -> usize {
  method max_len (line 111) | fn max_len(&self) -> usize {
  method split_at (line 115) | fn split_at(self, index: usize) -> (Self, Self) {

FILE: src/iter/extend.rs
  function len (line 42) | fn len<T>(vecs: &Either<Vec<T>, LinkedList<Vec<T>>>) -> usize {
  function string_len (line 50) | fn string_len<T: AsRef<str>>(vecs: &Either<Vec<T>, LinkedList<Vec<T>>>) ...
  function osstring_len (line 59) | fn osstring_len<T: AsRef<OsStr>>(vecs: &Either<Vec<T>, LinkedList<Vec<T>...
  function fast_collect (line 67) | pub(super) fn fast_collect<I, T>(pi: I) -> Either<Vec<T>, LinkedList<Vec...
  type ListVecConsumer (line 84) | struct ListVecConsumer;
    type Folder (line 91) | type Folder = ListVecFolder<T>;
    type Reducer (line 92) | type Reducer = ListReducer;
    type Result (line 93) | type Result = LinkedList<Vec<T>>;
    method split_at (line 95) | fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
    method into_folder (line 99) | fn into_folder(self) -> Self::Folder {
    method full (line 103) | fn full(&self) -> bool {
    method split_off_left (line 109) | fn split_off_left(&self) -> Self {
    method to_reducer (line 113) | fn to_reducer(&self) -> Self::Reducer {
  type ListVecFolder (line 86) | struct ListVecFolder<T> {
  type Result (line 119) | type Result = LinkedList<Vec<T>>;
  function consume (line 121) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 126) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 134) | fn complete(self) -> Self::Result {
  function full (line 142) | fn full(&self) -> bool {
  function par_extend (line 152) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 165) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 179) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 193) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 206) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 219) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 234) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 250) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 264) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 278) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 291) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 305) | fn par_extend<I>(&mut self, par_iter: I)
  type ListConsumer (line 313) | struct ListConsumer;
    type Folder (line 322) | type Folder = ListFolder<T>;
    type Reducer (line 323) | type Reducer = ListReducer;
    type Result (line 324) | type Result = LinkedList<T>;
    method split_at (line 326) | fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
    method into_folder (line 330) | fn into_folder(self) -> Self::Folder {
    method full (line 336) | fn full(&self) -> bool {
    method split_off_left (line 342) | fn split_off_left(&self) -> Self {
    method to_reducer (line 346) | fn to_reducer(&self) -> Self::Reducer {
  type ListFolder (line 315) | struct ListFolder<T> {
  type ListReducer (line 319) | struct ListReducer;
    method reduce (line 377) | fn reduce(self, mut left: LinkedList<T>, mut right: LinkedList<T>) -> ...
  type Result (line 352) | type Result = LinkedList<T>;
  function consume (line 354) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 359) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 367) | fn complete(self) -> Self::Result {
  function full (line 371) | fn full(&self) -> bool {
  method par_extend (line 385) | fn par_extend<I>(&mut self, par_iter: I)
  method par_extend (line 395) | fn par_extend<I>(&mut self, par_iter: I)
  method par_extend (line 405) | fn par_extend<I>(&mut self, par_iter: I)
  method par_extend (line 415) | fn par_extend<I>(&mut self, par_iter: I)
  method par_extend (line 429) | fn par_extend<I>(&mut self, par_iter: I)
  type ListStringConsumer (line 437) | struct ListStringConsumer;
    type Folder (line 444) | type Folder = ListStringFolder;
    type Reducer (line 445) | type Reducer = ListReducer;
    type Result (line 446) | type Result = LinkedList<String>;
    method split_at (line 448) | fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
    method into_folder (line 452) | fn into_folder(self) -> Self::Folder {
    method full (line 458) | fn full(&self) -> bool {
    method split_off_left (line 464) | fn split_off_left(&self) -> Self {
    method to_reducer (line 468) | fn to_reducer(&self) -> Self::Reducer {
  type ListStringFolder (line 439) | struct ListStringFolder {
    type Result (line 474) | type Result = LinkedList<String>;
    method consume (line 476) | fn consume(mut self, item: char) -> Self {
    method consume_iter (line 481) | fn consume_iter<I>(mut self, iter: I) -> Self
    method complete (line 489) | fn complete(self) -> Self::Result {
    method full (line 497) | fn full(&self) -> bool {
  method par_extend (line 504) | fn par_extend<I>(&mut self, par_iter: I)
  method par_extend (line 514) | fn par_extend<I>(&mut self, par_iter: I)
  method par_extend (line 524) | fn par_extend<I>(&mut self, par_iter: I)
  method par_extend (line 534) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 547) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 560) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 573) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 603) | fn par_extend<I>(&mut self, par_iter: I)
  function par_extend (line 613) | fn par_extend<I>(&mut self, par_iter: I)

FILE: src/iter/filter.rs
  type Filter (line 12) | pub struct Filter<I, P> {
  method fmt (line 18) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 25) | pub(super) fn new(base: I, filter_op: P) -> Self {
  type Item (line 35) | type Item = I::Item;
  method drive_unindexed (line 37) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FilterConsumer (line 49) | struct FilterConsumer<'p, C, P> {
  function new (line 55) | fn new(base: C, filter_op: &'p P) -> Self {
  type Folder (line 65) | type Folder = FilterFolder<'p, C::Folder, P>;
  type Reducer (line 66) | type Reducer = C::Reducer;
  type Result (line 67) | type Result = C::Result;
  function split_at (line 69) | fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
  function into_folder (line 78) | fn into_folder(self) -> Self::Folder {
  function full (line 85) | fn full(&self) -> bool {
  function split_off_left (line 95) | fn split_off_left(&self) -> Self {
  function to_reducer (line 99) | fn to_reducer(&self) -> Self::Reducer {
  type FilterFolder (line 104) | struct FilterFolder<'p, C, P> {
  type Result (line 114) | type Result = C::Result;
  function consume (line 116) | fn consume(self, item: T) -> Self {
  function complete (line 130) | fn complete(self) -> Self::Result {
  function full (line 134) | fn full(&self) -> bool {

FILE: src/iter/filter_map.rs
  type FilterMap (line 12) | pub struct FilterMap<I, P> {
  method fmt (line 18) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 27) | pub(super) fn new(base: I, filter_op: P) -> Self {
  type Item (line 38) | type Item = R;
  method drive_unindexed (line 40) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FilterMapConsumer (line 52) | struct FilterMapConsumer<'p, C, P> {
  function new (line 58) | fn new(base: C, filter_op: &'p P) -> Self {
  type Folder (line 68) | type Folder = FilterMapFolder<'p, C::Folder, P>;
  type Reducer (line 69) | type Reducer = C::Reducer;
  type Result (line 70) | type Result = C::Result;
  function split_at (line 72) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 81) | fn into_folder(self) -> Self::Folder {
  function full (line 89) | fn full(&self) -> bool {
  function split_off_left (line 99) | fn split_off_left(&self) -> Self {
  function to_reducer (line 103) | fn to_reducer(&self) -> Self::Reducer {
  type FilterMapFolder (line 108) | struct FilterMapFolder<'p, C, P> {
  type Result (line 118) | type Result = C::Result;
  function consume (line 120) | fn consume(self, item: T) -> Self {
  function complete (line 134) | fn complete(self) -> C::Result {
  function full (line 138) | fn full(&self) -> bool {

FILE: src/iter/find.rs
  function find (line 5) | pub(super) fn find<I, P>(pi: I, find_op: P) -> Option<I::Item>
  type FindConsumer (line 15) | struct FindConsumer<'p, P> {
  function new (line 21) | fn new(find_op: &'p P, found: &'p AtomicBool) -> Self {
  type Folder (line 31) | type Folder = FindFolder<'p, T, P>;
  type Reducer (line 32) | type Reducer = FindReducer;
  type Result (line 33) | type Result = Option<T>;
  function split_at (line 35) | fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 39) | fn into_folder(self) -> Self::Folder {
  function full (line 47) | fn full(&self) -> bool {
  function split_off_left (line 57) | fn split_off_left(&self) -> Self {
  function to_reducer (line 61) | fn to_reducer(&self) -> Self::Reducer {
  type FindFolder (line 66) | struct FindFolder<'p, T, P> {
  type Result (line 76) | type Result = Option<T>;
  function consume (line 78) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 86) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 105) | fn complete(self) -> Self::Result {
  function full (line 109) | fn full(&self) -> bool {
  type FindReducer (line 114) | struct FindReducer;
    method reduce (line 117) | fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {

FILE: src/iter/find_first_last/mod.rs
  type MatchPosition (line 27) | enum MatchPosition {
  function better_position (line 34) | fn better_position(pos1: usize, pos2: usize, mp: MatchPosition) -> bool {
  function find_first (line 41) | pub(super) fn find_first<I, P>(pi: I, find_op: P) -> Option<I::Item>
  function find_last (line 51) | pub(super) fn find_last<I, P>(pi: I, find_op: P) -> Option<I::Item>
  type FindConsumer (line 61) | struct FindConsumer<'p, P> {
  function new (line 70) | fn new(find_op: &'p P, match_position: MatchPosition, best_found: &'p At...
  function current_index (line 80) | fn current_index(&self) -> usize {
  type Folder (line 93) | type Folder = FindFolder<'p, T, P>;
  type Reducer (line 94) | type Reducer = FindReducer;
  type Result (line 95) | type Result = Option<T>;
  function split_at (line 97) | fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 108) | fn into_folder(self) -> Self::Folder {
  function full (line 118) | fn full(&self) -> bool {
  function split_off_left (line 134) | fn split_off_left(&self) -> Self {
  function to_reducer (line 159) | fn to_reducer(&self) -> Self::Reducer {
  type FindFolder (line 166) | struct FindFolder<'p, T, P> {
  type Result (line 175) | type Result = Option<T>;
  function consume (line 177) | fn consume(mut self, item: T) -> Self {
  function complete (line 200) | fn complete(self) -> Self::Result {
  function full (line 204) | fn full(&self) -> bool {
  type FindReducer (line 219) | struct FindReducer {
    method reduce (line 224) | fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {

FILE: src/iter/find_first_last/test.rs
  function same_range_first_consumers_return_correct_answer (line 4) | fn same_range_first_consumers_return_correct_answer() {
  function same_range_last_consumers_return_correct_answer (line 38) | fn same_range_last_consumers_return_correct_answer() {
  function find_first_folder_does_not_clobber_first_found (line 76) | fn find_first_folder_does_not_clobber_first_found() {
  function find_last_folder_yields_last_match (line 91) | fn find_last_folder_yields_last_match() {

FILE: src/iter/flat_map.rs
  type FlatMap (line 12) | pub struct FlatMap<I, F> {
  method fmt (line 18) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 25) | pub(super) fn new(base: I, map_op: F) -> Self {
  type Item (line 36) | type Item = PI::Item;
  method drive_unindexed (line 38) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FlatMapConsumer (line 50) | struct FlatMapConsumer<'f, C, F> {
  function new (line 56) | fn new(base: C, map_op: &'f F) -> Self {
  type Folder (line 67) | type Folder = FlatMapFolder<'f, C, F, C::Result>;
  type Reducer (line 68) | type Reducer = C::Reducer;
  type Result (line 69) | type Result = C::Result;
  function split_at (line 71) | fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
  function into_folder (line 80) | fn into_folder(self) -> Self::Folder {
  function full (line 88) | fn full(&self) -> bool {
  function split_off_left (line 99) | fn split_off_left(&self) -> Self {
  function to_reducer (line 103) | fn to_reducer(&self) -> Self::Reducer {
  type FlatMapFolder (line 108) | struct FlatMapFolder<'f, C, F, R> {
  type Result (line 120) | type Result = C::Result;
  function consume (line 122) | fn consume(self, item: T) -> Self {
  function complete (line 143) | fn complete(self) -> Self::Result {
  function full (line 150) | fn full(&self) -> bool {

FILE: src/iter/flat_map_iter.rs
  type FlatMapIter (line 12) | pub struct FlatMapIter<I, F> {
  method fmt (line 18) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 27) | pub(super) fn new(base: I, map_op: F) -> Self {
  type Item (line 38) | type Item = SI::Item;
  method drive_unindexed (line 40) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FlatMapIterConsumer (line 52) | struct FlatMapIterConsumer<'f, C, F> {
  function new (line 58) | fn new(base: C, map_op: &'f F) -> Self {
  type Folder (line 69) | type Folder = FlatMapIterFolder<'f, C::Folder, F>;
  type Reducer (line 70) | type Reducer = C::Reducer;
  type Result (line 71) | type Result = C::Result;
  function split_at (line 73) | fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
  function into_folder (line 82) | fn into_folder(self) -> Self::Folder {
  function full (line 89) | fn full(&self) -> bool {
  function split_off_left (line 100) | fn split_off_left(&self) -> Self {
  function to_reducer (line 104) | fn to_reducer(&self) -> Self::Reducer {
  type FlatMapIterFolder (line 109) | struct FlatMapIterFolder<'f, C, F> {
  type Result (line 120) | type Result = C::Result;
  function consume (line 122) | fn consume(self, item: T) -> Self {
  function consume_iter (line 128) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 138) | fn complete(self) -> Self::Result {
  function full (line 142) | fn full(&self) -> bool {

FILE: src/iter/flatten.rs
  type Flatten (line 10) | pub struct Flatten<I> {
  function new (line 16) | pub(super) fn new(base: I) -> Self {
  type Item (line 25) | type Item = <I::Item as IntoParallelIterator>::Item;
  method drive_unindexed (line 27) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FlattenConsumer (line 39) | struct FlattenConsumer<C> {
  function new (line 44) | fn new(base: C) -> Self {
  type Folder (line 54) | type Folder = FlattenFolder<C, C::Result>;
  type Reducer (line 55) | type Reducer = C::Reducer;
  type Result (line 56) | type Result = C::Result;
  function split_at (line 58) | fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
  function into_folder (line 67) | fn into_folder(self) -> Self::Folder {
  function full (line 74) | fn full(&self) -> bool {
  function split_off_left (line 84) | fn split_off_left(&self) -> Self {
  function to_reducer (line 88) | fn to_reducer(&self) -> Self::Reducer {
  type FlattenFolder (line 93) | struct FlattenFolder<C, R> {
  type Result (line 103) | type Result = C::Result;
  function consume (line 105) | fn consume(self, item: T) -> Self {
  function complete (line 124) | fn complete(self) -> Self::Result {
  function full (line 131) | fn full(&self) -> bool {

FILE: src/iter/flatten_iter.rs
  type FlattenIter (line 10) | pub struct FlattenIter<I> {
  function new (line 16) | pub(super) fn new(base: I) -> Self {
  type Item (line 25) | type Item = <I::Item as IntoIterator>::Item;
  method drive_unindexed (line 27) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FlattenIterConsumer (line 39) | struct FlattenIterConsumer<C> {
  function new (line 44) | fn new(base: C) -> Self {
  type Folder (line 54) | type Folder = FlattenIterFolder<C::Folder>;
  type Reducer (line 55) | type Reducer = C::Reducer;
  type Result (line 56) | type Result = C::Result;
  function split_at (line 58) | fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
  function into_folder (line 67) | fn into_folder(self) -> Self::Folder {
  function full (line 73) | fn full(&self) -> bool {
  function split_off_left (line 83) | fn split_off_left(&self) -> Self {
  function to_reducer (line 87) | fn to_reducer(&self) -> Self::Reducer {
  type FlattenIterFolder (line 92) | struct FlattenIterFolder<C> {
  type Result (line 101) | type Result = C::Result;
  function consume (line 103) | fn consume(self, item: T) -> Self {
  function consume_iter (line 108) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 117) | fn complete(self) -> Self::Result {
  function full (line 121) | fn full(&self) -> bool {

FILE: src/iter/fold.rs
  function new (line 7) | pub(super) fn new(base: I, identity: ID, fold_op: F) -> Self {
  type Fold (line 22) | pub struct Fold<I, ID, F> {
  method fmt (line 29) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 41) | type Item = U;
  method drive_unindexed (line 43) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FoldConsumer (line 56) | struct FoldConsumer<'c, C, ID, F> {
  type Folder (line 69) | type Folder = FoldFolder<'r, C::Folder, U, F>;
  type Reducer (line 70) | type Reducer = C::Reducer;
  type Result (line 71) | type Result = C::Result;
  function split_at (line 73) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 85) | fn into_folder(self) -> Self::Folder {
  function full (line 93) | fn full(&self) -> bool {
  function split_off_left (line 105) | fn split_off_left(&self) -> Self {
  function to_reducer (line 112) | fn to_reducer(&self) -> Self::Reducer {
  type FoldFolder (line 117) | struct FoldFolder<'r, C, ID, F> {
  type Result (line 128) | type Result = C::Result;
  function consume (line 130) | fn consume(self, item: T) -> Self {
  function consume_iter (line 139) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 164) | fn complete(self) -> C::Result {
  function full (line 168) | fn full(&self) -> bool {
  function new (line 176) | pub(super) fn new(base: I, item: U, fold_op: F) -> Self {
  type FoldWith (line 191) | pub struct FoldWith<I, U, F> {
  method fmt (line 198) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 212) | type Item = U;
  method drive_unindexed (line 214) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type FoldWithConsumer (line 227) | struct FoldWithConsumer<'c, C, U, F> {
  type Folder (line 239) | type Folder = FoldFolder<'r, C::Folder, U, F>;
  type Reducer (line 240) | type Reducer = C::Reducer;
  type Result (line 241) | type Result = C::Result;
  function split_at (line 243) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 259) | fn into_folder(self) -> Self::Folder {
  function full (line 267) | fn full(&self) -> bool {
  function split_off_left (line 278) | fn split_off_left(&self) -> Self {
  function to_reducer (line 286) | fn to_reducer(&self) -> Self::Reducer {

FILE: src/iter/fold_chunks.rs
  type FoldChunks (line 15) | pub struct FoldChunks<I, ID, F> {
  method fmt (line 23) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 33) | pub(super) fn new(base: I, chunk_size: usize, identity: ID, fold_op: F) ...
  type Item (line 50) | type Item = U;
  method drive_unindexed (line 52) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 59) | fn opt_len(&self) -> Option<usize> {
  method len (line 71) | fn len(&self) -> usize {
  method drive (line 75) | fn drive<C>(self, consumer: C) -> C::Result
  method with_producer (line 82) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  function check_fold_chunks (line 131) | fn check_fold_chunks() {
  function id (line 146) | fn id() -> i32 {
  function sum (line 149) | fn sum<T, U>(x: T, y: U) -> T
  function check_fold_chunks_zero_size (line 158) | fn check_fold_chunks_zero_size() {
  function check_fold_chunks_even_size (line 166) | fn check_fold_chunks_even_size() {
  function check_fold_chunks_empty (line 177) | fn check_fold_chunks_empty() {
  function check_fold_chunks_len (line 189) | fn check_fold_chunks_len() {
  function check_fold_chunks_uneven (line 198) | fn check_fold_chunks_uneven() {

FILE: src/iter/fold_chunks_with.rs
  type FoldChunksWith (line 15) | pub struct FoldChunksWith<I, U, F> {
  method fmt (line 23) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 34) | pub(super) fn new(base: I, chunk_size: usize, item: U, fold_op: F) -> Se...
  type Item (line 50) | type Item = U;
  method drive_unindexed (line 52) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 59) | fn opt_len(&self) -> Option<usize> {
  method len (line 70) | fn len(&self) -> usize {
  method drive (line 74) | fn drive<C>(self, consumer: C) -> C::Result
  method with_producer (line 81) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  function check_fold_chunks_with (line 130) | fn check_fold_chunks_with() {
  function sum (line 145) | fn sum<T, U>(x: T, y: U) -> T
  function check_fold_chunks_zero_size (line 154) | fn check_fold_chunks_zero_size() {
  function check_fold_chunks_even_size (line 162) | fn check_fold_chunks_even_size() {
  function check_fold_chunks_with_empty (line 173) | fn check_fold_chunks_with_empty() {
  function check_fold_chunks_len (line 185) | fn check_fold_chunks_len() {
  function check_fold_chunks_uneven (line 194) | fn check_fold_chunks_uneven() {

FILE: src/iter/for_each.rs
  function for_each (line 5) | pub(super) fn for_each<I, F, T>(pi: I, op: &F)
  type ForEachConsumer (line 15) | struct ForEachConsumer<'f, F> {
  type Folder (line 23) | type Folder = ForEachConsumer<'f, F>;
  type Reducer (line 24) | type Reducer = NoopReducer;
  type Result (line 25) | type Result = ();
  function split_at (line 27) | fn split_at(self, _index: usize) -> (Self, Self, NoopReducer) {
  function into_folder (line 31) | fn into_folder(self) -> Self {
  function full (line 35) | fn full(&self) -> bool {
  type Result (line 44) | type Result = ();
  function consume (line 46) | fn consume(self, item: T) -> Self {
  function consume_iter (line 51) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 59) | fn complete(self) {}
  function full (line 61) | fn full(&self) -> bool {
  function split_off_left (line 70) | fn split_off_left(&self) -> Self {
  function to_reducer (line 74) | fn to_reducer(&self) -> NoopReducer {

FILE: src/iter/from_par_iter.rs
  function collect_extended (line 14) | fn collect_extended<C, I>(par_iter: I) -> C
  function from_par_iter (line 29) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 42) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 55) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 68) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 81) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 95) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 109) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 127) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 144) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 158) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 171) | fn from_par_iter<I>(par_iter: I) -> Self
  method from_par_iter (line 212) | fn from_par_iter<I>(par_iter: I) -> Self
  method from_par_iter (line 222) | fn from_par_iter<I>(par_iter: I) -> Self
  method from_par_iter (line 232) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 250) | fn from_par_iter<I>(par_iter: I) -> Self
  function from_par_iter (line 274) | fn from_par_iter<I>(par_iter: I) -> Self

FILE: src/iter/inspect.rs
  type Inspect (line 15) | pub struct Inspect<I, F> {
  method fmt (line 21) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 28) | pub(super) fn new(base: I, inspect_op: F) -> Self {
  type Item (line 38) | type Item = I::Item;
  method drive_unindexed (line 40) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 48) | fn opt_len(&self) -> Option<usize> {
  method drive (line 58) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 66) | fn len(&self) -> usize {
  method with_producer (line 70) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type InspectProducer (line 107) | struct InspectProducer<'f, P, F> {
  type Item (line 117) | type Item = P::Item;
  type IntoIter (line 118) | type IntoIter = iter::Inspect<P::IntoIter, &'f F>;
  method into_iter (line 120) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 124) | fn min_len(&self) -> usize {
  method max_len (line 128) | fn max_len(&self) -> usize {
  method split_at (line 132) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 146) | fn fold_with<G>(self, folder: G) -> G
  type InspectConsumer (line 161) | struct InspectConsumer<'f, C, F> {
  function new (line 167) | fn new(base: C, inspect_op: &'f F) -> Self {
  type Folder (line 177) | type Folder = InspectFolder<'f, C::Folder, F>;
  type Reducer (line 178) | type Reducer = C::Reducer;
  type Result (line 179) | type Result = C::Result;
  function split_at (line 181) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 190) | fn into_folder(self) -> Self::Folder {
  function full (line 197) | fn full(&self) -> bool {
  function split_off_left (line 207) | fn split_off_left(&self) -> Self {
  function to_reducer (line 211) | fn to_reducer(&self) -> Self::Reducer {
  type InspectFolder (line 216) | struct InspectFolder<'f, C, F> {
  type Result (line 226) | type Result = C::Result;
  function consume (line 228) | fn consume(self, item: T) -> Self {
  function consume_iter (line 236) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 246) | fn complete(self) -> C::Result {
  function full (line 250) | fn full(&self) -> bool {

FILE: src/iter/interleave.rs
  type Interleave (line 12) | pub struct Interleave<I, J> {
  function new (line 19) | pub(super) fn new(i: I, j: J) -> Self {
  type Item (line 29) | type Item = I::Item;
  method drive_unindexed (line 31) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 38) | fn opt_len(&self) -> Option<usize> {
  method drive (line 48) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 55) | fn len(&self) -> usize {
  method with_producer (line 59) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type InterleaveProducer (line 133) | struct InterleaveProducer<I, J>
  function new (line 150) | fn new(i: I, j: J, i_len: usize, j_len: usize, i_next: bool) -> Interlea...
  type Item (line 166) | type Item = I::Item;
  type IntoIter (line 167) | type IntoIter = InterleaveSeq<I::IntoIter, J::IntoIter>;
  method into_iter (line 169) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 177) | fn min_len(&self) -> usize {
  method max_len (line 181) | fn max_len(&self) -> usize {
  method split_at (line 197) | fn split_at(self, index: usize) -> (Self, Self) {
  type InterleaveSeq (line 243) | struct InterleaveSeq<I, J> {
  type Item (line 262) | type Item = I::Item;
  method next (line 265) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 280) | fn size_hint(&self) -> (usize, Option<usize>) {
  method next_back (line 302) | fn next_back(&mut self) -> Option<I::Item> {
  method len (line 323) | fn len(&self) -> usize {

FILE: src/iter/interleave_shortest.rs
  type InterleaveShortest (line 14) | pub struct InterleaveShortest<I, J> {
  function new (line 24) | pub(super) fn new(i: I, j: J) -> Self {
  type Item (line 44) | type Item = I::Item;
  method drive_unindexed (line 46) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 53) | fn opt_len(&self) -> Option<usize> {
  method drive (line 63) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 70) | fn len(&self) -> usize {
  method with_producer (line 74) | fn with_producer<CB>(self, callback: CB) -> CB::Output

FILE: src/iter/intersperse.rs
  type Intersperse (line 13) | pub struct Intersperse<I>
  function new (line 26) | pub(super) fn new(base: I, item: I::Item) -> Self {
  type Item (line 35) | type Item = I::Item;
  method drive_unindexed (line 37) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 45) | fn opt_len(&self) -> Option<usize> {
  method drive (line 57) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 65) | fn len(&self) -> usize {
  method with_producer (line 74) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type IntersperseProducer (line 109) | struct IntersperseProducer<P>
  function new (line 123) | fn new(base: P, item: P::Item, len: usize) -> Self {
  type Item (line 137) | type Item = P::Item;
  type IntoIter (line 138) | type IntoIter = IntersperseIter<P::IntoIter>;
  method into_iter (line 140) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 152) | fn min_len(&self) -> usize {
  method max_len (line 155) | fn max_len(&self) -> usize {
  method split_at (line 159) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 188) | fn fold_with<F>(self, folder: F) -> F
  type IntersperseIter (line 201) | struct IntersperseIter<I>
  type Item (line 215) | type Item = I::Item;
  method next (line 217) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 233) | fn size_hint(&self) -> (usize, Option<usize>) {
  method next_back (line 243) | fn next_back(&mut self) -> Option<Self::Item> {
  method len (line 264) | fn len(&self) -> usize {
  type IntersperseConsumer (line 270) | struct IntersperseConsumer<C, T> {
  function new (line 280) | fn new(base: C, item: T) -> Self {
  type Folder (line 294) | type Folder = IntersperseFolder<C::Folder, T>;
  type Reducer (line 295) | type Reducer = C::Reducer;
  type Result (line 296) | type Result = C::Result;
  function split_at (line 298) | fn split_at(mut self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 313) | fn into_folder(self) -> Self::Folder {
  function full (line 321) | fn full(&self) -> bool {
  function split_off_left (line 331) | fn split_off_left(&self) -> Self {
  function to_reducer (line 341) | fn to_reducer(&self) -> Self::Reducer {
  type IntersperseFolder (line 346) | struct IntersperseFolder<C, T> {
  type Result (line 357) | type Result = C::Result;
  function consume (line 359) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 372) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 394) | fn complete(self) -> C::Result {
  function full (line 398) | fn full(&self) -> bool {

FILE: src/iter/len.rs
  type MinLen (line 10) | pub struct MinLen<I> {
  function new (line 17) | pub(super) fn new(base: I, min: usize) -> Self {
  type Item (line 26) | type Item = I::Item;
  method drive_unindexed (line 28) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 35) | fn opt_len(&self) -> Option<usize> {
  method drive (line 44) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
  method len (line 48) | fn len(&self) -> usize {
  method with_producer (line 52) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type MinLenProducer (line 88) | struct MinLenProducer<P> {
  type Item (line 97) | type Item = P::Item;
  type IntoIter (line 98) | type IntoIter = P::IntoIter;
  method into_iter (line 100) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 104) | fn min_len(&self) -> usize {
  method max_len (line 108) | fn max_len(&self) -> usize {
  method split_at (line 112) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 126) | fn fold_with<F>(self, folder: F) -> F
  type MaxLen (line 140) | pub struct MaxLen<I> {
  function new (line 147) | pub(super) fn new(base: I, max: usize) -> Self {
  type Item (line 156) | type Item = I::Item;
  method drive_unindexed (line 158) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 165) | fn opt_len(&self) -> Option<usize> {
  method drive (line 174) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
  method len (line 178) | fn len(&self) -> usize {
  method with_producer (line 182) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type MaxLenProducer (line 218) | struct MaxLenProducer<P> {
  type Item (line 227) | type Item = P::Item;
  type IntoIter (line 228) | type IntoIter = P::IntoIter;
  method into_iter (line 230) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 234) | fn min_len(&self) -> usize {
  method max_len (line 238) | fn max_len(&self) -> usize {
  method split_at (line 242) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 256) | fn fold_with<F>(self, folder: F) -> F

FILE: src/iter/map.rs
  type Map (line 14) | pub struct Map<I, F> {
  method fmt (line 20) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 27) | pub(super) fn new(base: I, map_op: F) -> Self {
  type Item (line 38) | type Item = F::Output;
  method drive_unindexed (line 40) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 48) | fn opt_len(&self) -> Option<usize> {
  method drive (line 59) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 67) | fn len(&self) -> usize {
  method with_producer (line 71) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type MapProducer (line 109) | struct MapProducer<'f, P, F> {
  type Item (line 120) | type Item = F::Output;
  type IntoIter (line 121) | type IntoIter = iter::Map<P::IntoIter, &'f F>;
  method into_iter (line 123) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 127) | fn min_len(&self) -> usize {
  method max_len (line 130) | fn max_len(&self) -> usize {
  method split_at (line 134) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 148) | fn fold_with<G>(self, folder: G) -> G
  type MapConsumer (line 163) | struct MapConsumer<'f, C, F> {
  function new (line 169) | fn new(base: C, map_op: &'f F) -> Self {
  type Folder (line 180) | type Folder = MapFolder<'f, C::Folder, F>;
  type Reducer (line 181) | type Reducer = C::Reducer;
  type Result (line 182) | type Result = C::Result;
  function split_at (line 184) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 193) | fn into_folder(self) -> Self::Folder {
  function full (line 200) | fn full(&self) -> bool {
  function split_off_left (line 211) | fn split_off_left(&self) -> Self {
  function to_reducer (line 215) | fn to_reducer(&self) -> Self::Reducer {
  type MapFolder (line 220) | struct MapFolder<'f, C, F> {
  type Result (line 230) | type Result = C::Result;
  function consume (line 232) | fn consume(self, item: T) -> Self {
  function consume_iter (line 240) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 248) | fn complete(self) -> C::Result {
  function full (line 252) | fn full(&self) -> bool {

FILE: src/iter/map_with.rs
  type MapWith (line 13) | pub struct MapWith<I, T, F> {
  method fmt (line 20) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 30) | pub(super) fn new(base: I, item: T, map_op: F) -> Self {
  type Item (line 42) | type Item = R;
  method drive_unindexed (line 44) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 52) | fn opt_len(&self) -> Option<usize> {
  method drive (line 64) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 72) | fn len(&self) -> usize {
  method with_producer (line 76) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type MapWithProducer (line 118) | struct MapWithProducer<'f, P, U, F> {
  type Item (line 131) | type Item = R;
  type IntoIter (line 132) | type IntoIter = MapWithIter<'f, P::IntoIter, U, F>;
  method into_iter (line 134) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 142) | fn min_len(&self) -> usize {
  method max_len (line 145) | fn max_len(&self) -> usize {
  method split_at (line 149) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 165) | fn fold_with<G>(self, folder: G) -> G
  type MapWithIter (line 178) | struct MapWithIter<'f, I, U, F> {
  type Item (line 190) | type Item = R;
  method next (line 192) | fn next(&mut self) -> Option<R> {
  method size_hint (line 197) | fn size_hint(&self) -> (usize, Option<usize>) {
  method next_back (line 208) | fn next_back(&mut self) -> Option<R> {
  type MapWithConsumer (line 225) | struct MapWithConsumer<'f, C, U, F> {
  function new (line 232) | fn new(base: C, item: U, map_op: &'f F) -> Self {
  type Folder (line 244) | type Folder = MapWithFolder<'f, C::Folder, U, F>;
  type Reducer (line 245) | type Reducer = C::Reducer;
  type Result (line 246) | type Result = C::Result;
  function split_at (line 248) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 257) | fn into_folder(self) -> Self::Folder {
  function full (line 265) | fn full(&self) -> bool {
  function split_off_left (line 277) | fn split_off_left(&self) -> Self {
  function to_reducer (line 281) | fn to_reducer(&self) -> Self::Reducer {
  type MapWithFolder (line 286) | struct MapWithFolder<'f, C, U, F> {
  type Result (line 297) | type Result = C::Result;
  function consume (line 299) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 305) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 323) | fn complete(self) -> C::Result {
  function full (line 327) | fn full(&self) -> bool {
  type MapInit (line 341) | pub struct MapInit<I, INIT, F> {
  method fmt (line 348) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 355) | pub(super) fn new(base: I, init: INIT, map_op: F) -> Self {
  type Item (line 367) | type Item = R;
  method drive_unindexed (line 369) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 377) | fn opt_len(&self) -> Option<usize> {
  method drive (line 389) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 397) | fn len(&self) -> usize {
  method with_producer (line 401) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type MapInitProducer (line 443) | struct MapInitProducer<'f, P, INIT, F> {
  type Item (line 456) | type Item = R;
  type IntoIter (line 457) | type IntoIter = MapWithIter<'f, P::IntoIter, U, F>;
  method into_iter (line 459) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 467) | fn min_len(&self) -> usize {
  method max_len (line 470) | fn max_len(&self) -> usize {
  method split_at (line 474) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 490) | fn fold_with<G>(self, folder: G) -> G
  type MapInitConsumer (line 506) | struct MapInitConsumer<'f, C, INIT, F> {
  function new (line 513) | fn new(base: C, init: &'f INIT, map_op: &'f F) -> Self {
  type Folder (line 525) | type Folder = MapWithFolder<'f, C::Folder, U, F>;
  type Reducer (line 526) | type Reducer = C::Reducer;
  type Result (line 527) | type Result = C::Result;
  function split_at (line 529) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 538) | fn into_folder(self) -> Self::Folder {
  function full (line 546) | fn full(&self) -> bool {
  function split_off_left (line 558) | fn split_off_left(&self) -> Self {
  function to_reducer (line 562) | fn to_reducer(&self) -> Self::Reducer {

FILE: src/iter/mod.rs
  type IntoParallelIterator (line 220) | pub trait IntoParallelIterator {
    method into_par_iter (line 249) | fn into_par_iter(self) -> Self::Iter;
    type Iter (line 2425) | type Iter = T;
    type Item (line 2426) | type Item = T::Item;
    method into_par_iter (line 2428) | fn into_par_iter(self) -> T {
  type IntoParallelRefIterator (line 262) | pub trait IntoParallelRefIterator<'data> {
    method par_iter (line 285) | fn par_iter(&'data self) -> Self::Iter;
  type Iter (line 292) | type Iter = <&'data I as IntoParallelIterator>::Iter;
  type Item (line 293) | type Item = <&'data I as IntoParallelIterator>::Item;
  method par_iter (line 295) | fn par_iter(&'data self) -> Self::Iter {
  type IntoParallelRefMutIterator (line 310) | pub trait IntoParallelRefMutIterator<'data> {
    method par_iter_mut (line 329) | fn par_iter_mut(&'data mut self) -> Self::Iter;
  type Iter (line 336) | type Iter = <&'data mut I as IntoParallelIterator>::Iter;
  type Item (line 337) | type Item = <&'data mut I as IntoParallelIterator>::Item;
  method par_iter_mut (line 339) | fn par_iter_mut(&'data mut self) -> Self::Iter {
  type ParallelIterator (line 357) | pub trait ParallelIterator: Sized + Send {
    method for_each (line 374) | fn for_each<OP>(self, op: OP)
    method for_each_with (line 404) | fn for_each_with<OP, T>(self, init: T, op: OP)
    method for_each_init (line 438) | fn for_each_init<OP, INIT, T>(self, init: INIT, op: OP)
    method try_for_each (line 466) | fn try_for_each<OP, R>(self, op: OP) -> R
    method try_for_each_with (line 505) | fn try_for_each_with<OP, T, R>(self, init: T, op: OP) -> R
    method try_for_each_init (line 547) | fn try_for_each_init<OP, INIT, T, R>(self, init: INIT, op: OP) -> R
    method count (line 571) | fn count(self) -> usize {
    method map (line 593) | fn map<F, R>(self, map_op: F) -> Map<Self, F>
    method map_with (line 630) | fn map_with<F, T, R>(self, init: T, map_op: F) -> MapWith<Self, T, F>
    method map_init (line 667) | fn map_init<F, INIT, T, R>(self, init: INIT, map_op: F) -> MapInit<Sel...
    method cloned (line 697) | fn cloned<'a, T>(self) -> Cloned<Self>
    method copied (line 726) | fn copied<'a, T>(self) -> Copied<Self>
    method inspect (line 763) | fn inspect<OP>(self, inspect_op: OP) -> Inspect<Self, OP>
    method update (line 783) | fn update<F>(self, update_op: F) -> Update<Self, F>
    method filter (line 804) | fn filter<P>(self, filter_op: P) -> Filter<Self, P>
    method filter_map (line 829) | fn filter_map<P, R>(self, filter_op: P) -> FilterMap<Self, P>
    method flat_map (line 855) | fn flat_map<F, PI>(self, map_op: F) -> FlatMap<Self, F>
    method flat_map_iter (line 901) | fn flat_map_iter<F, SI>(self, map_op: F) -> FlatMapIter<Self, F>
    method flatten (line 923) | fn flatten(self) -> Flatten<Self>
    method flatten_iter (line 946) | fn flatten_iter(self) -> FlattenIter<Self>
    method reduce (line 983) | fn reduce<OP, ID>(self, identity: ID, op: OP) -> Self::Item
    method reduce_with (line 1017) | fn reduce_with<OP>(self, op: OP) -> Option<Self::Item>
    method try_reduce (line 1071) | fn try_reduce<T, OP, ID>(self, identity: ID, op: OP) -> Self::Item
    method try_reduce_with (line 1115) | fn try_reduce_with<T, OP>(self, op: OP) -> Option<Self::Item>
    method fold (line 1256) | fn fold<T, ID, F>(self, identity: ID, fold_op: F) -> Fold<Self, ID, F>
    method fold_with (line 1284) | fn fold_with<F, T>(self, init: T, fold_op: F) -> FoldWith<Self, T, F>
    method try_fold (line 1317) | fn try_fold<T, R, ID, F>(self, identity: ID, fold_op: F) -> TryFold<Se...
    method try_fold_with (line 1344) | fn try_fold_with<F, T, R>(self, init: T, fold_op: F) -> TryFoldWith<Se...
    method sum (line 1377) | fn sum<S>(self) -> S
    method product (line 1410) | fn product<P>(self) -> P
    method min (line 1440) | fn min(self) -> Option<Self::Item>
    method min_by (line 1464) | fn min_by<F>(self, f: F) -> Option<Self::Item>
    method min_by_key (line 1495) | fn min_by_key<K, F>(self, f: F) -> Option<Self::Item>
    method max (line 1538) | fn max(self) -> Option<Self::Item>
    method max_by (line 1562) | fn max_by<F>(self, f: F) -> Option<Self::Item>
    method max_by_key (line 1593) | fn max_by_key<K, F>(self, f: F) -> Option<Self::Item>
    method chain (line 1629) | fn chain<C>(self, chain: C) -> Chain<Self, C::Iter>
    method find_any (line 1659) | fn find_any<P>(self, predicate: P) -> Option<Self::Item>
    method find_first (line 1692) | fn find_first<P>(self, predicate: P) -> Option<Self::Item>
    method find_last (line 1721) | fn find_last<P>(self, predicate: P) -> Option<Self::Item>
    method find_map_any (line 1751) | fn find_map_any<P, R>(self, predicate: P) -> Option<R>
    method find_map_first (line 1785) | fn find_map_first<P, R>(self, predicate: P) -> Option<R>
    method find_map_last (line 1819) | fn find_map_last<P, R>(self, predicate: P) -> Option<R>
    method find (line 1833) | fn find<P>(self, predicate: P) -> Option<Self::Item>
    method any (line 1857) | fn any<P>(self, predicate: P) -> bool
    method all (line 1879) | fn all<P>(self, predicate: P) -> bool
    method while_some (line 1913) | fn while_some<T>(self) -> WhileSome<Self>
    method panic_fuse (line 1951) | fn panic_fuse(self) -> PanicFuse<Self> {
    method collect (line 2054) | fn collect<C>(self) -> C
    method unzip (line 2095) | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
    method partition (line 2125) | fn partition<A, B, P>(self, predicate: P) -> (A, B)
    method partition_map (line 2177) | fn partition_map<A, B, P, L, R>(self, predicate: P) -> (A, B)
    method intersperse (line 2200) | fn intersperse(self, element: Self::Item) -> Intersperse<Self>
    method take_any (line 2228) | fn take_any(self, n: usize) -> TakeAny<Self> {
    method skip_any (line 2253) | fn skip_any(self, n: usize) -> SkipAny<Self> {
    method take_any_while (line 2303) | fn take_any_while<P>(self, predicate: P) -> TakeAnyWhile<Self, P>
    method skip_any_while (line 2337) | fn skip_any_while<P>(self, predicate: P) -> SkipAnyWhile<Self, P>
    method collect_vec_list (line 2376) | fn collect_vec_list(self) -> LinkedList<Vec<Self::Item>> {
    method drive_unindexed (line 2401) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
    method opt_len (line 2419) | fn opt_len(&self) -> Option<usize> {
  type IndexedParallelIterator (line 2440) | pub trait IndexedParallelIterator: ParallelIterator {
    method by_exponential_blocks (line 2474) | fn by_exponential_blocks(self) -> ExponentialBlocks<Self> {
    method by_uniform_blocks (line 2500) | fn by_uniform_blocks(self, block_size: usize) -> UniformBlocks<Self> {
    method collect_into_vec (line 2523) | fn collect_into_vec(self, target: &mut Vec<Self::Item>) {
    method unzip_into_vecs (line 2548) | fn unzip_into_vecs<A, B>(self, left: &mut Vec<A>, right: &mut Vec<B>)
    method zip (line 2575) | fn zip<Z>(self, zip_op: Z) -> Zip<Self, Z::Iter>
    method zip_eq (line 2602) | fn zip_eq<Z>(self, zip_op: Z) -> ZipEq<Self, Z::Iter>
    method interleave (line 2629) | fn interleave<I>(self, other: I) -> Interleave<Self, I::Iter>
    method interleave_shortest (line 2647) | fn interleave_shortest<I>(self, other: I) -> InterleaveShortest<Self, ...
    method chunks (line 2677) | fn chunks(self, chunk_size: usize) -> Chunks<Self> {
    method fold_chunks (line 2713) | fn fold_chunks<T, ID, F>(
    method fold_chunks_with (line 2751) | fn fold_chunks_with<T, F>(
    method cmp (line 2779) | fn cmp<I>(self, other: I) -> Ordering
    method partial_cmp (line 2817) | fn partial_cmp<I>(self, other: I) -> Option<Ordering>
    method eq (line 2842) | fn eq<I>(self, other: I) -> bool
    method ne (line 2858) | fn ne<I>(self, other: I) -> bool
    method lt (line 2868) | fn lt<I>(self, other: I) -> bool
    method le (line 2878) | fn le<I>(self, other: I) -> bool
    method gt (line 2889) | fn gt<I>(self, other: I) -> bool
    method ge (line 2899) | fn ge<I>(self, other: I) -> bool
    method enumerate (line 2923) | fn enumerate(self) -> Enumerate<Self> {
    method step_by (line 2942) | fn step_by(self, step: usize) -> StepBy<Self> {
    method skip (line 2960) | fn skip(self, n: usize) -> Skip<Self> {
    method take (line 2978) | fn take(self, n: usize) -> Take<Self> {
    method position_any (line 3000) | fn position_any<P>(self, predicate: P) -> Option<usize>
    method position_first (line 3037) | fn position_first<P>(self, predicate: P) -> Option<usize>
    method position_last (line 3074) | fn position_last<P>(self, predicate: P) -> Option<usize>
    method position (line 3092) | fn position<P>(self, predicate: P) -> Option<usize>
    method positions (line 3117) | fn positions<P>(self, predicate: P) -> Positions<Self, P>
    method rev (line 3139) | fn rev(self) -> Rev<Self> {
    method with_min_len (line 3165) | fn with_min_len(self, min: usize) -> MinLen<Self> {
    method with_max_len (line 3193) | fn with_max_len(self, max: usize) -> MaxLen<Self> {
    method len (line 3211) | fn len(&self) -> usize;
    method drive (line 3227) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result;
    method with_producer (line 3244) | fn with_producer<CB: ProducerCallback<Self::Item>>(self, callback: CB)...
  type FromParallelIterator (line 3281) | pub trait FromParallelIterator<T>
    method from_par_iter (line 3301) | fn from_par_iter<I>(par_iter: I) -> Self
  type ParallelExtend (line 3334) | pub trait ParallelExtend<T>
    method par_extend (line 3351) | fn par_extend<I>(&mut self, par_iter: I)
  type ParallelDrainFull (line 3361) | pub trait ParallelDrainFull {
    method par_drain (line 3394) | fn par_drain(self) -> Self::Iter;
  type ParallelDrainRange (line 3401) | pub trait ParallelDrainRange<Idx = usize> {
    method par_drain (line 3467) | fn par_drain<R: RangeBounds<Idx>>(self, range: R) -> Self::Iter;
  type Try (line 3480) | pub trait Try {
    method from_output (line 3486) | fn from_output(output: Self::Output) -> Self;
    method from_residual (line 3488) | fn from_residual(residual: Self::Residual) -> Self;
    method branch (line 3490) | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
    type Output (line 3496) | type Output = C;
    type Residual (line 3497) | type Residual = ControlFlow<B, Infallible>;
    method from_output (line 3499) | fn from_output(output: Self::Output) -> Self {
    method from_residual (line 3503) | fn from_residual(residual: Self::Residual) -> Self {
    method branch (line 3511) | fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
    type Output (line 3522) | type Output = T;
    type Residual (line 3523) | type Residual = Option<Infallible>;
    method from_output (line 3525) | fn from_output(output: Self::Output) -> Self {
    method from_residual (line 3529) | fn from_residual(residual: Self::Residual) -> Self {
    method branch (line 3537) | fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
    type Output (line 3548) | type Output = T;
    type Residual (line 3549) | type Residual = Result<Infallible, E>;
    method from_output (line 3551) | fn from_output(output: Self::Output) -> Self {
    method from_residual (line 3555) | fn from_residual(residual: Self::Residual) -> Self {
    method branch (line 3563) | fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
    type Output (line 3574) | type Output = Poll<T>;
    type Residual (line 3575) | type Residual = Result<Infallible, E>;
    method from_output (line 3577) | fn from_output(output: Self::Output) -> Self {
    method from_residual (line 3581) | fn from_residual(residual: Self::Residual) -> Self {
    method branch (line 3589) | fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
    type Output (line 3601) | type Output = Poll<Option<T>>;
    type Residual (line 3602) | type Residual = Result<Infallible, E>;
    method from_output (line 3604) | fn from_output(output: Self::Output) -> Self {
    method from_residual (line 3611) | fn from_residual(residual: Self::Residual) -> Self {
    method branch (line 3619) | fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {

FILE: src/iter/multizip.rs
  type MultiZip (line 79) | pub struct MultiZip<T> {

FILE: src/iter/noop.rs
  type NoopConsumer (line 3) | pub(super) struct NoopConsumer;
    type Folder (line 6) | type Folder = NoopConsumer;
    type Reducer (line 7) | type Reducer = NoopReducer;
    type Result (line 8) | type Result = ();
    method split_at (line 10) | fn split_at(self, _index: usize) -> (Self, Self, NoopReducer) {
    method into_folder (line 14) | fn into_folder(self) -> Self {
    method full (line 18) | fn full(&self) -> bool {
    type Result (line 24) | type Result = ();
    method consume (line 26) | fn consume(self, _item: T) -> Self {
    method consume_iter (line 30) | fn consume_iter<I>(self, iter: I) -> Self
    method complete (line 38) | fn complete(self) {}
    method full (line 40) | fn full(&self) -> bool {
    method split_off_left (line 46) | fn split_off_left(&self) -> Self {
    method to_reducer (line 50) | fn to_reducer(&self) -> NoopReducer {
  type NoopReducer (line 55) | pub(super) struct NoopReducer;
    method reduce (line 58) | fn reduce(self, _left: (), _right: ()) {}

FILE: src/iter/once.rs
  function once (line 24) | pub fn once<T: Send>(item: T) -> Once<T> {
  type Once (line 32) | pub struct Once<T> {
  type Item (line 37) | type Item = T;
  method drive_unindexed (line 39) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 46) | fn opt_len(&self) -> Option<usize> {
  method drive (line 52) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 59) | fn len(&self) -> usize {
  method with_producer (line 63) | fn with_producer<CB>(self, callback: CB) -> CB::Output

FILE: src/iter/panic_fuse.rs
  type PanicFuse (line 14) | pub struct PanicFuse<I> {
  type Fuse (line 20) | struct Fuse<'a>(&'a AtomicBool);
  method drop (line 24) | fn drop(&mut self) {
  function panicked (line 33) | fn panicked(&self) -> bool {
  function new (line 40) | pub(super) fn new(base: I) -> PanicFuse<I> {
  type Item (line 49) | type Item = I::Item;
  method drive_unindexed (line 51) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 63) | fn opt_len(&self) -> Option<usize> {
  method drive (line 72) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 84) | fn len(&self) -> usize {
  method with_producer (line 88) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type PanicFuseProducer (line 122) | struct PanicFuseProducer<'a, P> {
  type Item (line 131) | type Item = P::Item;
  type IntoIter (line 132) | type IntoIter = PanicFuseIter<'a, P::IntoIter>;
  method into_iter (line 134) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 141) | fn min_len(&self) -> usize {
  method max_len (line 144) | fn max_len(&self) -> usize {
  method split_at (line 148) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 162) | fn fold_with<G>(self, folder: G) -> G
  type PanicFuseIter (line 174) | struct PanicFuseIter<'a, I> {
  type Item (line 183) | type Item = I::Item;
  method next (line 185) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 193) | fn size_hint(&self) -> (usize, Option<usize>) {
  method next_back (line 202) | fn next_back(&mut self) -> Option<Self::Item> {
  method len (line 215) | fn len(&self) -> usize {
  type PanicFuseConsumer (line 223) | struct PanicFuseConsumer<'a, C> {
  type Folder (line 232) | type Folder = PanicFuseFolder<'a, C::Folder>;
  type Reducer (line 233) | type Reducer = PanicFuseReducer<'a, C::Reducer>;
  type Result (line 234) | type Result = C::Result;
  function split_at (line 236) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 254) | fn into_folder(self) -> Self::Folder {
  function full (line 261) | fn full(&self) -> bool {
  function split_off_left (line 270) | fn split_off_left(&self) -> Self {
  function to_reducer (line 277) | fn to_reducer(&self) -> Self::Reducer {
  type PanicFuseFolder (line 285) | struct PanicFuseFolder<'a, C> {
  type Result (line 294) | type Result = C::Result;
  function consume (line 296) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 301) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 317) | fn complete(self) -> C::Result {
  function full (line 321) | fn full(&self) -> bool {
  type PanicFuseReducer (line 326) | struct PanicFuseReducer<'a, C> {
  function reduce (line 335) | fn reduce(self, left: T, right: T) -> T {

FILE: src/iter/par_bridge.rs
  type ParallelBridge (line 53) | pub trait ParallelBridge: Sized {
    method par_bridge (line 55) | fn par_bridge(self) -> IterBridge<Self>;
    method par_bridge (line 62) | fn par_bridge(self) -> IterBridge<Self> {
  type IterBridge (line 72) | pub struct IterBridge<Iter> {
  type Item (line 80) | type Item = Iter::Item;
  method drive_unindexed (line 82) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type IterParallelProducer (line 100) | struct IterParallelProducer<'a, Iter> {
  type Item (line 107) | type Item = Iter::Item;
  method split (line 109) | fn split(self) -> (Self, Option<Self>) {
  method fold_with (line 117) | fn fold_with<F>(self, mut folder: F) -> F

FILE: src/iter/plumbing/mod.rs
  type ProducerCallback (line 17) | pub trait ProducerCallback<T> {
    method callback (line 27) | fn callback<P>(self, producer: P) -> Self::Output
  type Producer (line 56) | pub trait Producer: Send + Sized {
    method into_iter (line 66) | fn into_iter(self) -> Self::IntoIter;
    method min_len (line 78) | fn min_len(&self) -> usize {
    method max_len (line 91) | fn max_len(&self) -> usize {
    method split_at (line 97) | fn split_at(self, index: usize) -> (Self, Self);
    method fold_with (line 103) | fn fold_with<F>(self, folder: F) -> F
  type Consumer (line 123) | pub trait Consumer<Item>: Send + Sized {
    method split_at (line 137) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer);
    method into_folder (line 141) | fn into_folder(self) -> Self::Folder;
    method full (line 145) | fn full(&self) -> bool;
  type Folder (line 154) | pub trait Folder<Item>: Sized {
    method consume (line 159) | fn consume(self, item: Item) -> Self;
    method consume_iter (line 169) | fn consume_iter<I>(mut self, iter: I) -> Self
    method complete (line 183) | fn complete(self) -> Self::Result;
    method full (line 187) | fn full(&self) -> bool;
  type Reducer (line 197) | pub trait Reducer<Result> {
    method reduce (line 200) | fn reduce(self, left: Result, right: Result) -> Result;
  type UnindexedConsumer (line 208) | pub trait UnindexedConsumer<I>: Consumer<I> {
    method split_off_left (line 216) | fn split_off_left(&self) -> Self;
    method to_reducer (line 220) | fn to_reducer(&self) -> Self::Reducer;
  type UnindexedProducer (line 231) | pub trait UnindexedProducer: Send + Sized {
    method split (line 236) | fn split(self) -> (Self, Option<Self>);
    method fold_with (line 240) | fn fold_with<F>(self, folder: F) -> F
  type Splitter (line 251) | struct Splitter {
    method new (line 260) | fn new() -> Splitter {
    method try_split (line 267) | fn try_split(&mut self, stolen: bool) -> bool {
  type LengthSplitter (line 289) | struct LengthSplitter {
    method new (line 308) | fn new(min: usize, max: usize, len: usize) -> LengthSplitter {
    method try_split (line 329) | fn try_split(&mut self, len: usize, stolen: bool) -> bool {
  function bridge (line 346) | pub fn bridge<I, C>(par_iter: I, consumer: C) -> C::Result
  function bridge_producer_consumer (line 385) | pub fn bridge_producer_consumer<P, C>(len: usize, producer: P, consumer:...
  function bridge_unindexed (line 438) | pub fn bridge_unindexed<P, C>(producer: P, consumer: C) -> C::Result
  function bridge_unindexed_producer_consumer (line 447) | fn bridge_unindexed_producer_consumer<P, C>(

FILE: src/iter/positions.rs
  type Positions (line 14) | pub struct Positions<I, P> {
  method fmt (line 20) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 29) | pub(super) fn new(base: I, predicate: P) -> Self {
  type Item (line 39) | type Item = usize;
  method drive_unindexed (line 41) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type PositionsConsumer (line 53) | struct PositionsConsumer<'p, C, P> {
  function new (line 60) | fn new(base: C, predicate: &'p P, offset: usize) -> Self {
  type Folder (line 74) | type Folder = PositionsFolder<'p, C::Folder, P>;
  type Reducer (line 75) | type Reducer = C::Reducer;
  type Result (line 76) | type Result = C::Result;
  function split_at (line 78) | fn split_at(self, index: usize) -> (Self, Self, C::Reducer) {
  function into_folder (line 87) | fn into_folder(self) -> Self::Folder {
  function full (line 95) | fn full(&self) -> bool {
  type PositionsFolder (line 100) | struct PositionsFolder<'p, F, P> {
  type Result (line 111) | type Result = F::Result;
  function consume (line 113) | fn consume(mut self, item: T) -> Self {
  function complete (line 126) | fn complete(self) -> Self::Result {
  function full (line 130) | fn full(&self) -> bool {

FILE: src/iter/product.rs
  function product (line 7) | pub(super) fn product<PI, P>(pi: PI) -> P
  function mul (line 15) | fn mul<T: Product>(left: T, right: T) -> T {
  type ProductConsumer (line 19) | struct ProductConsumer<P: Send> {
  function new (line 26) | fn new() -> ProductConsumer<P> {
  type Folder (line 37) | type Folder = ProductFolder<P>;
  type Reducer (line 38) | type Reducer = Self;
  type Result (line 39) | type Result = P;
  function split_at (line 41) | fn split_at(self, _index: usize) -> (Self, Self, Self) {
  function into_folder (line 49) | fn into_folder(self) -> Self::Folder {
  function full (line 55) | fn full(&self) -> bool {
  function split_off_left (line 64) | fn split_off_left(&self) -> Self {
  function to_reducer (line 68) | fn to_reducer(&self) -> Self::Reducer {
  function reduce (line 77) | fn reduce(self, left: P, right: P) -> P {
  type ProductFolder (line 82) | struct ProductFolder<P> {
  type Result (line 90) | type Result = P;
  function consume (line 92) | fn consume(self, item: T) -> Self {
  function consume_iter (line 98) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 107) | fn complete(self) -> P {
  function full (line 111) | fn full(&self) -> bool {

FILE: src/iter/reduce.rs
  function reduce (line 4) | pub(super) fn reduce<PI, R, ID, T>(pi: PI, identity: ID, reduce_op: R) -> T
  type ReduceConsumer (line 18) | struct ReduceConsumer<'r, R, ID> {
  method clone (line 26) | fn clone(&self) -> Self {
  type Folder (line 37) | type Folder = ReduceFolder<'r, R, T>;
  type Reducer (line 38) | type Reducer = Self;
  type Result (line 39) | type Result = T;
  function split_at (line 41) | fn split_at(self, _index: usize) -> (Self, Self, Self) {
  function into_folder (line 45) | fn into_folder(self) -> Self::Folder {
  function full (line 52) | fn full(&self) -> bool {
  function split_off_left (line 63) | fn split_off_left(&self) -> Self {
  function to_reducer (line 67) | fn to_reducer(&self) -> Self::Reducer {
  function reduce (line 76) | fn reduce(self, left: T, right: T) -> T {
  type ReduceFolder (line 81) | struct ReduceFolder<'r, R, T> {
  type Result (line 90) | type Result = T;
  function consume (line 92) | fn consume(self, item: T) -> Self {
  function consume_iter (line 99) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 109) | fn complete(self) -> T {
  function full (line 113) | fn full(&self) -> bool {

FILE: src/iter/repeat.rs
  type Repeat (line 10) | pub struct Repeat<T> {
  function repeat (line 30) | pub fn repeat<T: Clone + Send>(element: T) -> Repeat<T> {
  function take (line 45) | pub fn take(self, n: usize) -> RepeatN<T> {
  function zip (line 53) | pub fn zip<Z>(self, zip_op: Z) -> Zip<RepeatN<T>, Z::Iter>
  type Item (line 67) | type Item = T;
  method drive_unindexed (line 69) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type RepeatProducer (line 81) | struct RepeatProducer<T: Clone + Send> {
  type Item (line 86) | type Item = T;
  method split (line 88) | fn split(self) -> (Self, Option<Self>) {
  method fold_with (line 99) | fn fold_with<F>(self, folder: F) -> F
  type RepeatN (line 111) | pub struct RepeatN<T> {
  function repeat_n (line 126) | pub fn repeat_n<T: Clone + Send>(element: T, n: usize) -> RepeatN<T> {
  function repeatn (line 139) | pub fn repeatn<T: Clone + Send>(element: T, n: usize) -> RepeatN<T> {
  function fmt (line 144) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 160) | type Item = T;
  method drive_unindexed (line 162) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 169) | fn opt_len(&self) -> Option<usize> {
  method drive (line 178) | fn drive<C>(self, consumer: C) -> C::Result
  method with_producer (line 185) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  method len (line 192) | fn len(&self) -> usize {
  type RepeatNProducer (line 199) | enum RepeatNProducer<T> {
  type Item (line 205) | type Item = T;
  type IntoIter (line 206) | type IntoIter = Self;
  method into_iter (line 208) | fn into_iter(self) -> Self::IntoIter {
  method split_at (line 214) | fn split_at(self, index: usize) -> (Self, Self) {
  type Item (line 237) | type Item = T;
  method next (line 240) | fn next(&mut self) -> Option<T> {
  method nth (line 257) | fn nth(&mut self, n: usize) -> Option<T> {
  method size_hint (line 269) | fn size_hint(&self) -> (usize, Option<usize>) {
  method next_back (line 277) | fn next_back(&mut self) -> Option<T> {
  method nth_back (line 282) | fn nth_back(&mut self, n: usize) -> Option<T> {
  method len (line 289) | fn len(&self) -> usize {

FILE: src/iter/rev.rs
  type Rev (line 11) | pub struct Rev<I> {
  function new (line 17) | pub(super) fn new(base: I) -> Self {
  type Item (line 26) | type Item = I::Item;
  method drive_unindexed (line 28) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 35) | fn opt_len(&self) -> Option<usize> {
  method drive (line 44) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
  method len (line 48) | fn len(&self) -> usize {
  method with_producer (line 52) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type RevProducer (line 83) | struct RevProducer<P> {
  type Item (line 92) | type Item = P::Item;
  type IntoIter (line 93) | type IntoIter = iter::Rev<P::IntoIter>;
  method into_iter (line 95) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 99) | fn min_len(&self) -> usize {
  method max_len (line 102) | fn max_len(&self) -> usize {
  method split_at (line 106) | fn split_at(self, index: usize) -> (Self, Self) {

FILE: src/iter/skip.rs
  type Skip (line 11) | pub struct Skip<I> {
  function new (line 21) | pub(super) fn new(base: I, n: usize) -> Self {
  type Item (line 31) | type Item = I::Item;
  method drive_unindexed (line 33) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 40) | fn opt_len(&self) -> Option<usize> {
  method len (line 49) | fn len(&self) -> usize {
  method drive (line 53) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
  method with_producer (line 57) | fn with_producer<CB>(self, callback: CB) -> CB::Output

FILE: src/iter/skip_any.rs
  type SkipAny (line 11) | pub struct SkipAny<I> {
  function new (line 18) | pub(super) fn new(base: I, count: usize) -> Self {
  type Item (line 27) | type Item = I::Item;
  method drive_unindexed (line 29) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type SkipAnyConsumer (line 44) | struct SkipAnyConsumer<'f, C> {
  type Folder (line 54) | type Folder = SkipAnyFolder<'f, C::Folder>;
  type Reducer (line 55) | type Reducer = C::Reducer;
  type Result (line 56) | type Result = C::Result;
  function split_at (line 58) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 70) | fn into_folder(self) -> Self::Folder {
  function full (line 77) | fn full(&self) -> bool {
  function split_off_left (line 87) | fn split_off_left(&self) -> Self {
  function to_reducer (line 94) | fn to_reducer(&self) -> Self::Reducer {
  type SkipAnyFolder (line 99) | struct SkipAnyFolder<'f, C> {
  function checked_decrement (line 104) | fn checked_decrement(u: &AtomicUsize) -> bool {
  type Result (line 113) | type Result = C::Result;
  function consume (line 115) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 122) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 133) | fn complete(self) -> C::Result {
  function full (line 137) | fn full(&self) -> bool {

FILE: src/iter/skip_any_while.rs
  type SkipAnyWhile (line 13) | pub struct SkipAnyWhile<I, P> {
  function fmt (line 19) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 28) | pub(super) fn new(base: I, predicate: P) -> Self {
  type Item (line 38) | type Item = I::Item;
  method drive_unindexed (line 40) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type SkipAnyWhileConsumer (line 56) | struct SkipAnyWhileConsumer<'p, C, P> {
  type Folder (line 67) | type Folder = SkipAnyWhileFolder<'p, C::Folder, P>;
  type Reducer (line 68) | type Reducer = C::Reducer;
  type Result (line 69) | type Result = C::Result;
  function split_at (line 71) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 83) | fn into_folder(self) -> Self::Folder {
  function full (line 91) | fn full(&self) -> bool {
  function split_off_left (line 101) | fn split_off_left(&self) -> Self {
  function to_reducer (line 108) | fn to_reducer(&self) -> Self::Reducer {
  type SkipAnyWhileFolder (line 113) | struct SkipAnyWhileFolder<'p, C, P> {
  function skip (line 119) | fn skip<T>(item: &T, skipping: &AtomicBool, predicate: &impl Fn(&T) -> b...
  type Result (line 135) | type Result = C::Result;
  function consume (line 137) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 144) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 155) | fn complete(self) -> C::Result {
  function full (line 159) | fn full(&self) -> bool {

FILE: src/iter/splitter.rs
  function split (line 106) | pub fn split<D, S>(data: D, splitter: S) -> Split<D, S>
  type Split (line 117) | pub struct Split<D, S> {
  method fmt (line 123) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 133) | type Item = D;
  method drive_unindexed (line 135) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type SplitProducer (line 147) | struct SplitProducer<'a, D, S> {
  type Item (line 157) | type Item = D;
  method split (line 159) | fn split(mut self) -> (Self, Option<Self>) {
  method fold_with (line 166) | fn fold_with<F>(self, folder: F) -> F

FILE: src/iter/step_by.rs
  type StepBy (line 11) | pub struct StepBy<I> {
  function new (line 18) | pub(super) fn new(base: I, step: usize) -> Self {
  type Item (line 27) | type Item = I::Item;
  method drive_unindexed (line 29) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 36) | fn opt_len(&self) -> Option<usize> {
  method drive (line 45) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
  method len (line 49) | fn len(&self) -> usize {
  method with_producer (line 53) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type StepByProducer (line 93) | struct StepByProducer<P> {
  type Item (line 103) | type Item = P::Item;
  type IntoIter (line 104) | type IntoIter = iter::StepBy<P::IntoIter>;
  method into_iter (line 106) | fn into_iter(self) -> Self::IntoIter {
  method split_at (line 110) | fn split_at(self, index: usize) -> (Self, Self) {
  method min_len (line 128) | fn min_len(&self) -> usize {
  method max_len (line 132) | fn max_len(&self) -> usize {

FILE: src/iter/sum.rs
  function sum (line 7) | pub(super) fn sum<PI, S>(pi: PI) -> S
  function add (line 15) | fn add<T: Sum>(left: T, right: T) -> T {
  type SumConsumer (line 19) | struct SumConsumer<S: Send> {
  function new (line 26) | fn new() -> SumConsumer<S> {
  type Folder (line 37) | type Folder = SumFolder<S>;
  type Reducer (line 38) | type Reducer = Self;
  type Result (line 39) | type Result = S;
  function split_at (line 41) | fn split_at(self, _index: usize) -> (Self, Self, Self) {
  function into_folder (line 45) | fn into_folder(self) -> Self::Folder {
  function full (line 51) | fn full(&self) -> bool {
  function split_off_left (line 60) | fn split_off_left(&self) -> Self {
  function to_reducer (line 64) | fn to_reducer(&self) -> Self::Reducer {
  function reduce (line 73) | fn reduce(self, left: S, right: S) -> S {
  type SumFolder (line 78) | struct SumFolder<S> {
  type Result (line 86) | type Result = S;
  function consume (line 88) | fn consume(self, item: T) -> Self {
  function consume_iter (line 94) | fn consume_iter<I>(self, iter: I) -> Self
  function complete (line 103) | fn complete(self) -> S {
  function full (line 107) | fn full(&self) -> bool {

FILE: src/iter/take.rs
  type Take (line 10) | pub struct Take<I> {
  function new (line 20) | pub(super) fn new(base: I, n: usize) -> Self {
  type Item (line 30) | type Item = I::Item;
  method drive_unindexed (line 32) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 39) | fn opt_len(&self) -> Option<usize> {
  method len (line 48) | fn len(&self) -> usize {
  method drive (line 52) | fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
  method with_producer (line 56) | fn with_producer<CB>(self, callback: CB) -> CB::Output

FILE: src/iter/take_any.rs
  type TakeAny (line 11) | pub struct TakeAny<I> {
  function new (line 18) | pub(super) fn new(base: I, count: usize) -> Self {
  type Item (line 27) | type Item = I::Item;
  method drive_unindexed (line 29) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type TakeAnyConsumer (line 44) | struct TakeAnyConsumer<'f, C> {
  type Folder (line 54) | type Folder = TakeAnyFolder<'f, C::Folder>;
  type Reducer (line 55) | type Reducer = C::Reducer;
  type Result (line 56) | type Result = C::Result;
  function split_at (line 58) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 70) | fn into_folder(self) -> Self::Folder {
  function full (line 77) | fn full(&self) -> bool {
  function split_off_left (line 87) | fn split_off_left(&self) -> Self {
  function to_reducer (line 94) | fn to_reducer(&self) -> Self::Reducer {
  type TakeAnyFolder (line 99) | struct TakeAnyFolder<'f, C> {
  function checked_decrement (line 104) | fn checked_decrement(u: &AtomicUsize) -> bool {
  type Result (line 113) | type Result = C::Result;
  function consume (line 115) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 122) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 133) | fn complete(self) -> C::Result {
  function full (line 137) | fn full(&self) -> bool {

FILE: src/iter/take_any_while.rs
  type TakeAnyWhile (line 13) | pub struct TakeAnyWhile<I, P> {
  function fmt (line 19) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 28) | pub(super) fn new(base: I, predicate: P) -> Self {
  type Item (line 38) | type Item = I::Item;
  method drive_unindexed (line 40) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type TakeAnyWhileConsumer (line 56) | struct TakeAnyWhileConsumer<'p, C, P> {
  type Folder (line 67) | type Folder = TakeAnyWhileFolder<'p, C::Folder, P>;
  type Reducer (line 68) | type Reducer = C::Reducer;
  type Result (line 69) | type Result = C::Result;
  function split_at (line 71) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 83) | fn into_folder(self) -> Self::Folder {
  function full (line 91) | fn full(&self) -> bool {
  function split_off_left (line 101) | fn split_off_left(&self) -> Self {
  function to_reducer (line 108) | fn to_reducer(&self) -> Self::Reducer {
  type TakeAnyWhileFolder (line 113) | struct TakeAnyWhileFolder<'p, C, P> {
  function take (line 119) | fn take<T>(item: &T, taking: &AtomicBool, predicate: &impl Fn(&T) -> boo...
  type Result (line 135) | type Result = C::Result;
  function consume (line 137) | fn consume(mut self, item: T) -> Self {
  function consume_iter (line 144) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 155) | fn complete(self) -> C::Result {
  function full (line 159) | fn full(&self) -> bool {

FILE: src/iter/test.rs
  function is_indexed (line 16) | fn is_indexed<T: IndexedParallelIterator>(_: T) {}
  function seeded_rng (line 18) | fn seeded_rng() -> XorShiftRng {
  function execute (line 25) | fn execute() {
  function execute_cloned (line 34) | fn execute_cloned() {
  function execute_range (line 43) | fn execute_range() {
  function execute_unindexed_range (line 52) | fn execute_unindexed_range() {
  function execute_pseudo_indexed_range (line 60) | fn execute_pseudo_indexed_range() {
  function check_map_indexed (line 73) | fn check_map_indexed() {
  function map_sum (line 79) | fn map_sum() {
  function map_reduce (line 87) | fn map_reduce() {
  function map_reduce_with (line 95) | fn map_reduce_with() {
  function fold_map_reduce (line 103) | fn fold_map_reduce() {
  function fold_is_full (line 166) | fn fold_is_full() {
  function check_step_by (line 180) | fn check_step_by() {
  function check_step_by_unaligned (line 188) | fn check_step_by_unaligned() {
  function check_step_by_rev (line 196) | fn check_step_by_rev() {
  function check_enumerate (line 204) | fn check_enumerate() {
  function check_enumerate_rev (line 216) | fn check_enumerate_rev() {
  function check_indices_after_enumerate_split (line 229) | fn check_indices_after_enumerate_split() {
  function check_increment (line 254) | fn check_increment() {
  function check_skip (line 263) | fn check_skip() {
  function check_take (line 293) | fn check_take() {
  function check_inspect (line 313) | fn check_inspect() {
  function check_move (line 328) | fn check_move() {
  function check_drops (line 340) | fn check_drops() {
  function check_slice_indexed (line 378) | fn check_slice_indexed() {
  function check_slice_mut_indexed (line 384) | fn check_slice_mut_indexed() {
  function check_vec_indexed (line 390) | fn check_vec_indexed() {
  function check_range_indexed (line 396) | fn check_range_indexed() {
  function check_cmp_direct (line 401) | fn check_cmp_direct() {
  function check_cmp_to_seq (line 411) | fn check_cmp_to_seq() {
  function check_cmp_rng_to_seq (line 419) | fn check_cmp_rng_to_seq() {
  function check_cmp_lt_direct (line 433) | fn check_cmp_lt_direct() {
  function check_cmp_lt_to_seq (line 443) | fn check_cmp_lt_to_seq() {
  function check_cmp_gt_direct (line 451) | fn check_cmp_gt_direct() {
  function check_cmp_gt_to_seq (line 461) | fn check_cmp_gt_to_seq() {
  function check_cmp_short_circuit (line 470) | fn check_cmp_short_circuit() {
  function check_partial_cmp_short_circuit (line 500) | fn check_partial_cmp_short_circuit() {
  function check_partial_cmp_nan_short_circuit (line 530) | fn check_partial_cmp_nan_short_circuit() {
  function check_partial_cmp_direct (line 559) | fn check_partial_cmp_direct() {
  function check_partial_cmp_to_seq (line 569) | fn check_partial_cmp_to_seq() {
  function check_partial_cmp_rng_to_seq (line 576) | fn check_partial_cmp_rng_to_seq() {
  function check_partial_cmp_lt_direct (line 590) | fn check_partial_cmp_lt_direct() {
  function check_partial_cmp_lt_to_seq (line 600) | fn check_partial_cmp_lt_to_seq() {
  function check_partial_cmp_gt_direct (line 607) | fn check_partial_cmp_gt_direct() {
  function check_partial_cmp_gt_to_seq (line 617) | fn check_partial_cmp_gt_to_seq() {
  function check_partial_cmp_none_direct (line 624) | fn check_partial_cmp_none_direct() {
  function check_partial_cmp_none_to_seq (line 634) | fn check_partial_cmp_none_to_seq() {
  function check_partial_cmp_late_nan_direct (line 645) | fn check_partial_cmp_late_nan_direct() {
  function check_partial_cmp_late_nan_to_seq (line 655) | fn check_partial_cmp_late_nan_to_seq() {
  function check_cmp_lengths (line 666) | fn check_cmp_lengths() {
  function check_eq_direct (line 676) | fn check_eq_direct() {
  function check_eq_to_seq (line 686) | fn check_eq_to_seq() {
  function check_ne_direct (line 694) | fn check_ne_direct() {
  function check_ne_to_seq (line 704) | fn check_ne_to_seq() {
  function check_ne_lengths (line 712) | fn check_ne_lengths() {
  function check_lt_direct (line 722) | fn check_lt_direct() {
  function check_lt_to_seq (line 728) | fn check_lt_to_seq() {
  function check_le_equal_direct (line 736) | fn check_le_equal_direct() {
  function check_le_equal_to_seq (line 741) | fn check_le_equal_to_seq() {
  function check_le_less_direct (line 749) | fn check_le_less_direct() {
  function check_le_less_to_seq (line 754) | fn check_le_less_to_seq() {
  function check_gt_direct (line 762) | fn check_gt_direct() {
  function check_gt_to_seq (line 767) | fn check_gt_to_seq() {
  function check_ge_equal_direct (line 775) | fn check_ge_equal_direct() {
  function check_ge_equal_to_seq (line 780) | fn check_ge_equal_to_seq() {
  function check_ge_greater_direct (line 788) | fn check_ge_greater_direct() {
  function check_ge_greater_to_seq (line 793) | fn check_ge_greater_to_seq() {
  function check_zip (line 801) | fn check_zip() {
  function check_zip_into_par_iter (line 811) | fn check_zip_into_par_iter() {
  function check_zip_into_mut_par_iter (line 823) | fn check_zip_into_mut_par_iter() {
  function check_zip_range (line 833) | fn check_zip_range() {
  function check_zip_eq (line 844) | fn check_zip_eq() {
  function check_zip_eq_into_par_iter (line 854) | fn check_zip_eq_into_par_iter() {
  function check_zip_eq_into_mut_par_iter (line 866) | fn check_zip_eq_into_mut_par_iter() {
  function check_zip_eq_range (line 876) | fn check_zip_eq_range() {
  function check_sum_filtered_ints (line 887) | fn check_sum_filtered_ints() {
  function check_sum_filtermap_ints (line 895) | fn check_sum_filtermap_ints() {
  function check_flat_map_nested_ranges (line 909) | fn check_flat_map_nested_ranges() {
  function check_empty_flat_map_sum (line 927) | fn check_empty_flat_map_sum() {
  function check_flatten_vec (line 941) | fn check_flatten_vec() {
  function check_flatten_vec_empty (line 954) | fn check_flatten_vec_empty() {
  function check_slice_split (line 962) | fn check_slice_split() {
  function check_slice_split_inclusive (line 985) | fn check_slice_split_inclusive() {
  function check_slice_split_mut (line 1004) | fn check_slice_split_mut() {
  function check_slice_split_inclusive_mut (line 1022) | fn check_slice_split_inclusive_mut() {
  function check_chunks (line 1042) | fn check_chunks() {
  function check_chunks_mut (line 1056) | fn check_chunks_mut() {
  function check_windows (line 1073) | fn check_windows() {
  function check_options (line 1101) | fn check_options() {
  function check_results (line 1115) | fn check_results() {
  function check_binary_heap (line 1134) | fn check_binary_heap() {
  function check_btree_map (line 1144) | fn check_btree_map() {
  function check_btree_set (line 1158) | fn check_btree_set() {
  function check_hash_map (line 1168) | fn check_hash_map() {
  function check_hash_set (line 1182) | fn check_hash_set() {
  function check_linked_list (line 1192) | fn check_linked_list() {
  function check_vec_deque (line 1205) | fn check_vec_deque() {
  function check_chain (line 1222) | fn check_chain() {
  function check_count (line 1278) | fn check_count() {
  function find_any (line 1288) | fn find_any() {
  function find_first_or_last (line 1313) | fn find_first_or_last() {
  function find_map_first_or_last_or_any (line 1352) | fn find_map_first_or_last_or_any() {
  function check_find_not_present (line 1396) | fn check_find_not_present() {
  function check_find_is_present (line 1407) | fn check_find_is_present() {
  function check_while_some (line 1419) | fn check_while_some() {
  function par_iter_collect_option (line 1441) | fn par_iter_collect_option() {
  function par_iter_collect_result (line 1454) | fn par_iter_collect_result() {
  function par_iter_collect (line 1473) | fn par_iter_collect() {
  function par_iter_collect_vecdeque (line 1481) | fn par_iter_collect_vecdeque() {
  function par_iter_collect_binaryheap (line 1489) | fn par_iter_collect_binaryheap() {
  function par_iter_collect_hashmap (line 1501) | fn par_iter_collect_hashmap() {
  function par_iter_collect_hashset (line 1509) | fn par_iter_collect_hashset() {
  function par_iter_collect_btreemap (line 1516) | fn par_iter_collect_btreemap() {
  function par_iter_collect_btreeset (line 1524) | fn par_iter_collect_btreeset() {
  function par_iter_collect_linked_list (line 1531) | fn par_iter_collect_linked_list() {
  function par_iter_collect_linked_list_flat_map_filter (line 1539) | fn par_iter_collect_linked_list_flat_map_filter() {
  function par_iter_collect_cows (line 1553) | fn par_iter_collect_cows() {
  function par_iter_unindexed_flat_map (line 1594) | fn par_iter_unindexed_flat_map() {
  function min_max (line 1601) | fn min_max() {
  function min_max_by (line 1612) | fn min_max_by() {
  function min_max_by_key (line 1631) | fn min_max_by_key() {
  function check_rev (line 1650) | fn check_rev() {
  function scope_mix (line 1658) | fn scope_mix() {
  function divide_and_conquer (line 1673) | fn divide_and_conquer<'scope>(scope: &Scope<'scope>, counter: &'scope At...
  function check_split (line 1684) | fn check_split() {
  function check_lengths (line 1703) | fn check_lengths() {
  function check_map_with (line 1733) | fn check_map_with() {
  function check_fold_with (line 1747) | fn check_fold_with() {
  function check_for_each_with (line 1764) | fn check_for_each_with() {
  function check_extend_items (line 1777) | fn check_extend_items() {
  function check_extend_heap (line 1811) | fn check_extend_heap() {
  function check_extend_pairs (line 1831) | fn check_extend_pairs() {
  function check_unzip_into_vecs (line 1863) | fn check_unzip_into_vecs() {
  function check_unzip (line 1878) | fn check_unzip() {
  function check_partition (line 1908) | fn check_partition() {
  function check_partition_map (line 1916) | fn check_partition_map() {
  function check_either (line 1930) | fn check_either() {
  function check_either_extend (line 1950) | fn check_either_extend() {
  function check_interleave_eq (line 1967) | fn check_interleave_eq() {
  function check_interleave_uneven (line 1985) | fn check_interleave_uneven() {
  function check_interleave_shortest (line 2040) | fn check_interleave_shortest() {
  function check_chunks_zero_size (line 2088) | fn check_chunks_zero_size() {
  function check_chunks_even_size (line 2093) | fn check_chunks_even_size() {
  function check_chunks_empty (line 2101) | fn check_chunks_empty() {
  function check_chunks_len (line 2111) | fn check_chunks_len() {
  function check_chunks_uneven (line 2120) | fn check_chunks_uneven() {
  function check_repeat_unbounded (line 2149) | fn check_repeat_unbounded() {
  function check_repeat_find_any (line 2159) | fn check_repeat_find_any() {
  function check_repeat_take (line 2165) | fn check_repeat_take() {
  function check_repeat_zip (line 2171) | fn check_repeat_zip() {
  function check_repeat_n_zip_left (line 2181) | fn check_repeat_n_zip_left() {
  function check_repeat_n_zip_right (line 2191) | fn check_repeat_n_zip_right() {
  function count_repeat_n_clones (line 2201) | fn count_repeat_n_clones() {
  function check_empty (line 2265) | fn check_empty() {
  function check_once (line 2280) | fn check_once() {
  function check_update (line 2295) | fn check_update() {
  function walk_tree_prefix (line 2303) | fn walk_tree_prefix() {
  function walk_tree_postfix (line 2318) | fn walk_tree_postfix() {
  function walk_flat_tree_prefix (line 2333) | fn walk_flat_tree_prefix() {
  function walk_flat_tree_postfix (line 2340) | fn walk_flat_tree_postfix() {
  function walk_tree_prefix_degree5 (line 2347) | fn walk_tree_prefix_degree5() {
  function walk_tree_postfix_degree5 (line 2363) | fn walk_tree_postfix_degree5() {
  function blocks (line 2379) | fn blocks() {

FILE: src/iter/try_fold.rs
  function new (line 10) | pub(super) fn new(base: I, identity: ID, fold_op: F) -> Self {
  type TryFold (line 26) | pub struct TryFold<I, U, ID, F> {
  method fmt (line 34) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 46) | type Item = U;
  method drive_unindexed (line 48) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type TryFoldConsumer (line 62) | struct TryFoldConsumer<'c, U, C, ID, F> {
  type Folder (line 76) | type Folder = TryFoldFolder<'r, C::Folder, U, F>;
  type Reducer (line 77) | type Reducer = C::Reducer;
  type Result (line 78) | type Result = C::Result;
  function split_at (line 80) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 92) | fn into_folder(self) -> Self::Folder {
  function full (line 100) | fn full(&self) -> bool {
  function split_off_left (line 112) | fn split_off_left(&self) -> Self {
  function to_reducer (line 119) | fn to_reducer(&self) -> Self::Reducer {
  type TryFoldFolder (line 124) | struct TryFoldFolder<'r, C, U: Try, F> {
  type Result (line 136) | type Result = C::Result;
  function consume (line 138) | fn consume(mut self, item: T) -> Self {
  function complete (line 146) | fn complete(self) -> C::Result {
  function full (line 154) | fn full(&self) -> bool {
  function new (line 165) | pub(super) fn new(base: I, item: U::Output, fold_op: F) -> Self {
  type TryFoldWith (line 180) | pub struct TryFoldWith<I, U: Try, F> {
  method fmt (line 191) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 205) | type Item = U;
  method drive_unindexed (line 207) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type TryFoldWithConsumer (line 220) | struct TryFoldWithConsumer<'c, C, U: Try, F> {
  type Folder (line 232) | type Folder = TryFoldFolder<'r, C::Folder, U, F>;
  type Reducer (line 233) | type Reducer = C::Reducer;
  type Result (line 234) | type Result = C::Result;
  function split_at (line 236) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 252) | fn into_folder(self) -> Self::Folder {
  function full (line 260) | fn full(&self) -> bool {
  function split_off_left (line 271) | fn split_off_left(&self) -> Self {
  function to_reducer (line 279) | fn to_reducer(&self) -> Self::Reducer {

FILE: src/iter/try_reduce.rs
  function try_reduce (line 8) | pub(super) fn try_reduce<PI, R, ID, T>(pi: PI, identity: ID, reduce_op: ...
  type TryReduceConsumer (line 24) | struct TryReduceConsumer<'r, R, ID> {
  method clone (line 33) | fn clone(&self) -> Self {
  type Folder (line 44) | type Folder = TryReduceFolder<'r, R, T>;
  type Reducer (line 45) | type Reducer = Self;
  type Result (line 46) | type Result = T;
  function split_at (line 48) | fn split_at(self, _index: usize) -> (Self, Self, Self) {
  function into_folder (line 52) | fn into_folder(self) -> Self::Folder {
  function full (line 60) | fn full(&self) -> bool {
  function split_off_left (line 71) | fn split_off_left(&self) -> Self {
  function to_reducer (line 75) | fn to_reducer(&self) -> Self::Reducer {
  function reduce (line 85) | fn reduce(self, left: T, right: T) -> T {
  type TryReduceFolder (line 93) | struct TryReduceFolder<'r, R, T: Try> {
  type Result (line 104) | type Result = T;
  function consume (line 106) | fn consume(mut self, item: T) -> Self {
  function complete (line 118) | fn complete(self) -> T {
  function full (line 125) | fn full(&self) -> bool {

FILE: src/iter/try_reduce_with.rs
  function try_reduce_with (line 8) | pub(super) fn try_reduce_with<PI, R, T>(pi: PI, reduce_op: R) -> Option<T>
  type TryReduceWithConsumer (line 22) | struct TryReduceWithConsumer<'r, R> {
  method clone (line 30) | fn clone(&self) -> Self {
  type Folder (line 40) | type Folder = TryReduceWithFolder<'r, R, T>;
  type Reducer (line 41) | type Reducer = Self;
  type Result (line 42) | type Result = Option<T>;
  function split_at (line 44) | fn split_at(self, _index: usize) -> (Self, Self, Self) {
  function into_folder (line 48) | fn into_folder(self) -> Self::Folder {
  function full (line 56) | fn full(&self) -> bool {
  function split_off_left (line 66) | fn split_off_left(&self) -> Self {
  function to_reducer (line 70) | fn to_reducer(&self) -> Self::Reducer {
  function reduce (line 80) | fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {
  type TryReduceWithFolder (line 92) | struct TryReduceWithFolder<'r, R, T: Try> {
  type Result (line 103) | type Result = Option<T>;
  function consume (line 105) | fn consume(mut self, item: T) -> Self {
  function complete (line 118) | fn complete(self) -> Option<T> {
  function full (line 126) | fn full(&self) -> bool {

FILE: src/iter/unzip.rs
  type UnzipOp (line 7) | trait UnzipOp<T>: Sync + Send {
    method consume (line 15) | fn consume<FA, FB>(&self, item: T, left: FA, right: FB) -> (FA, FB)
    method indexable (line 23) | fn indexable() -> bool {
  function execute (line 29) | fn execute<I, OP, FromA, FromB>(pi: I, op: OP) -> (FromA, FromB)
  function execute_into (line 43) | fn execute_into<I, OP, FromA, FromB>(a: &mut FromA, b: &mut FromB, pi: I...
  function unzip (line 61) | pub(super) fn unzip<I, A, B, FromA, FromB>(pi: I) -> (FromA, FromB)
  function unzip_indexed (line 75) | pub(super) fn unzip_indexed<I, A, B, CA, CB>(pi: I, left: CA, right: CB)...
  type Unzip (line 92) | struct Unzip;
    type Left (line 95) | type Left = A;
    type Right (line 96) | type Right = B;
    method consume (line 98) | fn consume<FA, FB>(&self, item: (A, B), left: FA, right: FB) -> (FA, FB)
    method indexable (line 106) | fn indexable() -> bool {
  function partition (line 115) | pub(super) fn partition<I, A, B, P>(pi: I, predicate: P) -> (A, B)
  type Partition (line 126) | struct Partition<P> {
  type Left (line 135) | type Left = T;
  type Right (line 136) | type Right = T;
  function consume (line 138) | fn consume<FA, FB>(&self, item: T, left: FA, right: FB) -> (FA, FB)
  function partition_map (line 155) | pub(super) fn partition_map<I, A, B, P, L, R>(pi: I, predicate: P) -> (A...
  type PartitionMap (line 168) | struct PartitionMap<P> {
  type Left (line 178) | type Left = L;
  type Right (line 179) | type Right = R;
  function consume (line 181) | fn consume<FA, FB>(&self, item: T, left: FA, right: FB) -> (FA, FB)
  type UnzipA (line 194) | struct UnzipA<'b, I, OP, FromB> {
  type Item (line 206) | type Item = OP::Left;
  method drive_unindexed (line 208) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 229) | fn opt_len(&self) -> Option<usize> {
  type UnzipB (line 239) | struct UnzipB<'r, I, OP, CA>
  type Item (line 257) | type Item = OP::Right;
  method drive_unindexed (line 259) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 275) | fn opt_len(&self) -> Option<usize> {
  type UnzipConsumer (line 285) | struct UnzipConsumer<'a, OP, CA, CB> {
  type Folder (line 297) | type Folder = UnzipFolder<'a, OP, CA::Folder, CB::Folder>;
  type Reducer (line 298) | type Reducer = UnzipReducer<CA::Reducer, CB::Reducer>;
  type Result (line 299) | type Result = (CA::Result, CB::Result);
  function split_at (line 301) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 323) | fn into_folder(self) -> Self::Folder {
  function full (line 331) | fn full(&self) -> bool {
  function split_off_left (line 343) | fn split_off_left(&self) -> Self {
  function to_reducer (line 351) | fn to_reducer(&self) -> Self::Reducer {
  type UnzipFolder (line 360) | struct UnzipFolder<'a, OP, FA, FB> {
  type Result (line 372) | type Result = (FA::Result, FB::Result);
  function consume (line 374) | fn consume(self, item: T) -> Self {
  function complete (line 383) | fn complete(self) -> Self::Result {
  function full (line 387) | fn full(&self) -> bool {
  type UnzipReducer (line 394) | struct UnzipReducer<RA, RB> {
  function reduce (line 404) | fn reduce(self, left: (A, B), right: (A, B)) -> (A, B) {
  function par_extend (line 419) | fn par_extend<I>(&mut self, pi: I)
  function par_extend (line 434) | fn par_extend<I>(&mut self, pi: I)
  type UnEither (line 443) | struct UnEither;
    type Left (line 450) | type Left = L;
    type Right (line 451) | type Right = R;
    method consume (line 453) | fn consume<FL, FR>(&self, item: Either<L, R>, left: FL, right: FR) -> ...
  function from_par_iter (line 472) | fn from_par_iter<I>(pi: I) -> Self
  function from_par_iter (line 488) | fn from_par_iter<I>(pi: I) -> Self
  type Collector (line 502) | struct Collector<FromT> {
  method default (line 507) | fn default() -> Self {
  function par_extend (line 517) | fn par_extend<I>(&mut self, pi: I)

FILE: src/iter/update.rs
  type Update (line 14) | pub struct Update<I, F> {
  method fmt (line 20) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function new (line 27) | pub(super) fn new(base: I, update_op: F) -> Self {
  type Item (line 37) | type Item = I::Item;
  method drive_unindexed (line 39) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 47) | fn opt_len(&self) -> Option<usize> {
  method drive (line 57) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 65) | fn len(&self) -> usize {
  method with_producer (line 69) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type UpdateProducer (line 106) | struct UpdateProducer<'f, P, F> {
  type Item (line 116) | type Item = P::Item;
  type IntoIter (line 117) | type IntoIter = UpdateSeq<P::IntoIter, &'f F>;
  method into_iter (line 119) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 126) | fn min_len(&self) -> usize {
  method max_len (line 129) | fn max_len(&self) -> usize {
  method split_at (line 133) | fn split_at(self, index: usize) -> (Self, Self) {
  method fold_with (line 147) | fn fold_with<G>(self, folder: G) -> G
  type UpdateConsumer (line 162) | struct UpdateConsumer<'f, C, F> {
  function new (line 168) | fn new(base: C, update_op: &'f F) -> Self {
  type Folder (line 178) | type Folder = UpdateFolder<'f, C::Folder, F>;
  type Reducer (line 179) | type Reducer = C::Reducer;
  type Result (line 180) | type Result = C::Result;
  function split_at (line 182) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 191) | fn into_folder(self) -> Self::Folder {
  function full (line 198) | fn full(&self) -> bool {
  function split_off_left (line 208) | fn split_off_left(&self) -> Self {
  function to_reducer (line 212) | fn to_reducer(&self) -> Self::Reducer {
  type UpdateFolder (line 217) | struct UpdateFolder<'f, C, F> {
  function apply (line 222) | fn apply<T>(update_op: impl Fn(&mut T)) -> impl Fn(T) -> T {
  type Result (line 234) | type Result = C::Result;
  function consume (line 236) | fn consume(self, mut item: T) -> Self {
  function consume_iter (line 245) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 256) | fn complete(self) -> C::Result {
  function full (line 260) | fn full(&self) -> bool {
  type UpdateSeq (line 268) | struct UpdateSeq<I, F> {
  type Item (line 278) | type Item = I::Item;
  method next (line 280) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 286) | fn size_hint(&self) -> (usize, Option<usize>) {
  method fold (line 290) | fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
  method collect (line 298) | fn collect<C>(self) -> C
  method next_back (line 318) | fn next_back(&mut self) -> Option<Self::Item> {

FILE: src/iter/walk_tree.rs
  type WalkTreePrefixProducer (line 6) | struct WalkTreePrefixProducer<'b, S, B> {
  type Item (line 18) | type Item = S;
  method split (line 20) | fn split(mut self) -> (Self, Option<Self>) {
  method fold_with (line 51) | fn fold_with<F>(mut self, mut folder: F) -> F
  type WalkTreePrefix (line 76) | pub struct WalkTreePrefix<S, B> {
  type Item (line 87) | type Item = S;
  method drive_unindexed (line 89) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  function walk_tree_prefix (line 204) | pub fn walk_tree_prefix<S, B, I>(root: S, children_of: B) -> WalkTreePre...
  type WalkTreePostfixProducer (line 219) | struct WalkTreePostfixProducer<'b, S, B> {
  type Item (line 231) | type Item = S;
  method split (line 233) | fn split(mut self) -> (Self, Option<Self>) {
  method fold_with (line 267) | fn fold_with<F>(self, mut folder: F) -> F
  function consume_rec_postfix (line 283) | fn consume_rec_postfix<F, S, B, I>(children_of: &B, s: S, mut folder: F)...
  type WalkTreePostfix (line 302) | pub struct WalkTreePostfix<S, B> {
  type Item (line 313) | type Item = S;
  method drive_unindexed (line 315) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  function split_vec (line 331) | fn split_vec<T>(v: &mut Vec<T>) -> Option<Vec<T>> {
  function walk_tree_postfix (line 444) | pub fn walk_tree_postfix<S, B, I>(root: S, children_of: B) -> WalkTreePo...
  type WalkTree (line 459) | pub struct WalkTree<S, B>(WalkTreePostfix<S, B>);
  function walk_tree (line 497) | pub fn walk_tree<S, B, I>(root: S, children_of: B) -> WalkTree<S, B>
  type Item (line 516) | type Item = S;
  method drive_unindexed (line 518) | fn drive_unindexed<C>(self, consumer: C) -> C::Result

FILE: src/iter/while_some.rs
  type WhileSome (line 13) | pub struct WhileSome<I> {
  function new (line 19) | pub(super) fn new(base: I) -> Self {
  type Item (line 29) | type Item = T;
  method drive_unindexed (line 31) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  type WhileSomeConsumer (line 47) | struct WhileSomeConsumer<'f, C> {
  type Folder (line 57) | type Folder = WhileSomeFolder<'f, C::Folder>;
  type Reducer (line 58) | type Reducer = C::Reducer;
  type Result (line 59) | type Result = C::Result;
  function split_at (line 61) | fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  function into_folder (line 73) | fn into_folder(self) -> Self::Folder {
  function full (line 80) | fn full(&self) -> bool {
  function split_off_left (line 90) | fn split_off_left(&self) -> Self {
  function to_reducer (line 97) | fn to_reducer(&self) -> Self::Reducer {
  type WhileSomeFolder (line 102) | struct WhileSomeFolder<'f, C> {
  type Result (line 111) | type Result = C::Result;
  function consume (line 113) | fn consume(mut self, item: Option<T>) -> Self {
  function consume_iter (line 121) | fn consume_iter<I>(mut self, iter: I) -> Self
  function complete (line 143) | fn complete(self) -> C::Result {
  function full (line 147) | fn full(&self) -> bool {

FILE: src/iter/zip.rs
  type Zip (line 12) | pub struct Zip<A, B> {
  function new (line 19) | pub(super) fn new(a: A, b: B) -> Self {
  type Item (line 29) | type Item = (A::Item, B::Item);
  method drive_unindexed (line 31) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 38) | fn opt_len(&self) -> Option<usize> {
  method drive (line 48) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 55) | fn len(&self) -> usize {
  method with_producer (line 59) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type ZipProducer (line 118) | struct ZipProducer<A: Producer, B: Producer> {
  type Item (line 124) | type Item = (A::Item, B::Item);
  type IntoIter (line 125) | type IntoIter = iter::Zip<A::IntoIter, B::IntoIter>;
  method into_iter (line 127) | fn into_iter(self) -> Self::IntoIter {
  method min_len (line 131) | fn min_len(&self) -> usize {
  method max_len (line 135) | fn max_len(&self) -> usize {
  method split_at (line 139) | fn split_at(self, index: usize) -> (Self, Self) {

FILE: src/iter/zip_eq.rs
  type ZipEq (line 13) | pub struct ZipEq<A, B> {
  function new (line 19) | pub(super) fn new(a: A, b: B) -> Self {
  type Item (line 31) | type Item = (A::Item, B::Item);
  method drive_unindexed (line 33) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 40) | fn opt_len(&self) -> Option<usize> {
  method drive (line 50) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 57) | fn len(&self) -> usize {
  method with_producer (line 61) | fn with_producer<CB>(self, callback: CB) -> CB::Output

FILE: src/lib.rs
  type SendPtr (line 133) | struct SendPtr<T>(*mut T);
  function get (line 143) | fn get(self) -> *mut T {
  method clone (line 150) | fn clone(&self) -> Self {

FILE: src/math.rs
  function simplify_range (line 4) | pub(super) fn simplify_range(range: impl RangeBounds<usize>, len: usize)...

FILE: src/option.rs
  type IntoIter (line 20) | pub struct IntoIter<T> {
  type Item (line 25) | type Item = T;
  type Iter (line 26) | type Iter = IntoIter<T>;
  method into_par_iter (line 28) | fn into_par_iter(self) -> Self::Iter {
  type Item (line 34) | type Item = T;
  method drive_unindexed (line 36) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 43) | fn opt_len(&self) -> Option<usize> {
  method drive (line 49) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 60) | fn len(&self) -> usize {
  method with_producer (line 67) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type Iter (line 83) | pub struct Iter<'a, T> {
  method clone (line 88) | fn clone(&self) -> Self {
  type Item (line 96) | type Item = &'a T;
  type Iter (line 97) | type Iter = Iter<'a, T>;
  method into_par_iter (line 99) | fn into_par_iter(self) -> Self::Iter {
  type IterMut (line 119) | pub struct IterMut<'a, T> {
  type Item (line 124) | type Item = &'a mut T;
  type Iter (line 125) | type Iter = IterMut<'a, T>;
  method into_par_iter (line 127) | fn into_par_iter(self) -> Self::Iter {
  type OptionProducer (line 140) | struct OptionProducer<T: Send> {
  type Item (line 145) | type Item = T;
  type IntoIter (line 146) | type IntoIter = std::option::IntoIter<T>;
  method into_iter (line 148) | fn into_iter(self) -> Self::IntoIter {
  method split_at (line 152) | fn split_at(self, index: usize) -> (Self, Self) {
  function from_par_iter (line 172) | fn from_par_iter<I>(par_iter: I) -> Self

FILE: src/par_either.rs
  type Item (line 11) | type Item = L::Item;
  method drive_unindexed (line 13) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 23) | fn opt_len(&self) -> Option<usize> {
  method drive (line 33) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 43) | fn len(&self) -> usize {
  method with_producer (line 47) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  function par_extend (line 65) | fn par_extend<I>(&mut self, par_iter: I)

FILE: src/private.rs
  type PrivateMarker (line 9) | pub struct PrivateMarker;

FILE: src/range.rs
  type Iter (line 45) | pub struct Iter<T> {
  type Item (line 54) | type Item = <Iter<T> as ParallelIterator>::Item;
  type Iter (line 55) | type Iter = Iter<T>;
  method into_par_iter (line 57) | fn into_par_iter(self) -> Self::Iter {
  type IterProducer (line 62) | struct IterProducer<T> {
  type Item (line 70) | type Item = <Range<T> as Iterator>::Item;
  type IntoIter (line 71) | type IntoIter = Range<T>;
  method into_iter (line 73) | fn into_iter(self) -> Self::IntoIter {
  type RangeInteger (line 89) | pub trait RangeInteger: Sized + Send {
    method drive_unindexed (line 92) | fn drive_unindexed<C>(iter: Iter<Self>, consumer: C) -> C::Result
    method opt_len (line 96) | fn opt_len(iter: &Iter<Self>) -> Option<usize>;
  type IndexedRangeInteger (line 100) | pub trait IndexedRangeInteger: RangeInteger {
    method drive (line 103) | fn drive<C>(iter: Iter<Self>, consumer: C) -> C::Result
    method len (line 107) | fn len(iter: &Iter<Self>) -> usize;
    method with_producer (line 109) | fn with_producer<CB>(iter: Iter<Self>, callback: CB) -> CB::Output
  type Item (line 117) | type Item = T;
  method drive_unindexed (line 119) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 127) | fn opt_len(&self) -> Option<usize> {
  method drive (line 133) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 141) | fn len(&self) -> usize {
  method with_producer (line 145) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type UnindexedRangeLen (line 212) | trait UnindexedRangeLen<L> {
    method unindexed_len (line 213) | fn unindexed_len(&self) -> L;
  type Item (line 321) | type Item = char;
  method drive_unindexed (line 323) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 330) | fn opt_len(&self) -> Option<usize> {
  method drive (line 337) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 344) | fn len(&self) -> usize {
  method with_producer (line 359) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  function check_range_split_at_overflow (line 368) | fn check_range_split_at_overflow() {
  function test_i128_len_doesnt_overflow (line 378) | fn test_i128_len_doesnt_overflow() {
  function test_u64_opt_len (line 396) | fn test_u64_opt_len() {
  function test_u128_opt_len (line 414) | fn test_u128_opt_len() {
  function test_usize_i64_overflow (line 428) | fn test_usize_i64_overflow() {
  function test_issue_833 (line 440) | fn test_issue_833() {

FILE: src/range_inclusive.rs
  type Iter (line 45) | pub struct Iter<T> {
  function bounds (line 59) | fn bounds(&self) -> Option<(T, T)> {
  type Item (line 78) | type Item = <Iter<T> as ParallelIterator>::Item;
  type Iter (line 79) | type Iter = Iter<T>;
  method into_par_iter (line 81) | fn into_par_iter(self) -> Self::Iter {
  type RangeInteger (line 97) | pub trait RangeInteger: Sized + Send {
    method drive_unindexed (line 100) | fn drive_unindexed<C>(iter: Iter<Self>, consumer: C) -> C::Result
    method opt_len (line 104) | fn opt_len(iter: &Iter<Self>) -> Option<usize>;
  type IndexedRangeInteger (line 108) | pub trait IndexedRangeInteger: RangeInteger {
    method drive (line 111) | fn drive<C>(iter: Iter<Self>, consumer: C) -> C::Result
    method len (line 115) | fn len(iter: &Iter<Self>) -> usize;
    method with_producer (line 117) | fn with_producer<CB>(iter: Iter<Self>, callback: CB) -> CB::Output
  type Item (line 125) | type Item = T;
  method drive_unindexed (line 127) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 135) | fn opt_len(&self) -> Option<usize> {
  method drive (line 141) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 149) | fn len(&self) -> usize {
  method with_producer (line 153) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  type Item (line 265) | type Item = char;
  method drive_unindexed (line 267) | fn drive_unindexed<C>(self, consumer: C) -> C::Result
  method opt_len (line 274) | fn opt_len(&self) -> Option<usize> {
  method drive (line 282) | fn drive<C>(self, consumer: C) -> C::Result
  method len (line 289) | fn len(&self) -> usize {
  method with_producer (line 304) | fn with_producer<CB>(self, callback: CB) -> CB::Output
  function test_u32_opt_len (line 314) | fn test_u32_opt_len() {
  function test_u64_opt_len (line 327) | fn test_u64_opt_len() {
  function test_u128_opt_len (line 338) | fn test_u128_opt_len() {
  function test_usize_i64_overflow (line 352) | fn test_usize_i64_overflow() {
  function test_issue_833 (line 364) | fn test_issue_833() {

FILE: src/result.rs
  type IntoIter (line 16) | pub struct IntoIter<T> {
  type Item (line 21) | type Item = T;
  type Iter (line 22) | type Iter = IntoIter<T>;
  method into_par_iter (line 24) | fn into_par_iter(self) -> Self::Iter {
  type Iter (line 38) | pub struct Iter<'a, T> {
  method clone (line 43) | fn clone(&self) -> Self {
  type Item (line 51) | type Item = &'a T;
  type Iter (line 52) | type Iter = Iter<'a, T>;
  method into_par_iter (line 54) | fn into_par_iter(self) -> Self::Iter {
  type IterMut (line 68) | pub struct IterMut<'a, T> {
  type Item (line 73) | type Item = &'a mut T;
  type Iter (line 74) | type Iter = IterMut<'a, T>;
  method into_par_iter (line 76) | fn into_par_iter(self) -> Self::Iter {
  function from_par_iter (line 99) | fn from_par_iter<I>(par_iter: I) -> Self

FILE: src/slice/chunk_by.rs
  type ChunkBySlice (line 6) | trait ChunkBySlice<T>: AsRef<[T]> + Default + Send {
    method split (line 7) | fn split(self, index: usize) -> (Self, Self);
    method chunk_by (line 8) | fn chunk_by(self, pred: &impl Fn(&T, &T) -> bool) -> impl Iterator<Ite...
    method find (line 10) | fn find(&self, pred: &impl Fn(&T, &T) -> bool, start: usize, end: usiz...
    method rfind (line 17) | fn rfind(&self, pred: &impl Fn(&T, &T) -> bool, end: usize) -> Option<...
  function split (line 26) | fn split(self, index: usize) -> (Self, Self) {
  function chunk_by (line 30) | fn chunk_by(self, pred: &impl Fn(&T, &T) -> bool) -> impl Iterator<Item ...
  function split (line 36) | fn split(self, index: usize) 
Condensed preview — 218 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,399K chars).
[
  {
    "path": ".github/dependabot.yml",
    "chars": 254,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: cargo\n    directory: /\n    schedule:\n      interval: monthly\n    open-pull-re"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "chars": 4270,
    "preview": "name: CI\non: merge_group\n\njobs:\n\n  check:\n    name: Check (1.80.0)\n    runs-on: ubuntu-latest\n    steps:\n      - uses: a"
  },
  {
    "path": ".github/workflows/main.yaml",
    "chars": 523,
    "preview": "name: main\non:\n  push:\n    branches:\n      - main\n  schedule:\n    - cron: '0 0 * * 0' # 00:00 Sunday\n\njobs:\n\n  test:\n   "
  },
  {
    "path": ".github/workflows/pr.yaml",
    "chars": 1655,
    "preview": "name: PR\non: pull_request\n\n# Using 16MB stacks for deep test/debug recursion\nenv:\n  RUST_MIN_STACK: 16777216\n\njobs:\n\n  c"
  },
  {
    "path": ".gitignore",
    "chars": 36,
    "preview": "Cargo.lock\ntarget\n*~\nTAGS\n*.bk\n.idea"
  },
  {
    "path": "Cargo.toml",
    "chars": 1512,
    "preview": "[package]\nname = \"rayon\"\nversion = \"1.11.0\"\ndescription = \"Simple work-stealing parallelism for Rust\"\ndocumentation = \"h"
  },
  {
    "path": "FAQ.md",
    "chars": 9247,
    "preview": "# Rayon FAQ\n\nThis file is for general questions that don't fit into the README or crate docs.\n\n## How many threads will "
  },
  {
    "path": "LICENSE-APACHE",
    "chars": 10847,
    "preview": "                              Apache License\n                        Version 2.0, January 2004\n                     http"
  },
  {
    "path": "LICENSE-MIT",
    "chars": 1071,
    "preview": "Copyright (c) 2010 The Rust Project Developers\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a "
  },
  {
    "path": "README.md",
    "chars": 5732,
    "preview": "# Rayon\n\n[![Rayon crate](https://img.shields.io/crates/v/rayon.svg)](https://crates.io/crates/rayon)\n[![Rayon documentat"
  },
  {
    "path": "RELEASES.md",
    "chars": 36893,
    "preview": "# Release rayon 1.11.0 / rayon-core 1.13.0 (2025-08-12)\n\n- The minimum supported `rustc` is now 1.80.\n- `iter::repeatn` "
  },
  {
    "path": "ci/alt-core/Cargo.toml",
    "chars": 180,
    "preview": "[package]\nedition = \"2018\"\nname = \"alt-core\"\nversion = \"0.0.0\"\nauthors = [\"Josh Stone <cuviper@gmail.com>\"]\nlinks = \"ray"
  },
  {
    "path": "ci/alt-core/build.rs",
    "chars": 13,
    "preview": "fn main() {}\n"
  },
  {
    "path": "ci/alt-core/src/lib.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "ci/highlander/Cargo.toml",
    "chars": 313,
    "preview": "[package]\nauthors = [\"Josh Stone <cuviper@gmail.com>\"]\nedition = \"2018\"\nname = \"highlander\"\ndescription = \"There Can Be "
  },
  {
    "path": "ci/highlander/src/main.rs",
    "chars": 13,
    "preview": "fn main() {}\n"
  },
  {
    "path": "ci/highlander.sh",
    "chars": 300,
    "preview": "#!/bin/bash\n\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\necho \"INFO: There Can Be Only One!\" >&2\n\nif cargo "
  },
  {
    "path": "rayon-core/Cargo.toml",
    "chars": 878,
    "preview": "[package]\nname = \"rayon-core\"\nversion = \"1.13.0\"\ndescription = \"Core APIs for Rayon\"\ndocumentation = \"https://docs.rs/ra"
  },
  {
    "path": "rayon-core/LICENSE-APACHE",
    "chars": 10847,
    "preview": "                              Apache License\n                        Version 2.0, January 2004\n                     http"
  },
  {
    "path": "rayon-core/LICENSE-MIT",
    "chars": 1071,
    "preview": "Copyright (c) 2010 The Rust Project Developers\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a "
  },
  {
    "path": "rayon-core/README.md",
    "chars": 781,
    "preview": "Rayon-core represents the \"core, stable\" APIs of Rayon: join, scope, and so forth, as well as the ability to create cust"
  },
  {
    "path": "rayon-core/build.rs",
    "chars": 278,
    "preview": "// We need a build script to use `link = \"rayon-core\"`.  But we're not\n// *actually* linking to anything, just making su"
  },
  {
    "path": "rayon-core/src/broadcast/mod.rs",
    "chars": 5385,
    "preview": "use crate::job::{ArcJob, StackJob};\nuse crate::latch::{CountLatch, LatchRef};\nuse crate::registry::{Registry, WorkerThre"
  },
  {
    "path": "rayon-core/src/broadcast/test.rs",
    "chars": 8487,
    "preview": "#![cfg(test)]\n\nuse crate::ThreadPoolBuilder;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::mpsc::channe"
  },
  {
    "path": "rayon-core/src/compile_fail/mod.rs",
    "chars": 163,
    "preview": "// These modules contain `compile_fail` doc tests.\nmod quicksort_race1;\nmod quicksort_race2;\nmod quicksort_race3;\nmod rc"
  },
  {
    "path": "rayon-core/src/compile_fail/quicksort_race1.rs",
    "chars": 535,
    "preview": "/*! ```compile_fail,E0524\n\nfn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n"
  },
  {
    "path": "rayon-core/src/compile_fail/quicksort_race2.rs",
    "chars": 534,
    "preview": "/*! ```compile_fail,E0500\n\nfn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n"
  },
  {
    "path": "rayon-core/src/compile_fail/quicksort_race3.rs",
    "chars": 535,
    "preview": "/*! ```compile_fail,E0524\n\nfn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {\n    if v.len() <= 1 {\n        return;\n    }\n\n"
  },
  {
    "path": "rayon-core/src/compile_fail/rc_return.rs",
    "chars": 234,
    "preview": "/** ```compile_fail,E0277\n\nuse std::rc::Rc;\n\nrayon_core::join(|| Rc::new(22), || ()); //~ ERROR\n\n``` */\nmod left {}\n\n/**"
  },
  {
    "path": "rayon-core/src/compile_fail/rc_upvar.rs",
    "chars": 131,
    "preview": "/*! ```compile_fail,E0277\n\nuse std::rc::Rc;\n\nlet r = Rc::new(22);\nrayon_core::join(|| r.clone(), || r.clone());\n//~^ ERR"
  },
  {
    "path": "rayon-core/src/compile_fail/scope_join_bad.rs",
    "chars": 376,
    "preview": "/*! ```compile_fail,E0373\n\nfn bad_scope<F>(f: F)\n    where F: FnOnce(&i32) + Send,\n{\n    rayon_core::scope(|s| {\n       "
  },
  {
    "path": "rayon-core/src/job.rs",
    "chars": 7571,
    "preview": "use crate::latch::Latch;\nuse crate::unwind;\nuse crossbeam_deque::{Injector, Steal};\nuse std::any::Any;\nuse std::cell::Un"
  },
  {
    "path": "rayon-core/src/join/mod.rs",
    "chars": 6899,
    "preview": "use crate::job::StackJob;\nuse crate::latch::SpinLatch;\nuse crate::registry::{self, WorkerThread};\nuse crate::unwind;\nuse"
  },
  {
    "path": "rayon-core/src/join/test.rs",
    "chars": 4195,
    "preview": "//! Tests for the join code.\n\nuse super::*;\nuse crate::ThreadPoolBuilder;\nuse rand::distr::StandardUniform;\nuse rand::{R"
  },
  {
    "path": "rayon-core/src/latch.rs",
    "chars": 15054,
    "preview": "use std::marker::PhantomData;\nuse std::ops::Deref;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::Arc;\n\n"
  },
  {
    "path": "rayon-core/src/lib.rs",
    "chars": 32356,
    "preview": "//! Rayon-core houses the core stable APIs of Rayon.\n//!\n//! These APIs have been mirrored in the Rayon crate and it is "
  },
  {
    "path": "rayon-core/src/private.rs",
    "chars": 886,
    "preview": "//! The public parts of this private module are used to create traits\n//! that cannot be implemented outside of our own "
  },
  {
    "path": "rayon-core/src/registry.rs",
    "chars": 34919,
    "preview": "use crate::job::{JobFifo, JobRef, StackJob};\nuse crate::latch::{AsCoreLatch, CoreLatch, Latch, LatchRef, LockLatch, Once"
  },
  {
    "path": "rayon-core/src/scope/mod.rs",
    "chars": 29571,
    "preview": "//! Methods for custom fork-join scopes, created by the [`scope()`]\n//! and [`in_place_scope()`] functions. These are a "
  },
  {
    "path": "rayon-core/src/scope/test.rs",
    "chars": 19092,
    "preview": "use crate::unwind;\nuse crate::ThreadPoolBuilder;\nuse crate::{scope, scope_fifo, Scope, ScopeFifo};\nuse rand::{Rng, Seeda"
  },
  {
    "path": "rayon-core/src/sleep/README.md",
    "chars": 10950,
    "preview": "# Introduction: the sleep module\n\nThe code in this module governs when worker threads should go to\nsleep. The system use"
  },
  {
    "path": "rayon-core/src/sleep/counters.rs",
    "chars": 9580,
    "preview": "use std::sync::atomic::{AtomicUsize, Ordering};\n\npub(super) struct AtomicCounters {\n    /// Packs together a number of c"
  },
  {
    "path": "rayon-core/src/sleep/mod.rs",
    "chars": 11973,
    "preview": "//! Code that decides when workers should go to sleep. See README.md\n//! for an overview.\n\nuse crate::latch::CoreLatch;\n"
  },
  {
    "path": "rayon-core/src/spawn/mod.rs",
    "chars": 6267,
    "preview": "use crate::job::*;\nuse crate::registry::Registry;\nuse crate::unwind;\nuse std::mem;\nuse std::sync::Arc;\n\n/// Puts the tas"
  },
  {
    "path": "rayon-core/src/spawn/test.rs",
    "chars": 8014,
    "preview": "use crate::scope;\nuse std::any::Any;\nuse std::sync::mpsc::channel;\nuse std::sync::Mutex;\n\nuse super::{spawn, spawn_fifo}"
  },
  {
    "path": "rayon-core/src/test.rs",
    "chars": 6347,
    "preview": "#![cfg(test)]\n\nuse crate::{ThreadPoolBuildError, ThreadPoolBuilder};\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse"
  },
  {
    "path": "rayon-core/src/thread_pool/mod.rs",
    "chars": 18720,
    "preview": "//! Contains support for user-managed thread pools, represented by the\n//! the [`ThreadPool`] type (see that struct for "
  },
  {
    "path": "rayon-core/src/thread_pool/test.rs",
    "chars": 13447,
    "preview": "#![cfg(test)]\n\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::mpsc::channel;\nuse std::sync::{Arc, Mutex}"
  },
  {
    "path": "rayon-core/src/unwind.rs",
    "chars": 939,
    "preview": "//! Package up unwind recovery. Note that if you are in some sensitive\n//! place, you can use the `AbortIfPanic` helper "
  },
  {
    "path": "rayon-core/tests/double_init_fail.rs",
    "chars": 474,
    "preview": "use rayon_core::ThreadPoolBuilder;\nuse std::error::Error;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_famil"
  },
  {
    "path": "rayon-core/tests/init_zero_threads.rs",
    "chars": 242,
    "preview": "use rayon_core::ThreadPoolBuilder;\n\n#[test]\n#[cfg_attr(any(target_os = \"emscripten\", target_family = \"wasm\"), ignore)]\nf"
  },
  {
    "path": "rayon-core/tests/scope_join.rs",
    "chars": 917,
    "preview": "/// Test that one can emulate join with `scope`:\nfn pseudo_join<F, G>(f: F, g: G)\nwhere\n    F: FnOnce() + Send,\n    G: F"
  },
  {
    "path": "rayon-core/tests/scoped_threadpool.rs",
    "chars": 3380,
    "preview": "use crossbeam_utils::thread;\nuse rayon_core::ThreadPoolBuilder;\n\n#[derive(PartialEq, Eq, Debug)]\nstruct Local(i32);\n\nsco"
  },
  {
    "path": "rayon-core/tests/simple_panic.rs",
    "chars": 140,
    "preview": "use rayon_core::join;\n\n#[test]\n#[should_panic(expected = \"should panic\")]\nfn simple_panic() {\n    join(|| {}, || panic!("
  },
  {
    "path": "rayon-core/tests/stack_overflow_crash.rs",
    "chars": 2234,
    "preview": "use rayon_core::ThreadPoolBuilder;\n\nuse std::env;\nuse std::process::{Command, ExitStatus, Stdio};\n\n#[cfg(target_os = \"li"
  },
  {
    "path": "rayon-core/tests/use_current_thread.rs",
    "chars": 1878,
    "preview": "use rayon_core::ThreadPoolBuilder;\nuse std::sync::{Arc, Condvar, Mutex};\nuse std::thread::{self, JoinHandle};\n\n#[test]\n#"
  },
  {
    "path": "rayon-demo/Cargo.toml",
    "chars": 560,
    "preview": "[package]\nname = \"rayon-demo\"\npublish = false\n\nedition.workspace = true\nrust-version.workspace = true\n\n[dependencies]\nra"
  },
  {
    "path": "rayon-demo/data/README.md",
    "chars": 80,
    "preview": "Data for various benchmarks. All in public domain or otherwise freely\nlicensed.\n"
  },
  {
    "path": "rayon-demo/data/tsp/README.md",
    "chars": 231,
    "preview": "Inputs for the Traveling Salesman Problem solver. These are in TSPLIB\nformat.\n\nSources:\n\n- `dj10.tsp`: derived from `dj3"
  },
  {
    "path": "rayon-demo/data/tsp/dj10.tsp",
    "chars": 417,
    "preview": "NAME: dj10\nCOMMENT : 10 locations in Djibouti; chosen from dj38.tsp\nTYPE: TSP\nDIMENSION: 10\nEDGE_WEIGHT_TYPE: EUC_2D\nNOD"
  },
  {
    "path": "rayon-demo/data/tsp/dj15.tsp",
    "chars": 562,
    "preview": "NAME: dj15\nCOMMENT : 15 locations in Djibouti; chosen from dj38.tsp\nTYPE: TSP\nDIMENSION: 15\nEDGE_WEIGHT_TYPE: EUC_2D\nNOD"
  },
  {
    "path": "rayon-demo/data/tsp/dj38.tsp",
    "chars": 1465,
    "preview": "NAME: dj38\nCOMMENT : 38 locations in Djibouti\nCOMMENT : Derived from National Imagery and Mapping Agency data\nCOMMENT : "
  },
  {
    "path": "rayon-demo/examples/README.md",
    "chars": 154,
    "preview": "We use this directory for interactive tests that can't be run in an\nautomatic fashion. For examples of how to use Rayon,"
  },
  {
    "path": "rayon-demo/examples/cpu_monitor.rs",
    "chars": 2168,
    "preview": "use docopt::Docopt;\nuse std::io;\nuse std::process;\n\nconst USAGE: &str = \"\nUsage: cpu_monitor [options] <scenario>\n      "
  },
  {
    "path": "rayon-demo/src/cpu_time/mod.rs",
    "chars": 1280,
    "preview": "use std::time::{Duration, Instant};\n\n#[cfg(windows)]\nmod win;\n#[cfg(windows)]\npub use self::win::get_cpu_time;\n\n#[cfg(un"
  },
  {
    "path": "rayon-demo/src/cpu_time/unix.rs",
    "chars": 560,
    "preview": "use libc::{getrusage, RUSAGE_SELF};\nuse std::mem::MaybeUninit;\n\npub fn get_cpu_time() -> Option<u64> {\n    let usage = u"
  },
  {
    "path": "rayon-demo/src/cpu_time/win.rs",
    "chars": 906,
    "preview": "use std::mem::MaybeUninit;\nuse winapi::um::processthreadsapi::{GetCurrentProcess, GetProcessTimes};\n\npub fn get_cpu_time"
  },
  {
    "path": "rayon-demo/src/factorial/mod.rs",
    "chars": 2605,
    "preview": "//! Benchmark Factorial N! = 1×2×⋯×N\n\nuse num::{BigUint, One};\nuse rayon::prelude::*;\nuse std::ops::Mul;\n\nconst N: u32 ="
  },
  {
    "path": "rayon-demo/src/fibonacci/mod.rs",
    "chars": 3277,
    "preview": "//! Benchmark Fibonacci numbers, F(n) = F(n-1) + F(n-2)\n//!\n//! Recursion is a horrible way to compute this -- roughly O"
  },
  {
    "path": "rayon-demo/src/find/mod.rs",
    "chars": 10196,
    "preview": "//! Simple benchmarks of `find_any()` and `find_first` performance\n\nmacro_rules! make_tests {\n    ($n:expr, $m:ident) =>"
  },
  {
    "path": "rayon-demo/src/join_microbench.rs",
    "chars": 1592,
    "preview": "//! Some microbenchmarks that stress test a pure `join` path.\n\nuse rayon::prelude::*;\nuse test::Bencher;\n\n#[bench]\nfn in"
  },
  {
    "path": "rayon-demo/src/lib.rs",
    "chars": 121,
    "preview": "// Make sure the examples in the main README actually compile.\n#[cfg(doctest)]\ndoc_comment::doctest!(\"../../README.md\");"
  },
  {
    "path": "rayon-demo/src/life/bench.rs",
    "chars": 433,
    "preview": "use super::Board;\n\n#[bench]\nfn generations(b: &mut ::test::Bencher) {\n    b.iter(|| super::generations(Board::new(200, 2"
  },
  {
    "path": "rayon-demo/src/life/mod.rs",
    "chars": 8496,
    "preview": "const USAGE: &str = \"\nUsage: life bench [--size N] [--gens N] [--skip-bridge]\n       life play [--size N] [--gens N] [--"
  },
  {
    "path": "rayon-demo/src/main.rs",
    "chars": 2428,
    "preview": "#![cfg_attr(test, feature(test))]\n#![warn(rust_2018_idioms)]\n\nuse std::{env, io, io::prelude::*, process::exit};\n\nmod cp"
  },
  {
    "path": "rayon-demo/src/map_collect.rs",
    "chars": 9723,
    "preview": "//! Some benchmarks stress-testing various ways to build the standard\n//! `HashMap` data structures from the standard li"
  },
  {
    "path": "rayon-demo/src/matmul/bench.rs",
    "chars": 282,
    "preview": "const ROW_SIZE: usize = 256;\n\n#[bench]\nfn bench_matmul_strassen(b: &mut test::Bencher) {\n    let n = ROW_SIZE * ROW_SIZE"
  },
  {
    "path": "rayon-demo/src/matmul/mod.rs",
    "chars": 12283,
    "preview": "const USAGE: &str = \"\nUsage: matmul bench [--size N]\n       matmul --help\nParallel matrix multiplication.\n\nCommands:\n   "
  },
  {
    "path": "rayon-demo/src/mergesort/bench.rs",
    "chars": 669,
    "preview": "// Size to use when doing `cargo bench`; extensively tuned to run in\n// \"not too long\" on my laptop -nmatsakis\nconst BEN"
  },
  {
    "path": "rayon-demo/src/mergesort/mod.rs",
    "chars": 7848,
    "preview": "use rand::distr::StandardUniform;\nuse rand::Rng;\n\nconst USAGE: &str = \"\nUsage: mergesort bench [--size N]\n       mergeso"
  },
  {
    "path": "rayon-demo/src/nbody/bench.rs",
    "chars": 953,
    "preview": "use super::nbody::NBodyBenchmark;\n\n// Because benchmarks run iteratively, use smaller constants by default:\nconst BENCH_"
  },
  {
    "path": "rayon-demo/src/nbody/mod.rs",
    "chars": 3997,
    "preview": "use docopt::Docopt;\nuse std::time::Instant;\n\n#[cfg(test)]\nmod bench;\n#[allow(clippy::module_inception)]\nmod nbody;\nmod v"
  },
  {
    "path": "rayon-demo/src/nbody/nbody.rs",
    "chars": 14684,
    "preview": "// Rust source (c) 2016 by the Rayon developers. This is ported from\n// [JavaScript sources][1] developed by Intel as pa"
  },
  {
    "path": "rayon-demo/src/nbody/visualize.rs",
    "chars": 7602,
    "preview": "use cgmath::{Angle, EuclideanSpace, Matrix4, Point3, Rad, Vector3};\nuse glium::backend::glutin::{Display, SimpleWindowBu"
  },
  {
    "path": "rayon-demo/src/noop/mod.rs",
    "chars": 932,
    "preview": "const USAGE: &str = \"\nUsage: noop [--sleep N] [--iters N]\n\nNoop loop to measure CPU usage. See rayon-rs/rayon#642.\n\nOpti"
  },
  {
    "path": "rayon-demo/src/pythagoras/mod.rs",
    "chars": 2997,
    "preview": "//! How many Pythagorean triples exist less than or equal to a million?\n//! i.e. a²+b²=c² and a,b,c ≤ 1000000\n\nuse num::"
  },
  {
    "path": "rayon-demo/src/quicksort/bench.rs",
    "chars": 1284,
    "preview": "use super::{Parallel, Sequential};\n\n// Size to use when doing `cargo bench`; extensively tuned to run in\n// \"not too lon"
  },
  {
    "path": "rayon-demo/src/quicksort/mod.rs",
    "chars": 3542,
    "preview": "#![allow(non_camel_case_types)]\n\nconst USAGE: &str = \"\nUsage: quicksort bench [options]\n       quicksort --help\n\nParalle"
  },
  {
    "path": "rayon-demo/src/sieve/bench.rs",
    "chars": 653,
    "preview": "use super::NUM_PRIMES;\n\nconst MAGNITUDE: usize = 7;\n\nfn sieve_bench<TICK>(b: &mut test::Bencher, mut tick: TICK)\nwhere\n "
  },
  {
    "path": "rayon-demo/src/sieve/mod.rs",
    "chars": 5754,
    "preview": "const USAGE: &str = \"\nUsage: sieve bench\n       sieve --help\n\nSieve of Eratosthenes\n\nA sieve finds prime numbers by firs"
  },
  {
    "path": "rayon-demo/src/sort.rs",
    "chars": 7255,
    "preview": "use rand::distr::{Alphanumeric, StandardUniform, Uniform};\nuse rand::Rng;\nuse rayon::prelude::*;\nuse std::sync::atomic::"
  },
  {
    "path": "rayon-demo/src/str_split.rs",
    "chars": 1926,
    "preview": "//! Some microbenchmarks for splitting strings\n\nuse rand::seq::SliceRandom;\nuse rayon::prelude::*;\nuse std::sync::LazyLo"
  },
  {
    "path": "rayon-demo/src/tree.rs",
    "chars": 2441,
    "preview": "//! Some benches for tree walks.\nuse rayon::prelude::*;\n\nconst SIZE: u64 = 100_000;\nconst VAL: u64 = SIZE * (SIZE - 1) /"
  },
  {
    "path": "rayon-demo/src/tsp/bench.rs",
    "chars": 1463,
    "preview": "use std::path::Path;\n\nuse super::graph::Node;\nuse super::parse_solver;\nuse super::solver::SolverCx;\n\nfn run_dir(\n    b: "
  },
  {
    "path": "rayon-demo/src/tsp/graph.rs",
    "chars": 2570,
    "preview": "use fixedbitset::FixedBitSet;\nuse std::iter;\n\nuse super::weight::Weight;\n\npub struct Graph {\n    num_nodes: usize,\n\n    "
  },
  {
    "path": "rayon-demo/src/tsp/mod.rs",
    "chars": 3082,
    "preview": "//! A solver for the Travelling Salesman Problem.\n//!\n//! Based on code developed at ETH by Christoph von Praun, Florian"
  },
  {
    "path": "rayon-demo/src/tsp/parser.rs",
    "chars": 7047,
    "preview": "use regex::Regex;\nuse std::collections::HashMap;\nuse std::str::{FromStr, Lines};\nuse std::sync::LazyLock;\n\nuse super::gr"
  },
  {
    "path": "rayon-demo/src/tsp/solver.rs",
    "chars": 3324,
    "preview": "use std::collections::BinaryHeap;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::{Arc, Mutex};\n\nuse supe"
  },
  {
    "path": "rayon-demo/src/tsp/step.rs",
    "chars": 6233,
    "preview": "use rayon::Scope;\nuse std::sync::Arc;\n\nuse super::graph::{Graph, Node, NodeSet};\nuse super::solver::SolverCx;\nuse super:"
  },
  {
    "path": "rayon-demo/src/tsp/tour.rs",
    "chars": 1462,
    "preview": "use std::cmp::Ordering;\nuse std::sync::Arc;\n\nuse super::graph::{Node, NodeSet};\nuse super::solver::TourId;\nuse super::we"
  },
  {
    "path": "rayon-demo/src/tsp/weight.rs",
    "chars": 1360,
    "preview": "use std::ops::{Add, AddAssign, Sub, SubAssign};\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]\npub struc"
  },
  {
    "path": "rayon-demo/src/vec_collect.rs",
    "chars": 6452,
    "preview": "//! Some benchmarks stress-testing various ways to build a standard `Vec`.\n\nmod util {\n    use rayon::prelude::*;\n    us"
  },
  {
    "path": "src/array.rs",
    "chars": 2143,
    "preview": "//! Parallel iterator types for [arrays] (`[T; N]`)\n//!\n//! You will rarely need to interact with this module directly u"
  },
  {
    "path": "src/collections/binary_heap.rs",
    "chars": 2966,
    "preview": "//! This module contains the parallel iterator types for heaps\n//! (`BinaryHeap<T>`). You will rarely need to interact w"
  },
  {
    "path": "src/collections/btree_map.rs",
    "chars": 1473,
    "preview": "//! This module contains the parallel iterator types for B-Tree maps\n//! (`BTreeMap<K, V>`). You will rarely need to int"
  },
  {
    "path": "src/collections/btree_set.rs",
    "chars": 1051,
    "preview": "//! This module contains the parallel iterator types for B-Tree sets\n//! (`BTreeSet<T>`). You will rarely need to intera"
  },
  {
    "path": "src/collections/hash_map.rs",
    "chars": 2130,
    "preview": "//! This module contains the parallel iterator types for hash maps\n//! (`HashMap<K, V>`). You will rarely need to intera"
  },
  {
    "path": "src/collections/hash_set.rs",
    "chars": 1671,
    "preview": "//! This module contains the parallel iterator types for hash sets\n//! (`HashSet<T>`). You will rarely need to interact "
  },
  {
    "path": "src/collections/linked_list.rs",
    "chars": 1308,
    "preview": "//! This module contains the parallel iterator types for linked lists\n//! (`LinkedList<T>`). You will rarely need to int"
  },
  {
    "path": "src/collections/mod.rs",
    "chars": 2615,
    "preview": "//! Parallel iterator types for [standard collections]\n//!\n//! You will rarely need to interact with this module directl"
  },
  {
    "path": "src/collections/vec_deque.rs",
    "chars": 3949,
    "preview": "//! This module contains the parallel iterator types for double-ended queues\n//! (`VecDeque<T>`). You will rarely need t"
  },
  {
    "path": "src/compile_fail/cannot_collect_filtermap_data.rs",
    "chars": 332,
    "preview": "/*! ```compile_fail,E0599\n\nuse rayon::prelude::*;\n\n// zip requires data of exact size, but filter yields only bounded\n//"
  },
  {
    "path": "src/compile_fail/cannot_zip_filtered_data.rs",
    "chars": 330,
    "preview": "/*! ```compile_fail,E0277\n\nuse rayon::prelude::*;\n\n// zip requires data of exact size, but filter yields only bounded\n//"
  },
  {
    "path": "src/compile_fail/cell_par_iter.rs",
    "chars": 264,
    "preview": "/*! ```compile_fail,E0277\n\n// Check that we can't use the par-iter API to access contents of a `Cell`.\n\nuse rayon::prelu"
  },
  {
    "path": "src/compile_fail/mod.rs",
    "chars": 188,
    "preview": "// These modules contain `compile_fail` doc tests.\nmod cannot_collect_filtermap_data;\nmod cannot_zip_filtered_data;\nmod "
  },
  {
    "path": "src/compile_fail/must_use.rs",
    "chars": 3191,
    "preview": "// Check that we are flagged for ignoring `must_use` parallel adaptors.\n// (unfortunately there's no error code for `unu"
  },
  {
    "path": "src/compile_fail/no_send_par_iter.rs",
    "chars": 864,
    "preview": "// Check that `!Send` types fail early.\n\n/** ```compile_fail,E0277\n\nuse rayon::prelude::*;\nuse std::ptr::null;\n\n#[derive"
  },
  {
    "path": "src/compile_fail/rc_par_iter.rs",
    "chars": 325,
    "preview": "/*! ```compile_fail,E0599\n\n// Check that we can't use the par-iter API to access contents of an\n// `Rc`.\n\nuse rayon::pre"
  },
  {
    "path": "src/delegate.rs",
    "chars": 2995,
    "preview": "//! Macros for delegating newtype iterators to inner types.\n\n// Note: these place `impl` bounds at the end, as token gob"
  },
  {
    "path": "src/iter/blocks.rs",
    "chars": 3815,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nstruct BlocksCallback<S, C> {\n    sizes: S,\n    consumer: C,\n    len: usize,\n}\n\ni"
  },
  {
    "path": "src/iter/chain.rs",
    "chars": 6676,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse rayon_core::join;\nuse std::iter;\n\n/// `Chain` is an iterator that joins `b` af"
  },
  {
    "path": "src/iter/chunks.rs",
    "chars": 5163,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// `Chunks` is an iterator that groups elements of an underlying iterator.\n///\n/"
  },
  {
    "path": "src/iter/cloned.rs",
    "chars": 4830,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::iter;\n\n/// `Cloned` is an iterator that clones the elements of an underl"
  },
  {
    "path": "src/iter/collect/consumer.rs",
    "chars": 6129,
    "preview": "use super::super::plumbing::*;\nuse crate::SendPtr;\nuse std::marker::PhantomData;\nuse std::ptr;\n\npub(super) struct Collec"
  },
  {
    "path": "src/iter/collect/mod.rs",
    "chars": 4255,
    "preview": "use super::{IndexedParallelIterator, ParallelIterator};\n\nmod consumer;\nuse self::consumer::CollectConsumer;\nuse self::co"
  },
  {
    "path": "src/iter/collect/test.rs",
    "chars": 13488,
    "preview": "#![cfg(test)]\n#![allow(unused_assignments)]\n\n// These tests are primarily targeting \"abusive\" producers that will\n// try"
  },
  {
    "path": "src/iter/copied.rs",
    "chars": 4816,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::iter;\n\n/// `Copied` is an iterator that copies the elements of an underl"
  },
  {
    "path": "src/iter/empty.rs",
    "chars": 2223,
    "preview": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\nuse std::fmt;\nuse std::marker::PhantomData;\n\n/// Creates a parallel i"
  },
  {
    "path": "src/iter/enumerate.rs",
    "chars": 3343,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\nuse std::ops::Range;\n\n/// `Enumerate` is an iterator that returns t"
  },
  {
    "path": "src/iter/extend.rs",
    "chars": 15905,
    "preview": "use super::noop::NoopConsumer;\nuse super::plumbing::{Consumer, Folder, Reducer, UnindexedConsumer};\nuse super::{IntoPara"
  },
  {
    "path": "src/iter/filter.rs",
    "chars": 3374,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `Filter` takes a predicate `filter_op` and filt"
  },
  {
    "path": "src/iter/filter_map.rs",
    "chars": 3582,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `FilterMap` creates an iterator that uses `filt"
  },
  {
    "path": "src/iter/find.rs",
    "chars": 2727,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\npub(super) fn find<I, P>(pi: I, fi"
  },
  {
    "path": "src/iter/find_first_last/mod.rs",
    "chars": 7325,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::cell::Cell;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\n#[cfg(test)]"
  },
  {
    "path": "src/iter/find_first_last/test.rs",
    "chars": 3882,
    "preview": "use super::*;\n\n#[test]\nfn same_range_first_consumers_return_correct_answer() {\n    let find_op = |x: &i32| x % 2 == 0;\n "
  },
  {
    "path": "src/iter/flat_map.rs",
    "chars": 3826,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `FlatMap` maps each element to a parallel itera"
  },
  {
    "path": "src/iter/flat_map_iter.rs",
    "chars": 3619,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `FlatMapIter` maps each element to a serial ite"
  },
  {
    "path": "src/iter/flatten.rs",
    "chars": 3180,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// `Flatten` turns each element to a parallel iterator, then flattens these iter"
  },
  {
    "path": "src/iter/flatten_iter.rs",
    "chars": 2901,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// `FlattenIter` turns each element to a serial iterator, then flattens these it"
  },
  {
    "path": "src/iter/fold.rs",
    "chars": 6777,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\nimpl<I, ID, F> Fold<I, ID, F> {\n    pub(super) fn n"
  },
  {
    "path": "src/iter/fold_chunks.rs",
    "chars": 6077,
    "preview": "use std::fmt::{self, Debug};\n\nuse super::chunks::ChunkProducer;\nuse super::plumbing::*;\nuse super::*;\n\n/// `FoldChunks` "
  },
  {
    "path": "src/iter/fold_chunks_with.rs",
    "chars": 6063,
    "preview": "use std::fmt::{self, Debug};\n\nuse super::chunks::ChunkProducer;\nuse super::plumbing::*;\nuse super::*;\n\n/// `FoldChunksWi"
  },
  {
    "path": "src/iter/for_each.rs",
    "chars": 1416,
    "preview": "use super::noop::*;\nuse super::plumbing::*;\nuse super::ParallelIterator;\n\npub(super) fn for_each<I, F, T>(pi: I, op: &F)"
  },
  {
    "path": "src/iter/from_par_iter.rs",
    "chars": 7620,
    "preview": "use super::noop::NoopConsumer;\nuse super::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}"
  },
  {
    "path": "src/iter/inspect.rs",
    "chars": 5963,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\nuse std::iter;\n\n/// `Inspect` is an iterator that ca"
  },
  {
    "path": "src/iter/interleave.rs",
    "chars": 8741,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::iter::Fuse;\n\n/// `Interleave` is an iterator that interleaves elements of"
  },
  {
    "path": "src/iter/interleave_shortest.rs",
    "chars": 2129,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// `InterleaveShortest` is an iterator that works similarly to\n/// `Interleave`,"
  },
  {
    "path": "src/iter/intersperse.rs",
    "chars": 10118,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::cell::Cell;\nuse std::iter::{self, Fuse};\n\n/// `Intersperse` is an iterato"
  },
  {
    "path": "src/iter/len.rs",
    "chars": 5942,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// `MinLen` is an iterator that imposes a minimum length on iterator splits.\n///"
  },
  {
    "path": "src/iter/map.rs",
    "chars": 5832,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\nuse std::iter;\n\n/// `Map` is an iterator that transf"
  },
  {
    "path": "src/iter/map_with.rs",
    "chars": 13955,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `MapWith` is an iterator that transforms the el"
  },
  {
    "path": "src/iter/mod.rs",
    "chars": 121119,
    "preview": "//! Traits for writing parallel programs using an iterator-style interface\n//!\n//! You will rarely need to interact with"
  },
  {
    "path": "src/iter/multizip.rs",
    "chars": 8883,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// `MultiZip` is an iterator that zips up a tuple of parallel iterators to\n/// p"
  },
  {
    "path": "src/iter/noop.rs",
    "chars": 1074,
    "preview": "use super::plumbing::*;\n\npub(super) struct NoopConsumer;\n\nimpl<T> Consumer<T> for NoopConsumer {\n    type Folder = NoopC"
  },
  {
    "path": "src/iter/once.rs",
    "chars": 1679,
    "preview": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\n/// Creates a parallel iterator that produces an element exactly once"
  },
  {
    "path": "src/iter/panic_fuse.rs",
    "chars": 7581,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::thread;\n\n/// `PanicFuse` i"
  },
  {
    "path": "src/iter/par_bridge.rs",
    "chars": 5631,
    "preview": "#[cfg(not(feature = \"web_spin_lock\"))]\nuse std::sync::Mutex;\n\n#[cfg(feature = \"web_spin_lock\")]\nuse wasm_sync::Mutex;\n\nu"
  },
  {
    "path": "src/iter/plumbing/README.md",
    "chars": 13535,
    "preview": "# Parallel Iterators\n\nThese are some notes on the design of the parallel iterator traits.\nThis file does not describe ho"
  },
  {
    "path": "src/iter/plumbing/mod.rs",
    "chars": 18379,
    "preview": "//! Traits and functions used to implement parallel iteration.  These are\n//! low-level details -- users of parallel ite"
  },
  {
    "path": "src/iter/positions.rs",
    "chars": 3298,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `Positions` takes a predicate `predicate` and f"
  },
  {
    "path": "src/iter/product.rs",
    "chars": 2229,
    "preview": "use super::plumbing::*;\nuse super::ParallelIterator;\n\nuse std::iter::{self, Product};\nuse std::marker::PhantomData;\n\npub"
  },
  {
    "path": "src/iter/reduce.rs",
    "chars": 2315,
    "preview": "use super::plumbing::*;\nuse super::ParallelIterator;\n\npub(super) fn reduce<PI, R, ID, T>(pi: PI, identity: ID, reduce_op"
  },
  {
    "path": "src/iter/repeat.rs",
    "chars": 7677,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::num::NonZeroUsize;\nuse std::{fmt, iter, mem};\n\n/// Iterator adaptor for ["
  },
  {
    "path": "src/iter/rev.rs",
    "chars": 2660,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\n\n/// `Rev` is an iterator that produces elements in reverse order. "
  },
  {
    "path": "src/iter/skip.rs",
    "chars": 2358,
    "preview": "use super::noop::NoopConsumer;\nuse super::plumbing::*;\nuse super::*;\n\n/// `Skip` is an iterator that skips over the firs"
  },
  {
    "path": "src/iter/skip_any.rs",
    "chars": 3198,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\n/// `SkipAny` is an iterator that"
  },
  {
    "path": "src/iter/skip_any_while.rs",
    "chars": 3997,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::fmt;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n/// `SkipAnyWhile` i"
  },
  {
    "path": "src/iter/splitter.rs",
    "chars": 5484,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// The `split` function takes arbitrary data and a"
  },
  {
    "path": "src/iter/step_by.rs",
    "chars": 3225,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\n\n/// `StepBy` is an iterator that skips `n` elements between each y"
  },
  {
    "path": "src/iter/sum.rs",
    "chars": 2010,
    "preview": "use super::plumbing::*;\nuse super::ParallelIterator;\n\nuse std::iter::{self, Sum};\nuse std::marker::PhantomData;\n\npub(sup"
  },
  {
    "path": "src/iter/take.rs",
    "chars": 1927,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// `Take` is an iterator that iterates over the first `n` elements.\n/// This str"
  },
  {
    "path": "src/iter/take_any.rs",
    "chars": 3286,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\n/// `TakeAny` is an iterator that"
  },
  {
    "path": "src/iter/take_any_while.rs",
    "chars": 4059,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::fmt;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n/// `TakeAnyWhile` i"
  },
  {
    "path": "src/iter/test.rs",
    "chars": 65300,
    "preview": "use std::sync::atomic::{AtomicUsize, Ordering};\n\nuse super::*;\nuse crate::prelude::*;\nuse rayon_core::*;\n\nuse rand::dist"
  },
  {
    "path": "src/iter/try_fold.rs",
    "chars": 7107,
    "preview": "use super::plumbing::*;\nuse super::ParallelIterator;\nuse super::Try;\n\nuse std::fmt::{self, Debug};\nuse std::marker::Phan"
  },
  {
    "path": "src/iter/try_reduce.rs",
    "chars": 3244,
    "preview": "use super::plumbing::*;\nuse super::ParallelIterator;\nuse super::Try;\n\nuse std::ops::ControlFlow::{self, Break, Continue}"
  },
  {
    "path": "src/iter/try_reduce_with.rs",
    "chars": 3410,
    "preview": "use super::plumbing::*;\nuse super::ParallelIterator;\nuse super::Try;\n\nuse std::ops::ControlFlow::{self, Break, Continue}"
  },
  {
    "path": "src/iter/unzip.rs",
    "chars": 13564,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// This trait abstracts the different ways we can \"unzip\" one parallel\n/// itera"
  },
  {
    "path": "src/iter/update.rs",
    "chars": 7528,
    "preview": "use super::plumbing::*;\nuse super::*;\n\nuse std::fmt::{self, Debug};\n\n/// `Update` is an iterator that mutates the elemen"
  },
  {
    "path": "src/iter/walk_tree.rs",
    "chars": 13831,
    "preview": "use crate::iter::plumbing::{bridge_unindexed, Folder, UnindexedConsumer, UnindexedProducer};\nuse crate::prelude::*;\nuse "
  },
  {
    "path": "src/iter/while_some.rs",
    "chars": 3638,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n/// `WhileSome` is an iterator tha"
  },
  {
    "path": "src/iter/zip.rs",
    "chars": 3716,
    "preview": "use super::plumbing::*;\nuse super::*;\nuse std::iter;\n\n/// `Zip` is an iterator that zips up `a` and `b` into a single it"
  },
  {
    "path": "src/iter/zip_eq.rs",
    "chars": 1549,
    "preview": "use super::plumbing::*;\nuse super::*;\n\n/// An [`IndexedParallelIterator`] that iterates over two parallel iterators of e"
  },
  {
    "path": "src/lib.rs",
    "chars": 5711,
    "preview": "//! Rayon is a data-parallelism library that makes it easy to convert sequential\n//! computations into parallel.\n//!\n//!"
  },
  {
    "path": "src/math.rs",
    "chars": 882,
    "preview": "use std::ops::{Bound, Range, RangeBounds};\n\n/// Normalize arbitrary `RangeBounds` to a `Range`\npub(super) fn simplify_ra"
  },
  {
    "path": "src/option.rs",
    "chars": 4822,
    "preview": "//! Parallel iterator types for [options]\n//!\n//! You will rarely need to interact with this module directly unless you "
  },
  {
    "path": "src/par_either.rs",
    "chars": 1904,
    "preview": "use crate::iter::plumbing::*;\nuse crate::iter::Either::{Left, Right};\nuse crate::iter::*;\n\n/// `Either<L, R>` is a paral"
  },
  {
    "path": "src/prelude.rs",
    "chars": 744,
    "preview": "//! The rayon prelude imports the various `ParallelIterator` traits.\n//! The intention is that one can include `use rayo"
  },
  {
    "path": "src/private.rs",
    "chars": 886,
    "preview": "//! The public parts of this private module are used to create traits\n//! that cannot be implemented outside of our own "
  },
  {
    "path": "src/range.rs",
    "chars": 13350,
    "preview": "//! Parallel iterator types for [ranges],\n//! the type for values created by `a..b` expressions\n//!\n//! You will rarely "
  },
  {
    "path": "src/range_inclusive.rs",
    "chars": 11272,
    "preview": "//! Parallel iterator types for [inclusive ranges],\n//! the type for values created by `a..=b` expressions\n//!\n//! You w"
  },
  {
    "path": "src/result.rs",
    "chars": 3321,
    "preview": "//! Parallel iterator types for [results]\n//!\n//! You will rarely need to interact with this module directly unless you "
  },
  {
    "path": "src/slice/chunk_by.rs",
    "chars": 6653,
    "preview": "use crate::iter::plumbing::*;\nuse crate::iter::*;\nuse std::fmt;\nuse std::marker::PhantomData;\n\ntrait ChunkBySlice<T>: As"
  },
  {
    "path": "src/slice/chunks.rs",
    "chars": 10243,
    "preview": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\n/// Parallel iterator over immutable non-overlapping chunks of a slic"
  },
  {
    "path": "src/slice/mod.rs",
    "chars": 40722,
    "preview": "//! Parallel iterator types for [slices]\n//!\n//! You will rarely need to interact with this module directly unless you n"
  },
  {
    "path": "src/slice/rchunks.rs",
    "chars": 10392,
    "preview": "use crate::iter::plumbing::*;\nuse crate::iter::*;\n\n/// Parallel iterator over immutable non-overlapping chunks of a slic"
  },
  {
    "path": "src/slice/sort.rs",
    "chars": 65428,
    "preview": "//! **Parallel** Slice sorting\n//!\n//! This implementation is mostly copied from the `core::slice::sort` module, with mi"
  },
  {
    "path": "src/slice/test.rs",
    "chars": 7225,
    "preview": "#![cfg(test)]\n\nuse crate::prelude::*;\nuse rand::distr::Uniform;\nuse rand::seq::IndexedRandom;\nuse rand::{rng, Rng};\nuse "
  },
  {
    "path": "src/split_producer.rs",
    "chars": 4681,
    "preview": "//! Common splitter for strings and slices\n//!\n//! This module is private, so these items are effectively `pub(super)`\n\n"
  },
  {
    "path": "src/str.rs",
    "chars": 29572,
    "preview": "//! Parallel iterator types for [strings]\n//!\n//! You will rarely need to interact with this module directly unless you "
  }
]

// ... and 18 more files (download for full content)

About this extraction

This page contains the full source code of the rayon-rs/rayon GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 218 files (1.3 MB), approximately 355.2k tokens, and a symbol index with 3282 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!